Skip to content

Commit

Permalink
Adjust type-trait evaluation to properly handle Using(Shadow)Decls
Browse files Browse the repository at this point in the history
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

llvm-svn: 287999
  • Loading branch information
Hal Finkel committed Nov 27, 2016
1 parent dc2917b commit fec8345
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 4 deletions.
14 changes: 10 additions & 4 deletions clang/lib/Sema/SemaExprCXX.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions clang/test/SemaCXX/cxx11-crashes.cpp
Expand Up @@ -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); }
}

0 comments on commit fec8345

Please sign in to comment.