[cfe-commits] r127596 - in /cfe/trunk: lib/Sema/SemaDecl.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaType.cpp test/CXX/except/except.spec/p15.cpp

Sebastian Redl sebastian.redl at getdesigned.at
Mon Mar 14 11:08:30 PDT 2011


Author: cornedbee
Date: Mon Mar 14 13:08:30 2011
New Revision: 127596

URL: http://llvm.org/viewvc/llvm-project?rev=127596&view=rev
Log:
Make deallocation functions implicitly noexcept in C++0x.

Added:
    cfe/trunk/test/CXX/except/except.spec/p15.cpp
Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaType.cpp

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=127596&r1=127595&r2=127596&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Mar 14 13:08:30 2011
@@ -3733,7 +3733,7 @@
       }
 
       bool isStatic = SC == SC_Static;
-    
+
       // [class.free]p1:
       // Any allocation function for a class T is a static member
       // (even if not explicitly declared static).
@@ -3746,7 +3746,7 @@
       if (Name.getCXXOverloadedOperator() == OO_Delete ||
           Name.getCXXOverloadedOperator() == OO_Array_Delete)
         isStatic = true;
-    
+
       // This is a C++ method declaration.
       NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC),
                                     D.getSourceRange().getBegin(),

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=127596&r1=127595&r2=127596&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Mar 14 13:08:30 2011
@@ -1404,11 +1404,18 @@
 /// DeclareGlobalNewDelete - Declare the global forms of operator new and
 /// delete. These are:
 /// @code
+///   // C++03:
 ///   void* operator new(std::size_t) throw(std::bad_alloc);
 ///   void* operator new[](std::size_t) throw(std::bad_alloc);
 ///   void operator delete(void *) throw();
 ///   void operator delete[](void *) throw();
+///   // C++0x:
+///   void* operator new(std::size_t);
+///   void* operator new[](std::size_t);
+///   void operator delete(void *);
+///   void operator delete[](void *);
 /// @endcode
+/// C++0x operator delete is implicitly noexcept.
 /// Note that the placement and nothrow forms of new are *not* implicitly
 /// declared. Their use requires including \<new\>.
 void Sema::DeclareGlobalNewDelete() {
@@ -1420,10 +1427,16 @@
   //   implicitly declared in global scope in each translation unit of a
   //   program
   //
+  //     C++03:
   //     void* operator new(std::size_t) throw(std::bad_alloc);
   //     void* operator new[](std::size_t) throw(std::bad_alloc);
   //     void  operator delete(void*) throw();
   //     void  operator delete[](void*) throw();
+  //     C++0x:
+  //     void* operator new(std::size_t);
+  //     void* operator new[](std::size_t);
+  //     void  operator delete(void*);
+  //     void  operator delete[](void*);
   //
   //   These implicit declarations introduce only the function names operator
   //   new, operator new[], operator delete, operator delete[].
@@ -1432,7 +1445,9 @@
   // "std" or "bad_alloc" as necessary to form the exception specification.
   // However, we do not make these implicit declarations visible to name
   // lookup.
-  if (!StdBadAlloc) {
+  // Note that the C++0x versions of operator delete are deallocation functions,
+  // and thus are implicitly noexcept.
+  if (!StdBadAlloc && !getLangOptions().CPlusPlus0x) {
     // The "std::bad_alloc" class has not yet been declared, so build it
     // implicitly.
     StdBadAlloc = CXXRecordDecl::Create(Context, TTK_Class,
@@ -1495,18 +1510,21 @@
   bool HasBadAllocExceptionSpec
     = (Name.getCXXOverloadedOperator() == OO_New ||
        Name.getCXXOverloadedOperator() == OO_Array_New);
-  if (HasBadAllocExceptionSpec) {
+  if (HasBadAllocExceptionSpec && !getLangOptions().CPlusPlus0x) {
     assert(StdBadAlloc && "Must have std::bad_alloc declared");
     BadAllocType = Context.getTypeDeclType(getStdBadAlloc());
   }
 
   FunctionProtoType::ExtProtoInfo EPI;
   if (HasBadAllocExceptionSpec) {
-    EPI.ExceptionSpecType = EST_Dynamic;
-    EPI.NumExceptions = 1;
-    EPI.Exceptions = &BadAllocType;
+    if (!getLangOptions().CPlusPlus0x) {
+      EPI.ExceptionSpecType = EST_Dynamic;
+      EPI.NumExceptions = 1;
+      EPI.Exceptions = &BadAllocType;
+    }
   } else {
-    EPI.ExceptionSpecType = EST_DynamicNone;
+    EPI.ExceptionSpecType = getLangOptions().CPlusPlus0x ?
+                                EST_BasicNoexcept : EST_DynamicNone;
   }
 
   QualType FnType = Context.getFunctionType(Return, &Argument, 1, EPI);

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=127596&r1=127595&r2=127596&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Mon Mar 14 13:08:30 2011
@@ -1494,9 +1494,19 @@
 
   TypeProcessingState state(*this, D);
 
+  // In C++0x, deallocation functions (normal and array operator delete)
+  // are implicitly noexcept.
+  bool ImplicitlyNoexcept = false;
+
   switch (D.getName().getKind()) {
-  case UnqualifiedId::IK_Identifier:
   case UnqualifiedId::IK_OperatorFunctionId:
+    if (getLangOptions().CPlusPlus0x) {
+      OverloadedOperatorKind OO = D.getName().OperatorFunctionId.Operator;
+      if (OO == OO_Delete || OO == OO_Array_Delete)
+        ImplicitlyNoexcept = true;
+    }
+    // Intentional fall-through.
+  case UnqualifiedId::IK_Identifier:
   case UnqualifiedId::IK_LiteralOperatorId:
   case UnqualifiedId::IK_TemplateId:
     T = ConvertDeclSpecToType(*this, state);
@@ -1917,6 +1927,10 @@
             else
               EPI.NoexceptExpr = NoexceptExpr;
           }
+        } else if (FTI.getExceptionSpecType() == EST_None &&
+                   ImplicitlyNoexcept && chunkIndex == 0) {
+          // Only the outermost chunk is marked noexcept, of course.
+          EPI.ExceptionSpecType = EST_BasicNoexcept;
         }
 
         T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(), EPI);

Added: cfe/trunk/test/CXX/except/except.spec/p15.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/except/except.spec/p15.cpp?rev=127596&view=auto
==============================================================================
--- cfe/trunk/test/CXX/except/except.spec/p15.cpp (added)
+++ cfe/trunk/test/CXX/except/except.spec/p15.cpp Mon Mar 14 13:08:30 2011
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -std=c++0x -fexceptions -fcxx-exceptions -fsyntax-only -verify %s
+
+// Deallocation functions are implicitly noexcept.
+// Thus, explicit specs aren't allowed to conflict.
+
+void f() {
+  // Force implicit declaration of delete.
+  delete new int;
+  delete[] new int[1];
+}
+
+void operator delete(void*) noexcept;
+void operator delete[](void*) noexcept;
+
+// Same goes for explicit declarations.
+void operator delete(void*, float);
+void operator delete(void*, float) noexcept;
+
+void operator delete[](void*, float);
+void operator delete[](void*, float) noexcept;
+
+// But explicit specs stay.
+void operator delete(void*, double) throw(int); // expected-note {{previous}}
+void operator delete(void*, double) noexcept; // expected-error {{does not match}}





More information about the cfe-commits mailing list