]> granicus.if.org Git - clang/commitdiff
Adjust type-trait evaluation to properly handle Using(Shadow)Decls
authorHal Finkel <hfinkel@anl.gov>
Sun, 27 Nov 2016 16:26:14 +0000 (16:26 +0000)
committerHal Finkel <hfinkel@anl.gov>
Sun, 27 Nov 2016 16:26:14 +0000 (16:26 +0000)
Since r274049, for an inheriting constructor declaration, the name of the using
declaration (and using shadow declaration comes from the using declaration) is
the name of a derived class, not the base class (line 8225-8232 of
lib/Sema/SemaDeclCXX.cpp in https://reviews.llvm.org/rL274049). Because of
this, name-based lookup performed inside Sema::LookupConstructors returns not
only CXXConstructorDecls but also Using(Shadow)Decls, which results assertion
failure reported in PR29087.

Patch by Taewook Oh, thanks!

Differential Revision: https://reviews.llvm.org/D23765

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@287999 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExprCXX.cpp
test/SemaCXX/cxx11-crashes.cpp

index 91cdb67f30379a369d1b618539691b221570d805..dfbbf01a515c07738a5774bd81b65168b1b2090a 100644 (file)
@@ -4416,9 +4416,12 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
         // A template constructor is never a copy constructor.
         // FIXME: However, it may actually be selected at the actual overload
         // resolution point.
-        if (isa<FunctionTemplateDecl>(ND))
+        if (isa<FunctionTemplateDecl>(ND->getUnderlyingDecl()))
           continue;
-        const CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(ND);
+        // UsingDecl itself is not a constructor
+        if (isa<UsingDecl>(ND))
+          continue;
+        auto *Constructor = cast<CXXConstructorDecl>(ND->getUnderlyingDecl());
         if (Constructor->isCopyConstructor(FoundTQs)) {
           FoundConstructor = true;
           const FunctionProtoType *CPT
@@ -4452,9 +4455,12 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
       bool FoundConstructor = false;
       for (const auto *ND : Self.LookupConstructors(RD)) {
         // FIXME: In C++0x, a constructor template can be a default constructor.
-        if (isa<FunctionTemplateDecl>(ND))
+        if (isa<FunctionTemplateDecl>(ND->getUnderlyingDecl()))
+          continue;
+        // UsingDecl itself is not a constructor
+        if (isa<UsingDecl>(ND))
           continue;
-        const CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(ND);
+        auto *Constructor = cast<CXXConstructorDecl>(ND->getUnderlyingDecl());
         if (Constructor->isDefaultConstructor()) {
           FoundConstructor = true;
           const FunctionProtoType *CPT
index 97c959454c354c651042b036b9e11e1b9b8a64c2..7c455eecd5fa3ff279a8401ca5c6ee0e4519247b 100644 (file)
@@ -91,3 +91,15 @@ void test(int some_number) {  // expected-note {{'some_number' declared here}}
   Foo(lambda);
 }
 }
+
+namespace pr29091 {
+  struct X{ X(const X &x); };
+  struct Y: X { using X::X; };
+  bool foo() { return __has_nothrow_constructor(Y); }
+  bool bar() { return __has_nothrow_copy(Y); }
+
+  struct A { template <typename T> A(); };
+  struct B : A { using A::A; };
+  bool baz() { return __has_nothrow_constructor(B); }
+  bool qux() { return __has_nothrow_copy(B); }
+}