diff options
| author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2009-07-04 11:39:00 +0000 | 
|---|---|---|
| committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2009-07-04 11:39:00 +0000 | 
| commit | 4f4d7b5d8e5fd921a407f9e00fed793c6ac1c1fc (patch) | |
| tree | b2a2569d7dce237da76a6092c5b07c8420fe18c7 /clang/lib | |
| parent | 108f89cbfa19f59711d4c559a173fdf4e2e57291 (diff) | |
| download | bcm5719-llvm-4f4d7b5d8e5fd921a407f9e00fed793c6ac1c1fc.tar.gz bcm5719-llvm-4f4d7b5d8e5fd921a407f9e00fed793c6ac1c1fc.zip | |
Catch function redeclarations with incompatible exception specifications.
llvm-svn: 74787
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Sema/Sema.h | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaType.cpp | 47 | 
3 files changed, 57 insertions, 0 deletions
| diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 72fb0a82a02..7af80c0261e 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -86,6 +86,7 @@ namespace clang {    class ObjCMethodDecl;    class ObjCPropertyDecl;    class ObjCContainerDecl; +  class FunctionProtoType;    class BasePaths;    struct MemberLookupCriteria;    class CXXTemporary; @@ -394,6 +395,9 @@ public:    DeclarationName GetNameForDeclarator(Declarator &D);    bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range);    bool CheckDistantExceptionSpec(QualType T); +  bool CheckEquivalentExceptionSpec( +      const FunctionProtoType *Old, SourceLocation OldLoc, +      const FunctionProtoType *New, SourceLocation NewLoc);    QualType ObjCGetTypeForMethodDefinition(DeclPtrTy D); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index d0357622620..75ceb191655 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -258,6 +258,12 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) {      }    } +  if (CheckEquivalentExceptionSpec( +          Old->getType()->getAsFunctionProtoType(), Old->getLocation(), +          New->getType()->getAsFunctionProtoType(), New->getLocation())) { +    Invalid = true; +  } +    return Invalid;  } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 7fa6d703c2a..3756df870c2 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -17,6 +17,7 @@  #include "clang/AST/DeclTemplate.h"  #include "clang/AST/Expr.h"  #include "clang/Parse/DeclSpec.h" +#include "llvm/ADT/SmallPtrSet.h"  using namespace clang;  /// \brief Perform adjustment on the parameter type of a function. @@ -1063,6 +1064,13 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip,        break;      }      case DeclaratorChunk::MemberPointer: +      // Verify that we're not building a pointer to pointer to function with +      // exception specification. +      if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) { +        Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec); +        D.setInvalidType(true); +        // Build the type anyway. +      }        // The scope spec must refer to a class, or be dependent.        QualType ClsType;        if (isDependentScopeSpecifier(DeclType.Mem.Scope())) { @@ -1187,6 +1195,45 @@ bool Sema::CheckDistantExceptionSpec(QualType T) {    return FnT->hasExceptionSpec();  } +/// CheckEquivalentExceptionSpec - Check if the two types have equivalent +/// exception specifications. Exception specifications are equivalent if +/// they allow exactly the same set of exception types. It does not matter how +/// that is achieved. See C++ [except.spec]p2. +bool Sema::CheckEquivalentExceptionSpec( +    const FunctionProtoType *Old, SourceLocation OldLoc, +    const FunctionProtoType *New, SourceLocation NewLoc) { +  bool OldAny = !Old->hasExceptionSpec() || Old->hasAnyExceptionSpec(); +  bool NewAny = !New->hasExceptionSpec() || New->hasAnyExceptionSpec(); +  if (OldAny && NewAny) +    return false; +  if (OldAny || NewAny) { +    Diag(NewLoc, diag::err_mismatched_exception_spec); +    Diag(OldLoc, diag::note_previous_declaration); +    return true; +  } + +  bool Success = true; +  // Both have a definite exception spec. Collect the first set, then compare +  // to the second. +  llvm::SmallPtrSet<const Type*, 8> Types; +  for (FunctionProtoType::exception_iterator I = Old->exception_begin(), +       E = Old->exception_end(); I != E; ++I) +    Types.insert(Context.getCanonicalType(*I).getTypePtr()); + +  for (FunctionProtoType::exception_iterator I = New->exception_begin(), +       E = New->exception_end(); I != E && Success; ++I) +    Success = Types.erase(Context.getCanonicalType(*I).getTypePtr()); + +  Success = Success && Types.empty(); + +  if (Success) { +    return false; +  } +  Diag(NewLoc, diag::err_mismatched_exception_spec); +  Diag(OldLoc, diag::note_previous_declaration); +  return true; +} +  /// ObjCGetTypeForMethodDefinition - Builds the type for a method definition  /// declarator  QualType Sema::ObjCGetTypeForMethodDefinition(DeclPtrTy D) { | 

