r199618 - Fix nothrow trait with multiple default constructors

Alp Toker alp at nuanti.com
Sun Jan 19 16:23:47 PST 2014


Author: alp
Date: Sun Jan 19 18:23:47 2014
New Revision: 199618

URL: http://llvm.org/viewvc/llvm-project?rev=199618&view=rev
Log:
Fix nothrow trait with multiple default constructors

Check all default ctors, not just the first one we see. This brings
__has_nothrow_constructor() in line with the other unary type traits.

A C++ class can have multiple default constructors but clang was only checking
the first one written, presumably due to ambiguity in the GNU specification.

MSVC has the same bug, while g++ has the correct implementation which we now
match.

Modified:
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/SemaCXX/type-traits.cpp

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=199618&r1=199617&r2=199618&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sun Jan 19 18:23:47 2014
@@ -3516,7 +3516,7 @@ static bool EvaluateUnaryTypeTrait(Sema
     }
     return false;
   case UTT_HasNothrowConstructor:
-    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+    // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html
     //   If __has_trivial_constructor (type) is true then the trait is
     //   true, else if type is a cv class or union type (or array
     //   thereof) with a default constructor that is known not to
@@ -3528,6 +3528,7 @@ static bool EvaluateUnaryTypeTrait(Sema
           !RD->hasNonTrivialDefaultConstructor())
         return true;
 
+      bool FoundConstructor = false;
       DeclContext::lookup_const_result R = Self.LookupConstructors(RD);
       for (DeclContext::lookup_const_iterator Con = R.begin(),
            ConEnd = R.end(); Con != ConEnd; ++Con) {
@@ -3536,16 +3537,19 @@ static bool EvaluateUnaryTypeTrait(Sema
           continue;
         CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
         if (Constructor->isDefaultConstructor()) {
+          FoundConstructor = true;
           const FunctionProtoType *CPT
               = Constructor->getType()->getAs<FunctionProtoType>();
           CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
           if (!CPT)
             return false;
-          // TODO: check whether evaluating default arguments can throw.
+          // FIXME: check whether evaluating default arguments can throw.
           // For now, we'll be conservative and assume that they can throw.
-          return CPT->isNothrow(Self.Context) && CPT->getNumArgs() == 0;
+          if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 0)
+            return false;
         }
       }
+      return FoundConstructor;
     }
     return false;
   case UTT_HasVirtualDestructor:

Modified: cfe/trunk/test/SemaCXX/type-traits.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=199618&r1=199617&r2=199618&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/type-traits.cpp (original)
+++ cfe/trunk/test/SemaCXX/type-traits.cpp Sun Jan 19 18:23:47 2014
@@ -112,6 +112,14 @@ struct HasNoThrowConstructor { HasNoThro
 struct HasNoThrowConstructorWithArgs {
   HasNoThrowConstructorWithArgs(HasCons i = HasCons(0)) throw();
 };
+struct HasMultipleDefaultConstructor1 {
+  HasMultipleDefaultConstructor1() throw();
+  HasMultipleDefaultConstructor1(int i = 0);
+};
+struct HasMultipleDefaultConstructor2 {
+  HasMultipleDefaultConstructor2(int i = 0);
+  HasMultipleDefaultConstructor2() throw();
+};
 
 struct HasNoThrowCopy { HasNoThrowCopy(const HasNoThrowCopy&) throw(); };
 struct HasMultipleCopy {
@@ -1562,6 +1570,9 @@ void has_nothrow_constructor() {
   { int arr[F(__has_nothrow_constructor(void))]; }
   { int arr[F(__has_nothrow_constructor(cvoid))]; }
   { int arr[F(__has_nothrow_constructor(HasTemplateCons))]; }
+
+  { int arr[F(__has_nothrow_constructor(HasMultipleDefaultConstructor1))]; }
+  { int arr[F(__has_nothrow_constructor(HasMultipleDefaultConstructor2))]; }
 }
 
 void has_virtual_destructor() {





More information about the cfe-commits mailing list