llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Mariya Podchishchaeva (Fznamznon) <details> <summary>Changes</summary> Current context set to where alias was met, not where it is declared caused incorrect access check in case alias referenced private members of the parent class. This is a recommit of 6b1aa31 with a slight modification in order to fix reported regression. Fixes https://github.com/llvm/llvm-project/issues/41693 --- Full diff: https://github.com/llvm/llvm-project/pull/75069.diff 6 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (+3) - (modified) clang/include/clang/Sema/Sema.h (+1-1) - (modified) clang/lib/Sema/SemaCXXScopeSpec.cpp (+20-4) - (modified) clang/lib/Sema/SemaTemplate.cpp (+13-3) - (modified) clang/test/CXX/temp/temp.decls/temp.alias/p3.cpp (+3-2) - (modified) clang/test/SemaCXX/alias-template.cpp (+65) ``````````diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b4b5352a306c1c..1d460ae8375e88 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -677,6 +677,9 @@ Bug Fixes in This Version (`#62157 <https://github.com/llvm/llvm-project/issues/62157>`_) and (`#64885 <https://github.com/llvm/llvm-project/issues/64885>`_) and (`#65568 <https://github.com/llvm/llvm-project/issues/65568>`_) +- Fixed false positive error emitted when templated alias inside a class + used private members of the same class. + Fixes (`#41693 <https://github.com/llvm/llvm-project/issues/41693>`_) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index f45e0a7d3d52d4..d8f4b01ee455f1 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -8738,7 +8738,7 @@ class Sema final { SourceLocation IILoc, bool DeducedTSTContext = true); - + bool RebuildingTypesInCurrentInstantiation = false; TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T, SourceLocation Loc, DeclarationName Name); diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 44a40215b90dfb..b3b19b7ed7ffff 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<TemplateSpecializationType>(Ty)) { + if (auto *Record = dyn_cast<CXXRecordDecl>(CurContext)) { + if (isa<ClassTemplatePartialSpecializationDecl>(Record) || + Record->getDescribedClassTemplate()) { + const Type *ICNT = Record->getTypeForDecl(); + QualType Injected = + cast<InjectedClassNameType>(ICNT)->getInjectedSpecializationType(); + + if (Ty == Injected->getCanonicalTypeInternal().getTypePtr()) + return Record; + } + } + } + if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) { CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl()); if (!Record->isDependentContext() || @@ -37,10 +51,12 @@ static CXXRecordDecl *getCurrentInstantiationOf(QualType T, return Record; return nullptr; - } else if (isa<InjectedClassNameType>(Ty)) - return cast<InjectedClassNameType>(Ty)->getDecl(); - else - return nullptr; + } + + if (auto *ICNT = dyn_cast<InjectedClassNameType>(Ty)) + return ICNT->getDecl(); + + 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 f10abeaba0d451..810a93f37d74e0 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -39,6 +39,7 @@ #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/SaveAndRestore.h" #include <iterator> #include <optional> @@ -3990,9 +3991,16 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, if (Inst.isInvalid()) return QualType(); - CanonType = SubstType(Pattern->getUnderlyingType(), - TemplateArgLists, AliasTemplate->getLocation(), - AliasTemplate->getDeclName()); + if (!RebuildingTypesInCurrentInstantiation) { + Sema::ContextRAII SavedContext(*this, Pattern->getDeclContext()); + CanonType = + SubstType(Pattern->getUnderlyingType(), TemplateArgLists, + AliasTemplate->getLocation(), AliasTemplate->getDeclName()); + } else { + 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 @@ -11392,6 +11400,8 @@ TypeSourceInfo *Sema::RebuildTypeInCurrentInstantiation(TypeSourceInfo *T, if (!T || !T->getType()->isInstantiationDependentType()) return T; + llvm::SaveAndRestore DisableContextSwitchForTypeAliases( + RebuildingTypesInCurrentInstantiation, true); CurrentInstantiationRebuilder Rebuilder(*this, Loc, Name); return Rebuilder.TransformType(T); } 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 2d46502e1d9b35..2b33a4ef566dad 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<class T> struct A; -template<class T> using B = typename A<T>::U; // expected-error {{no type named 'U' in 'A<T>'}} +template<class T> using B = typename A<T>::U; // expected-error {{no type named 'U' in 'A<short>'}} + // expected-note@-1 {{in instantiation of template class 'A<short>' requested here}} template<class T> struct A { typedef B<T> U; // expected-note {{in instantiation of template type alias 'B' requested here}} }; -B<short> b; +B<short> b; // expected-note {{in instantiation of template type alias 'B' requested here}} template<typename T> using U = int; diff --git a/clang/test/SemaCXX/alias-template.cpp b/clang/test/SemaCXX/alias-template.cpp index 5189405e23db56..dca63e15f5bb8a 100644 --- a/clang/test/SemaCXX/alias-template.cpp +++ b/clang/test/SemaCXX/alias-template.cpp @@ -192,3 +192,68 @@ int g = sfinae_me<int>(); // expected-error{{no matching function for call to 's namespace NullExceptionDecl { template<int... I> auto get = []() { try { } catch(...) {}; return I; }; // expected-error{{initializer contains unexpanded parameter pack 'I'}} } + +namespace GH41693 { +// No errors when a type alias defined in a class or a friend of a class +// accesses private members of the same class. +struct S { +private: + template <typename> static constexpr void Impl() {} + +public: + template <typename X> using U = decltype(Impl<X>()); +}; + +using X = S::U<void>; +struct Y { +private: + static constexpr int x=0; + + template <typename> + static constexpr int y=0; + + template <typename> + static constexpr int foo(); + +public: + template <typename U> + using bar1 = decltype(foo<U>()); + using bar2 = decltype(x); + template <typename U> + using bar3 = decltype(y<U>); +}; + + +using type1 = Y::bar1<float>; +using type2 = Y::bar2; +using type3 = Y::bar3<float>; + +struct theFriend{ + template<class T> + using theAlias = decltype(&T::i); +}; + +class theC{ + int i; + public: + friend struct theFriend; +}; + +int foo(){ + (void)sizeof(theFriend::theAlias<theC>); +} + +// Test case that regressed with the first iteration of the fix for GH41693. +template <typename T> class SP { + T* data; +}; + +template <typename T> class A { + static SP<A> foo(); +}; + +template<typename T> using TRet = SP<A<T>>; + +template<typename T> TRet<T> A<T>::foo() { return TRet<T>{};}; + +} `````````` </details> https://github.com/llvm/llvm-project/pull/75069 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits