diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 89ea2f0930cec..b3c7552f2efe6 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -658,6 +658,9 @@ Bug Fixes in This Version Fixes (`#64467 `_) - Clang's ``-Wchar-subscripts`` no longer warns on chars whose values are known non-negative constants. Fixes (`#18763 `_) +- Fixed false positive error emitted when templated alias inside a class + used private members of the same class. + Fixes (`#41693 `_) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 44a40215b90df..4bd96722a4b67 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -30,6 +30,20 @@ static CXXRecordDecl *getCurrentInstantiationOf(QualType T, return nullptr; const Type *Ty = T->getCanonicalTypeInternal().getTypePtr(); + if (isa(Ty)) { + if (auto *Record = dyn_cast(CurContext)) { + if (isa(Record) || + Record->getDescribedClassTemplate()) { + const Type *ICNT = Record->getTypeForDecl(); + QualType Injected = + cast(ICNT)->getInjectedSpecializationType(); + + if (Ty == Injected->getCanonicalTypeInternal().getTypePtr()) + return Record; + } + } + } + if (const RecordType *RecordTy = dyn_cast(Ty)) { CXXRecordDecl *Record = cast(RecordTy->getDecl()); if (!Record->isDependentContext() || @@ -37,10 +51,12 @@ static CXXRecordDecl *getCurrentInstantiationOf(QualType T, return Record; return nullptr; - } else if (isa(Ty)) + } + + if (isa(Ty)) return cast(Ty)->getDecl(); - else - return nullptr; + + return nullptr; } /// Compute the DeclContext that is associated with the given type. diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 09bbf14d39af5..a586014e0cb1b 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3990,9 +3990,16 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, if (Inst.isInvalid()) return QualType(); - CanonType = SubstType(Pattern->getUnderlyingType(), - TemplateArgLists, AliasTemplate->getLocation(), - AliasTemplate->getDeclName()); + { + bool ForLambdaCallOperator = false; + if (const auto *Rec = dyn_cast(Pattern->getDeclContext())) + ForLambdaCallOperator = Rec->isLambda(); + Sema::ContextRAII SavedContext(*this, Pattern->getDeclContext(), + !ForLambdaCallOperator); + CanonType = + SubstType(Pattern->getUnderlyingType(), TemplateArgLists, + AliasTemplate->getLocation(), AliasTemplate->getDeclName()); + } if (CanonType.isNull()) { // If this was enable_if and we failed to find the nested type // within enable_if in a SFINAE context, dig out the specific diff --git a/clang/test/CXX/temp/temp.decls/temp.alias/p3.cpp b/clang/test/CXX/temp/temp.decls/temp.alias/p3.cpp index 2d46502e1d9b3..2b33a4ef566da 100644 --- a/clang/test/CXX/temp/temp.decls/temp.alias/p3.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.alias/p3.cpp @@ -2,11 +2,12 @@ // The example given in the standard (this is rejected for other reasons anyway). template struct A; -template using B = typename A::U; // expected-error {{no type named 'U' in 'A'}} +template using B = typename A::U; // expected-error {{no type named 'U' in 'A'}} + // expected-note@-1 {{in instantiation of template class 'A' requested here}} template struct A { typedef B U; // expected-note {{in instantiation of template type alias 'B' requested here}} }; -B b; +B b; // expected-note {{in instantiation of template type alias 'B' requested here}} template using U = int; diff --git a/clang/test/SemaCXX/alias-template.cpp b/clang/test/SemaCXX/alias-template.cpp index 5189405e23db5..cd415c6cd4e9b 100644 --- a/clang/test/SemaCXX/alias-template.cpp +++ b/clang/test/SemaCXX/alias-template.cpp @@ -192,3 +192,53 @@ int g = sfinae_me(); // expected-error{{no matching function for call to 's namespace NullExceptionDecl { template auto get = []() { try { } catch(...) {}; return I; }; // expected-error{{initializer contains unexpanded parameter pack 'I'}} } + +namespace GH41693 { +struct S { +private: + template static constexpr void Impl() {} + +public: + template using U = decltype(Impl()); +}; + +using X = S::U; +struct Y { +private: + static constexpr int x=0; + + template + static constexpr int y=0; + + template + static constexpr int foo(); + +public: + template + using bar1 = decltype(foo()); + using bar2 = decltype(x); + template + using bar3 = decltype(y); +}; + + +using type1 = Y::bar1; +using type2 = Y::bar2; +using type3 = Y::bar3; + +struct theFriend{ + template + using theAlias = decltype(&T::i); +}; + +class theC{ + int i; + public: + friend struct theFriend; +}; + +int foo(){ + (void)sizeof(theFriend::theAlias); +} + +}