Skip to content

Commit dbf67ea

Browse files
authored
[clang] Substitute alias templates from correct context (#75069)
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 #41693
1 parent a110e99 commit dbf67ea

File tree

6 files changed

+103
-10
lines changed

6 files changed

+103
-10
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,9 @@ Bug Fixes in This Version
685685
(`#62157 <https://github.com/llvm/llvm-project/issues/62157>`_) and
686686
(`#64885 <https://github.com/llvm/llvm-project/issues/64885>`_) and
687687
(`#65568 <https://github.com/llvm/llvm-project/issues/65568>`_)
688+
- Fixed false positive error emitted when templated alias inside a class
689+
used private members of the same class.
690+
Fixes (`#41693 <https://github.com/llvm/llvm-project/issues/41693>`_)
688691

689692
Bug Fixes to Compiler Builtins
690693
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8737,7 +8737,7 @@ class Sema final {
87378737
SourceLocation IILoc,
87388738
bool DeducedTSTContext = true);
87398739

8740-
8740+
bool RebuildingTypesInCurrentInstantiation = false;
87418741
TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
87428742
SourceLocation Loc,
87438743
DeclarationName Name);

clang/lib/Sema/SemaCXXScopeSpec.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,33 @@ static CXXRecordDecl *getCurrentInstantiationOf(QualType T,
3030
return nullptr;
3131

3232
const Type *Ty = T->getCanonicalTypeInternal().getTypePtr();
33+
if (isa<TemplateSpecializationType>(Ty)) {
34+
if (auto *Record = dyn_cast<CXXRecordDecl>(CurContext)) {
35+
if (isa<ClassTemplatePartialSpecializationDecl>(Record) ||
36+
Record->getDescribedClassTemplate()) {
37+
const Type *ICNT = Record->getTypeForDecl();
38+
QualType Injected =
39+
cast<InjectedClassNameType>(ICNT)->getInjectedSpecializationType();
40+
41+
if (Ty == Injected->getCanonicalTypeInternal().getTypePtr())
42+
return Record;
43+
}
44+
}
45+
}
46+
3347
if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
3448
CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
3549
if (!Record->isDependentContext() ||
3650
Record->isCurrentInstantiation(CurContext))
3751
return Record;
3852

3953
return nullptr;
40-
} else if (isa<InjectedClassNameType>(Ty))
41-
return cast<InjectedClassNameType>(Ty)->getDecl();
42-
else
43-
return nullptr;
54+
}
55+
56+
if (auto *ICNT = dyn_cast<InjectedClassNameType>(Ty))
57+
return ICNT->getDecl();
58+
59+
return nullptr;
4460
}
4561

4662
/// Compute the DeclContext that is associated with the given type.

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "llvm/ADT/SmallBitVector.h"
4040
#include "llvm/ADT/SmallString.h"
4141
#include "llvm/ADT/StringExtras.h"
42+
#include "llvm/Support/SaveAndRestore.h"
4243

4344
#include <iterator>
4445
#include <optional>
@@ -3990,9 +3991,14 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
39903991
if (Inst.isInvalid())
39913992
return QualType();
39923993

3993-
CanonType = SubstType(Pattern->getUnderlyingType(),
3994-
TemplateArgLists, AliasTemplate->getLocation(),
3995-
AliasTemplate->getDeclName());
3994+
{
3995+
Sema::ContextRAII SavedContext(*this, Pattern->getDeclContext());
3996+
if (RebuildingTypesInCurrentInstantiation)
3997+
SavedContext.pop();
3998+
CanonType =
3999+
SubstType(Pattern->getUnderlyingType(), TemplateArgLists,
4000+
AliasTemplate->getLocation(), AliasTemplate->getDeclName());
4001+
}
39964002
if (CanonType.isNull()) {
39974003
// If this was enable_if and we failed to find the nested type
39984004
// within enable_if in a SFINAE context, dig out the specific
@@ -11392,6 +11398,8 @@ TypeSourceInfo *Sema::RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
1139211398
if (!T || !T->getType()->isInstantiationDependentType())
1139311399
return T;
1139411400

11401+
llvm::SaveAndRestore DisableContextSwitchForTypeAliases(
11402+
RebuildingTypesInCurrentInstantiation, true);
1139511403
CurrentInstantiationRebuilder Rebuilder(*this, Loc, Name);
1139611404
return Rebuilder.TransformType(T);
1139711405
}

clang/test/CXX/temp/temp.decls/temp.alias/p3.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
// The example given in the standard (this is rejected for other reasons anyway).
44
template<class T> struct A;
5-
template<class T> using B = typename A<T>::U; // expected-error {{no type named 'U' in 'A<T>'}}
5+
template<class T> using B = typename A<T>::U; // expected-error {{no type named 'U' in 'A<short>'}}
6+
// expected-note@-1 {{in instantiation of template class 'A<short>' requested here}}
67
template<class T> struct A {
78
typedef B<T> U; // expected-note {{in instantiation of template type alias 'B' requested here}}
89
};
9-
B<short> b;
10+
B<short> b; // expected-note {{in instantiation of template type alias 'B' requested here}}
1011

1112
template<typename T> using U = int;
1213

clang/test/SemaCXX/alias-template.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,68 @@ int g = sfinae_me<int>(); // expected-error{{no matching function for call to 's
192192
namespace NullExceptionDecl {
193193
template<int... I> auto get = []() { try { } catch(...) {}; return I; }; // expected-error{{initializer contains unexpanded parameter pack 'I'}}
194194
}
195+
196+
namespace GH41693 {
197+
// No errors when a type alias defined in a class or a friend of a class
198+
// accesses private members of the same class.
199+
struct S {
200+
private:
201+
template <typename> static constexpr void Impl() {}
202+
203+
public:
204+
template <typename X> using U = decltype(Impl<X>());
205+
};
206+
207+
using X = S::U<void>;
208+
struct Y {
209+
private:
210+
static constexpr int x=0;
211+
212+
template <typename>
213+
static constexpr int y=0;
214+
215+
template <typename>
216+
static constexpr int foo();
217+
218+
public:
219+
template <typename U>
220+
using bar1 = decltype(foo<U>());
221+
using bar2 = decltype(x);
222+
template <typename U>
223+
using bar3 = decltype(y<U>);
224+
};
225+
226+
227+
using type1 = Y::bar1<float>;
228+
using type2 = Y::bar2;
229+
using type3 = Y::bar3<float>;
230+
231+
struct theFriend{
232+
template<class T>
233+
using theAlias = decltype(&T::i);
234+
};
235+
236+
class theC{
237+
int i;
238+
public:
239+
friend struct theFriend;
240+
};
241+
242+
int foo(){
243+
(void)sizeof(theFriend::theAlias<theC>);
244+
}
245+
246+
// Test case that regressed with the first iteration of the fix for GH41693.
247+
template <typename T> class SP {
248+
T* data;
249+
};
250+
251+
template <typename T> class A {
252+
static SP<A> foo();
253+
};
254+
255+
template<typename T> using TRet = SP<A<T>>;
256+
257+
template<typename T> TRet<T> A<T>::foo() { return TRet<T>{};};
258+
259+
}

0 commit comments

Comments
 (0)