[cfe-commits] r74787 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaType.cpp test/SemaCXX/exception-spec.cpp
Sebastian Redl
sebastian.redl at getdesigned.at
Sat Jul 4 04:39:02 PDT 2009
Author: cornedbee
Date: Sat Jul 4 06:39:00 2009
New Revision: 74787
URL: http://llvm.org/viewvc/llvm-project?rev=74787&view=rev
Log:
Catch function redeclarations with incompatible exception specifications.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/test/SemaCXX/exception-spec.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=74787&r1=74786&r2=74787&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Jul 4 06:39:00 2009
@@ -287,6 +287,8 @@
def err_incomplete_in_exception_spec : Error<
"%select{|pointer to |reference to }1incomplete type %0 is not allowed "
"in exception specification">;
+def err_mismatched_exception_spec : Error<
+ "exception specification in declaration does not match previous declaration">;
// C++ access checking
def err_class_redeclared_with_different_access : Error<
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=74787&r1=74786&r2=74787&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sat Jul 4 06:39:00 2009
@@ -86,6 +86,7 @@
class ObjCMethodDecl;
class ObjCPropertyDecl;
class ObjCContainerDecl;
+ class FunctionProtoType;
class BasePaths;
struct MemberLookupCriteria;
class CXXTemporary;
@@ -394,6 +395,9 @@
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);
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=74787&r1=74786&r2=74787&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Jul 4 06:39:00 2009
@@ -258,6 +258,12 @@
}
}
+ if (CheckEquivalentExceptionSpec(
+ Old->getType()->getAsFunctionProtoType(), Old->getLocation(),
+ New->getType()->getAsFunctionProtoType(), New->getLocation())) {
+ Invalid = true;
+ }
+
return Invalid;
}
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=74787&r1=74786&r2=74787&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Sat Jul 4 06:39:00 2009
@@ -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 @@
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 @@
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) {
Modified: cfe/trunk/test/SemaCXX/exception-spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/exception-spec.cpp?rev=74787&r1=74786&r2=74787&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/exception-spec.cpp (original)
+++ cfe/trunk/test/SemaCXX/exception-spec.cpp Sat Jul 4 06:39:00 2009
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -verify %s
+// RUN: clang-cc -fsyntax-only -verify -fms-extensions %s
// Straight from the standard:
// Plain function with spec
@@ -33,3 +33,31 @@
void ic3() throw(void*);
void ic4() throw(Incomplete*); // expected-error {{pointer to incomplete type 'struct Incomplete' is not allowed in exception specification}}
void ic5() throw(Incomplete&); // expected-error {{reference to incomplete type 'struct Incomplete' is not allowed in exception specification}}
+
+// Redeclarations
+typedef int INT;
+void r1() throw(int);
+void r1() throw(int);
+
+void r2() throw(int);
+void r2() throw(INT);
+
+// throw-any spec and no spec at all are semantically equivalent
+void r3();
+void r3() throw(...);
+
+void r4() throw(int, float);
+void r4() throw(float, int);
+
+void r5() throw(int); // expected-note {{previous declaration}}
+void r5(); // expected-error {{exception specification in declaration does not match}}
+
+void r6() throw(...); // expected-note {{previous declaration}}
+void r6() throw(int); // expected-error {{exception specification in declaration does not match}}
+
+void r7() throw(int); // expected-note {{previous declaration}}
+void r7() throw(float); // expected-error {{exception specification in declaration does not match}}
+
+// Top-level const doesn't matter.
+void r8() throw(int);
+void r8() throw(const int);
More information about the cfe-commits
mailing list