[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