[cfe-commits] r127688 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaExceptionSpec.cpp test/CXX/except/except.spec/p3.cpp

Sebastian Redl sebastian.redl at getdesigned.at
Tue Mar 15 12:52:30 PDT 2011


Author: cornedbee
Date: Tue Mar 15 14:52:30 2011
New Revision: 127688

URL: http://llvm.org/viewvc/llvm-project?rev=127688&view=rev
Log:
Implement a hack to work around the changing exception specification of operator new in C++0x.

Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
    cfe/trunk/test/CXX/except/except.spec/p3.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=127688&r1=127687&r2=127688&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Mar 15 14:52:30 2011
@@ -758,7 +758,8 @@
       const FunctionProtoType *New, SourceLocation NewLoc,
       bool *MissingExceptionSpecification = 0,
       bool *MissingEmptyExceptionSpecification = 0,
-      bool AllowNoexceptAllMatchWithNoSpec = false);
+      bool AllowNoexceptAllMatchWithNoSpec = false,
+      bool IsOperatorNew = false);
   bool CheckExceptionSpecSubset(
       const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
       const FunctionProtoType *Superset, SourceLocation SuperLoc,

Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=127688&r1=127687&r2=127688&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Tue Mar 15 14:52:30 2011
@@ -96,6 +96,8 @@
 }
 
 bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
+  OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator();
+  bool IsOperatorNew = OO == OO_New || OO == OO_Array_New;
   bool MissingExceptionSpecification = false;
   bool MissingEmptyExceptionSpecification = false;
   if (!CheckEquivalentExceptionSpec(PDiag(diag::err_mismatched_exception_spec),
@@ -106,7 +108,8 @@
                                     New->getLocation(),
                                     &MissingExceptionSpecification,
                                     &MissingEmptyExceptionSpecification,
-                                    /*AllowNoexceptAllMatchWithNoSpec=*/true))
+                                    /*AllowNoexceptAllMatchWithNoSpec=*/true,
+                                    IsOperatorNew))
     return false;
 
   // The failure was something other than an empty exception
@@ -272,7 +275,8 @@
                                         SourceLocation NewLoc,
                                         bool *MissingExceptionSpecification,
                                         bool*MissingEmptyExceptionSpecification,
-                                        bool AllowNoexceptAllMatchWithNoSpec) {
+                                        bool AllowNoexceptAllMatchWithNoSpec,
+                                        bool IsOperatorNew) {
   // Just completely ignore this under -fno-exceptions.
   if (!getLangOptions().CXXExceptions)
     return false;
@@ -374,6 +378,38 @@
   if (OldNonThrowing && NewNonThrowing)
     return false;
 
+  // As a special compatibility feature, under C++0x we accept no spec and
+  // throw(std::bad_alloc) as equivalent for operator new and operator new[].
+  // This is because the implicit declaration changed, but old code would break.
+  if (getLangOptions().CPlusPlus0x && IsOperatorNew) {
+    const FunctionProtoType *WithExceptions = 0;
+    if (OldEST == EST_None && NewEST == EST_Dynamic)
+      WithExceptions = New;
+    else if (OldEST == EST_Dynamic && NewEST == EST_None)
+      WithExceptions = Old;
+    if (WithExceptions && WithExceptions->getNumExceptions() == 1) {
+      // One has no spec, the other throw(something). If that something is
+      // std::bad_alloc, all conditions are met.
+      QualType Exception = *WithExceptions->exception_begin();
+      if (CXXRecordDecl *ExRecord = Exception->getAsCXXRecordDecl()) {
+        IdentifierInfo* Name = ExRecord->getIdentifier();
+        if (Name && Name->getName() == "bad_alloc") {
+          // It's called bad_alloc, but is it in std?
+          DeclContext* DC = ExRecord->getDeclContext();
+          while (DC && !isa<NamespaceDecl>(DC))
+            DC = DC->getParent();
+          if (DC) {
+            NamespaceDecl* NS = cast<NamespaceDecl>(DC);
+            IdentifierInfo* NSName = NS->getIdentifier();
+            if (NSName && NSName->getName() == "std" &&
+                isa<TranslationUnitDecl>(NS->getParent()))
+              return false;
+          }
+        }
+      }
+    }
+  }
+
   // At this point, the only remaining valid case is two matching dynamic
   // specifications. We return here unless both specifications are dynamic.
   if (OldEST != EST_Dynamic || NewEST != EST_Dynamic) {

Modified: cfe/trunk/test/CXX/except/except.spec/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/except/except.spec/p3.cpp?rev=127688&r1=127687&r2=127688&view=diff
==============================================================================
--- cfe/trunk/test/CXX/except/except.spec/p3.cpp (original)
+++ cfe/trunk/test/CXX/except/except.spec/p3.cpp Tue Mar 15 14:52:30 2011
@@ -92,3 +92,14 @@
 
 extern void (*r21)() throw(int); // expected-note {{previous declaration}}
 extern void (*r21)() noexcept(true); // expected-error {{does not match}}
+
+
+// As a very special workaround, we allow operator new to match no spec
+// with a throw(bad_alloc) spec, because C++0x makes an incompatible change
+// here.
+namespace std { class bad_alloc {}; }
+void* operator new(unsigned long) throw(std::bad_alloc);
+void* operator new(unsigned long);
+void* operator new[](unsigned long) throw(std::bad_alloc);
+void* operator new[](unsigned long);
+





More information about the cfe-commits mailing list