summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2009-07-04 11:39:00 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2009-07-04 11:39:00 +0000
commit4f4d7b5d8e5fd921a407f9e00fed793c6ac1c1fc (patch)
treeb2a2569d7dce237da76a6092c5b07c8420fe18c7 /clang/lib
parent108f89cbfa19f59711d4c559a173fdf4e2e57291 (diff)
downloadbcm5719-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.h4
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp6
-rw-r--r--clang/lib/Sema/SemaType.cpp47
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) {
OpenPOWER on IntegriCloud