]> granicus.if.org Git - clang/commitdiff
Disallow exception specifications on multi-level indirections.
authorSebastian Redl <sebastian.redl@getdesigned.at>
Fri, 29 May 2009 15:01:05 +0000 (15:01 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Fri, 29 May 2009 15:01:05 +0000 (15:01 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72571 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/Sema.h
lib/Sema/SemaType.cpp
test/SemaCXX/exception-spec.cpp [new file with mode: 0644]

index 39feda96916a4868f38fc8e1d6a8ceb79fbb3cab..ed64f8a3d18e2760f6953601ca5cf5ce611caa5a 100644 (file)
@@ -268,6 +268,11 @@ def err_deleted_non_function : Error<
 def err_deleted_decl_not_first : Error<
   "deleted definition must be first declaration">;
 
+// C++ exception specifications
+def err_distant_exception_spec : Error<
+  "exception specifications are not allowed beyond a single level "
+  "of indirection">;
+
 // C++ access checking
 def err_class_redeclared_with_different_access : Error<
   "%0 redeclared with '%1' access">;
index 75632d560ec802a02eaec91dcfa85a2220511364..6559ca4f8f3b4576b9588545efb7d8c46d55636f 100644 (file)
@@ -349,6 +349,7 @@ public:
   QualType GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip = 0,
                                 TagDecl **OwnedDecl = 0);
   DeclarationName GetNameForDeclarator(Declarator &D);
+  bool CheckDistantExceptionSpec(QualType T);
 
   QualType ObjCGetTypeForMethodDefinition(DeclPtrTy D);
 
index 83f9b60fd7f66878aa325a74a8453470e3a1fbe3..01b8aa4fd41c0002502d566a769803e31ca2b216 100644 (file)
@@ -682,14 +682,35 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip,
              .getQualifiedType(DeclType.Cls.TypeQuals));
       break;
     case DeclaratorChunk::Pointer:
+      // 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.
+      }
       T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name);
       break;
     case DeclaratorChunk::Reference:
+      // Verify that we're not building a reference 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.
+      }
       T = BuildReferenceType(T, DeclType.Ref.LValueRef,
                              DeclType.Ref.HasRestrict ? QualType::Restrict : 0,
                              DeclType.Loc, Name);
       break;
     case DeclaratorChunk::Array: {
+      // Verify that we're not building an array of pointers 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.
+      }
       DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
       Expr *ArraySize = static_cast<Expr*>(ATI.NumElts);
       ArrayType::ArraySizeModifier ASM;
@@ -834,6 +855,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.
       DeclContext *DC = computeDeclContext(DeclType.Mem.Scope());
       QualType ClsType;
@@ -925,6 +953,24 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip,
   return T;
 }
 
+/// CheckDistantExceptionSpec - Check if the given type is a pointer or pointer
+/// to member to a function with an exception specification. This means that
+/// it is invalid to add another level of indirection.
+bool Sema::CheckDistantExceptionSpec(QualType T) {
+  if (const PointerType *PT = T->getAsPointerType())
+    T = PT->getPointeeType();
+  else if (const MemberPointerType *PT = T->getAsMemberPointerType())
+    T = PT->getPointeeType();
+  else
+    return false;
+
+  const FunctionProtoType *FnT = T->getAsFunctionProtoType();
+  if (!FnT)
+    return false;
+
+  return FnT->hasExceptionSpec();
+}
+
 /// ObjCGetTypeForMethodDefinition - Builds the type for a method definition
 /// declarator
 QualType Sema::ObjCGetTypeForMethodDefinition(DeclPtrTy D) {
diff --git a/test/SemaCXX/exception-spec.cpp b/test/SemaCXX/exception-spec.cpp
new file mode 100644 (file)
index 0000000..d697e02
--- /dev/null
@@ -0,0 +1,25 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// Straight from the standard:
+// Plain function with spec
+void f() throw(int);
+// Pointer to function with spec
+void (*fp)() throw (int);
+// Function taking reference to function with spec
+void g(void pfa() throw(int));
+// Typedef for pointer to function with spec
+typedef int (*pf)() throw(int); // xpected-error spec-on-typedef
+
+// Some more:
+// Function returning function with spec
+void (*h())() throw(int);
+// Ultimate parser thrill: function with spec returning function with spec and
+// taking pointer to function with spec.
+// The actual function throws int, the return type double, the argument float.
+void (*i() throw(int))(void (*)() throw(float)) throw(double);
+// Pointer to pointer to function taking function with spec
+void (**k)(void pfa() throw(int)); // no-error
+// Pointer to pointer to function with spec
+void (**j)() throw(int); // expected-error {{not allowed beyond a single}}
+// Pointer to function returning pointer to pointer to function with spec
+void (**(*h())())() throw(int); // expected-error {{not allowed beyond a single}}