diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 157d42c09cfcd8..91c83564b567e8 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -12963,14 +12963,15 @@ NamedDecl *Sema::BuildUsingDeclaration( return nullptr; } - DeclContext *LookupContext = computeDeclContext(SS); NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); - if (!LookupContext || EllipsisLoc.isValid()) { - NamedDecl *D; + DeclContext *LookupContext = computeDeclContext(SS); + + auto BuildDependent = [&] { + NamedDecl *D = nullptr; // Dependent scope, or an unexpanded pack if (!LookupContext && CheckUsingDeclQualifier(UsingLoc, HasTypenameKeyword, SS, NameInfo, IdentLoc)) - return nullptr; + return D; if (HasTypenameKeyword) { // FIXME: not all declaration name kinds are legal here @@ -12987,7 +12988,7 @@ NamedDecl *Sema::BuildUsingDeclaration( CurContext->addDecl(D); ProcessDeclAttributeList(S, D, AttrList); return D; - } + }; auto Build = [&](bool Invalid) { UsingDecl *UD = @@ -13002,6 +13003,9 @@ NamedDecl *Sema::BuildUsingDeclaration( auto BuildInvalid = [&]{ return Build(true); }; auto BuildValid = [&]{ return Build(false); }; + if (!LookupContext || EllipsisLoc.isValid()) + return BuildDependent(); + if (RequireCompleteDeclContext(SS, LookupContext)) return BuildInvalid(); @@ -13024,6 +13028,9 @@ NamedDecl *Sema::BuildUsingDeclaration( LookupQualifiedName(R, LookupContext); + if (R.wasNotFoundInCurrentInstantiation()) + return BuildDependent(); + // Validate the context, now we have a lookup if (CheckUsingDeclQualifier(UsingLoc, HasTypenameKeyword, SS, NameInfo, IdentLoc, &R)) diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp index be07ab0a48b33e..2a6bebb27bbeb9 100644 --- a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp @@ -137,17 +137,16 @@ namespace InhCtor { int n = b.T(); // expected-error {{'T' is a protected member of 'InhCtor::A'}} // expected-note@-15 {{declared protected here}} - // FIXME: EDG and GCC reject this too, but it's not clear why it would be - // ill-formed. template struct S : T { - struct U : S { // expected-note 6{{candidate}} + // FIXME: S is incomplete here and we should diagnose this! + struct U : S { using S::S; }; using T::T; }; - S::U ua(0); // expected-error {{no match}} - S::U ub(0); // expected-error {{no match}} + S::U ua(0); + S::U ub(0); template struct X : T { diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp index 43053c18c50766..d5824d251c2a59 100644 --- a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp +++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp @@ -484,6 +484,18 @@ namespace N3 { template struct E; // expected-note {{in instantiation of template class 'N3::E' requested here}} + template + struct F { + F& operator=(T); + struct G; + }; + + template + struct F::G : F { + using F::operator=; + }; + + template struct F; } // namespace N3 namespace N4 {