[clang] [clang] Substitute alias templates from correct context (PR #75069)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 11 08:41:54 PST 2023
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 at -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
More information about the cfe-commits
mailing list