[cfe-commits] r83710 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaType.cpp test/SemaCXX/exception-spec.cpp

Sebastian Redl sebastian.redl at getdesigned.at
Sat Oct 10 05:04:11 PDT 2009


Author: cornedbee
Date: Sat Oct 10 07:04:10 2009
New Revision: 83710

URL: http://llvm.org/viewvc/llvm-project?rev=83710&view=rev
Log:
Implement the core checking for compatible exception specifications in assignment and initialization.

The exception specification of the assignee must be the same or a subset of the target. In addition, exception specifications on arguments and return types must be equivalent, but this is not implemented yet.
This currently produces two diagnostics for every invalid assignment/initialization, due to the diagnostic produced outside PerformImplicitConversion, e.g. in CheckSingleInitializer. I don't know how to suppress this; in any case I think it is the wrong place for a diagnostic, since there are other diagnostics produced inside the function. So I'm leaving it as it is for the moment.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.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=83710&r1=83709&r2=83710&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Oct 10 07:04:10 2009
@@ -363,6 +363,8 @@
 def err_override_exception_spec : Error<
   "exception specification of overriding function is more lax than "
   "base version">;
+def err_incompatible_exception_specs : Error<
+  "target exception specification is not superset of source">;
 
 // 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=83710&r1=83709&r2=83710&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sat Oct 10 07:04:10 2009
@@ -3519,6 +3519,8 @@
 
   bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType);
 
+  bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType);
+
   bool PerformImplicitConversion(Expr *&From, QualType ToType,
                                  const char *Flavor,
                                  bool AllowExplicit = false,

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=83710&r1=83709&r2=83710&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Oct 10 07:04:10 2009
@@ -3630,6 +3630,8 @@
       CastExpr::CastKind CK = CastExpr::CK_NoOp;
       if (DerivedToBase)
         CK = CastExpr::CK_DerivedToBase;
+      else if(CheckExceptionSpecCompatibility(Init, T1))
+        return true;
       ImpCastExprToType(Init, T1, CK, /*isLvalue=*/true);
     }
   }
@@ -3703,7 +3705,9 @@
                                cast<CXXMethodDecl>(Best->Function), 
                                Owned(Init));
         Init = InitConversion.takeAs<Expr>();
-                                    
+
+        if (CheckExceptionSpecCompatibility(Init, T1))
+          return true;
         ImpCastExprToType(Init, T1, CastExpr::CK_UserDefinedConversion, 
                           /*isLvalue=*/true);
       }
@@ -3792,6 +3796,8 @@
       CastExpr::CastKind CK = CastExpr::CK_NoOp;
       if (DerivedToBase)
         CK = CastExpr::CK_DerivedToBase;
+      else if(CheckExceptionSpecCompatibility(Init, T1))
+        return true;
       ImpCastExprToType(Init, T1, CK, /*isLvalue=*/false);
     }
     return false;

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=83710&r1=83709&r2=83710&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sat Oct 10 07:04:10 2009
@@ -1197,7 +1197,11 @@
   // Perform the second implicit conversion
   switch (SCS.Second) {
   case ICK_Identity:
-    // Nothing to do.
+    // If both sides are functions (or pointers/references to them), there could
+    // be incompatible exception declarations.
+    if (CheckExceptionSpecCompatibility(From, ToType))
+      return true;
+    // Nothing else to do.
     break;
 
   case ICK_Integral_Promotion:
@@ -1235,6 +1239,8 @@
     CastExpr::CastKind Kind = CastExpr::CK_Unknown;
     if (CheckMemberPointerConversion(From, ToType, Kind))
       return true;
+    if (CheckExceptionSpecCompatibility(From, ToType))
+      return true;
     ImpCastExprToType(From, ToType, Kind);
     break;
   }
@@ -1269,6 +1275,38 @@
   return false;
 }
 
+bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType)
+{
+  // First we check for applicability.
+  // Target type must be a function, function pointer or function reference.
+  if (const PointerType *PtrTy = ToType->getAs<PointerType>())
+    ToType = PtrTy->getPointeeType();
+  else if (const ReferenceType *RefTy = ToType->getAs<ReferenceType>())
+    ToType = RefTy->getPointeeType();
+
+  const FunctionProtoType *ToFunc = ToType->getAs<FunctionProtoType>();
+  if (!ToFunc)
+    return false;
+
+  // SourceType must be a function or function pointer.
+  // References are treated as functions.
+  QualType FromType = From->getType();
+  if (const PointerType *PtrTy = FromType->getAs<PointerType>())
+    FromType = PtrTy->getPointeeType();
+
+  const FunctionProtoType *FromFunc = FromType->getAs<FunctionProtoType>();
+  if (!FromFunc)
+    return false;
+
+  // Now we've got the correct types on both sides, check their compatibility.
+  // This means that the source of the conversion can only throw a subset of
+  // the exceptions of the target, and any exception specs on arguments or
+  // return types must be equivalent.
+  return CheckExceptionSpecSubset(diag::err_incompatible_exception_specs,
+                                  0, ToFunc, From->getSourceRange().getBegin(),
+                                  FromFunc, SourceLocation());
+}
+
 Sema::OwningExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
                                                  SourceLocation KWLoc,
                                                  SourceLocation LParen,

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=83710&r1=83709&r2=83710&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Sat Oct 10 07:04:10 2009
@@ -1512,6 +1512,9 @@
   // FIXME: As usual, we could be more specific in our error messages, but
   // that better waits until we've got types with source locations.
 
+  if (!SubLoc.isValid())
+    SubLoc = SuperLoc;
+
   // If superset contains everything, we're done.
   if (!Superset->hasExceptionSpec() || Superset->hasAnyExceptionSpec())
     return false;
@@ -1519,7 +1522,8 @@
   // It does not. If the subset contains everything, we've failed.
   if (!Subset->hasExceptionSpec() || Subset->hasAnyExceptionSpec()) {
     Diag(SubLoc, DiagID);
-    Diag(SuperLoc, NoteID);
+    if (NoteID != 0)
+      Diag(SuperLoc, NoteID);
     return true;
   }
 
@@ -1584,7 +1588,8 @@
     }
     if (!Contained) {
       Diag(SubLoc, DiagID);
-      Diag(SuperLoc, NoteID);
+      if (NoteID != 0)
+        Diag(SuperLoc, NoteID);
       return true;
     }
   }

Modified: cfe/trunk/test/SemaCXX/exception-spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/exception-spec.cpp?rev=83710&r1=83709&r2=83710&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/exception-spec.cpp (original)
+++ cfe/trunk/test/SemaCXX/exception-spec.cpp Sat Oct 10 07:04:10 2009
@@ -134,25 +134,25 @@
 {
   // Assignment and initialization of function pointers.
   void (*t1)() throw() = &s1;    // valid
-  t1 = &s2;                      // invalid
-  t1 = &s3;                      // invalid
-  void (&t2)() throw() = s2;     // invalid
+  t1 = &s2;                      // expected-error {{not superset}} expected-error {{incompatible type}}
+  t1 = &s3;                      // expected-error {{not superset}} expected-error {{incompatible type}}
+  void (&t2)() throw() = s2;     // expected-error {{not superset}}
   void (*t3)() throw(int) = &s2; // valid
   void (*t4)() throw(A) = &s1;   // valid
   t4 = &s3;                      // valid
   t4 = &s4;                      // valid
-  t4 = &s5;                      // invalid
+  t4 = &s5;                      // expected-error {{not superset}} expected-error {{incompatible type}}
   void (*t5)() = &s1;            // valid
   t5 = &s2;                      // valid
   t5 = &s6;                      // valid
   t5 = &s7;                      // valid
-  t1 = t3;                       // invalid
+  t1 = t3;                       // expected-error {{not superset}} expected-error {{incompatible type}}
   t3 = t1;                       // valid
   void (*t6)() throw(B1);
-  t6 = t4;                       // invalid
+  t6 = t4;                       // expected-error {{not superset}} expected-error {{incompatible type}}
   t4 = t6;                       // valid
   t5 = t1;                       // valid
-  t1 = t5;                       // invalid
+  t1 = t5;                       // expected-error {{not superset}} expected-error {{incompatible type}}
 
   // return types and arguments must match exactly, no inheritance allowed
   void (*(*t7)())() throw(B1) = &s8;       // valid





More information about the cfe-commits mailing list