Skip to content

Commit 900a26a

Browse files
committed
[clang] Template Specialization Resugaring - Template Type Alias
This implements an additional user of the resugaring transform: the pattern of template type aliases. For more details and discussion see: https://discourse.llvm.org/t/rfc-improving-diagnostics-with-template-specialization-resugaring/64294 Differential Revision: https://reviews.llvm.org/D137199
1 parent a010f37 commit 900a26a

File tree

9 files changed

+44
-31
lines changed

9 files changed

+44
-31
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11512,7 +11512,8 @@ class Sema final : public SemaBase {
1151211512

1151311513
void NoteAllFoundTemplates(TemplateName Name);
1151411514

11515-
QualType CheckTemplateIdType(TemplateName Template,
11515+
QualType CheckTemplateIdType(const NestedNameSpecifier *NNS,
11516+
TemplateName Template,
1151611517
SourceLocation TemplateLoc,
1151711518
TemplateArgumentListInfo &TemplateArgs);
1151811519

clang/lib/Sema/SemaCXXScopeSpec.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,8 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
907907

908908
// We were able to resolve the template name to an actual template.
909909
// Build an appropriate nested-name-specifier.
910-
QualType T = CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs);
910+
QualType T = CheckTemplateIdType(SS.getScopeRep(), Template, TemplateNameLoc,
911+
TemplateArgs);
911912
if (T.isNull())
912913
return true;
913914

clang/lib/Sema/SemaCoroutine.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD,
9090

9191
// Build the template-id.
9292
QualType CoroTrait =
93-
S.CheckTemplateIdType(TemplateName(CoroTraits), KwLoc, Args);
93+
S.CheckTemplateIdType(nullptr, TemplateName(CoroTraits), KwLoc, Args);
9494
if (CoroTrait.isNull())
9595
return QualType();
9696
if (S.RequireCompleteType(KwLoc, CoroTrait,
@@ -169,7 +169,7 @@ static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType,
169169

170170
// Build the template-id.
171171
QualType CoroHandleType =
172-
S.CheckTemplateIdType(TemplateName(CoroHandle), Loc, Args);
172+
S.CheckTemplateIdType(nullptr, TemplateName(CoroHandle), Loc, Args);
173173
if (CoroHandleType.isNull())
174174
return QualType();
175175
if (S.RequireCompleteType(Loc, CoroHandleType,

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,7 +1140,8 @@ static bool lookupStdTypeTraitMember(Sema &S, LookupResult &TraitMemberLookup,
11401140
}
11411141

11421142
// Build the template-id.
1143-
QualType TraitTy = S.CheckTemplateIdType(TemplateName(TraitTD), Loc, Args);
1143+
QualType TraitTy =
1144+
S.CheckTemplateIdType(nullptr, TemplateName(TraitTD), Loc, Args);
11441145
if (TraitTy.isNull())
11451146
return true;
11461147
if (!S.isCompleteType(Loc, TraitTy)) {
@@ -12162,7 +12163,8 @@ QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) {
1216212163
Context.getTrivialTypeSourceInfo(Element,
1216312164
Loc)));
1216412165

12165-
QualType T = CheckTemplateIdType(TemplateName(StdInitializerList), Loc, Args);
12166+
QualType T =
12167+
CheckTemplateIdType(nullptr, TemplateName(StdInitializerList), Loc, Args);
1216612168
if (T.isNull())
1216712169
return QualType();
1216812170

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3826,15 +3826,16 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) {
38263826
}
38273827
}
38283828

3829-
static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate,
3829+
static QualType builtinCommonTypeImpl(Sema &S, const NestedNameSpecifier *NNS,
3830+
TemplateName BaseTemplate,
38303831
SourceLocation TemplateLoc,
38313832
ArrayRef<TemplateArgument> Ts) {
38323833
auto lookUpCommonType = [&](TemplateArgument T1,
38333834
TemplateArgument T2) -> QualType {
38343835
// Don't bother looking for other specializations if both types are
38353836
// builtins - users aren't allowed to specialize for them
38363837
if (T1.getAsType()->isBuiltinType() && T2.getAsType()->isBuiltinType())
3837-
return builtinCommonTypeImpl(S, BaseTemplate, TemplateLoc, {T1, T2});
3838+
return builtinCommonTypeImpl(S, NNS, BaseTemplate, TemplateLoc, {T1, T2});
38383839

38393840
TemplateArgumentListInfo Args;
38403841
Args.addArgument(TemplateArgumentLoc(
@@ -3848,7 +3849,7 @@ static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate,
38483849
Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());
38493850

38503851
QualType BaseTemplateInst =
3851-
S.CheckTemplateIdType(BaseTemplate, TemplateLoc, Args);
3852+
S.CheckTemplateIdType(NNS, BaseTemplate, TemplateLoc, Args);
38523853

38533854
if (SFINAE.hasErrorOccurred())
38543855
return QualType();
@@ -3961,8 +3962,8 @@ static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate,
39613962
}
39623963

39633964
static QualType checkBuiltinTemplateIdType(
3964-
Sema &SemaRef, TemplateName Name, BuiltinTemplateDecl *BTD,
3965-
ArrayRef<TemplateArgument> SugaredConverted,
3965+
Sema &SemaRef, const NestedNameSpecifier *NNS, TemplateName Name,
3966+
BuiltinTemplateDecl *BTD, ArrayRef<TemplateArgument> SugaredConverted,
39663967
ArrayRef<TemplateArgument> CanonicalConverted, SourceLocation TemplateLoc,
39673968
TemplateArgumentListInfo &TemplateArgs) {
39683969
ASTContext &Context = SemaRef.getASTContext();
@@ -4014,7 +4015,7 @@ static QualType checkBuiltinTemplateIdType(
40144015
// The first template argument will be reused as the template decl that
40154016
// our synthetic template arguments will be applied to.
40164017
QualType Result =
4017-
SemaRef.CheckTemplateIdType(SugaredConverted[0].getAsTemplate(),
4018+
SemaRef.CheckTemplateIdType(NNS, SugaredConverted[0].getAsTemplate(),
40184019
TemplateLoc, SyntheticTemplateArgs);
40194020
return SemaRef.Context.getTemplateSpecializationType(
40204021
Name, TemplateArgs.arguments(), SugaredConverted, CanonicalConverted,
@@ -4064,14 +4065,16 @@ static QualType checkBuiltinTemplateIdType(
40644065
QualType HasNoTypeMember = SugaredConverted[2].getAsType();
40654066
ArrayRef<TemplateArgument> Ts = SugaredConverted[3].getPackAsArray();
40664067
QualType Result = HasNoTypeMember;
4067-
if (auto CT = builtinCommonTypeImpl(SemaRef, BaseTemplate, TemplateLoc, Ts);
4068+
if (auto CT =
4069+
builtinCommonTypeImpl(SemaRef, NNS, BaseTemplate, TemplateLoc, Ts);
40684070
!CT.isNull()) {
40694071
TemplateArgumentListInfo TAs;
40704072
TAs.addArgument(TemplateArgumentLoc(
40714073
TemplateArgument(CT), SemaRef.Context.getTrivialTypeSourceInfo(
40724074
CT, TemplateArgs[1].getLocation())));
40734075

4074-
Result = SemaRef.CheckTemplateIdType(HasTypeMember, TemplateLoc, TAs);
4076+
Result =
4077+
SemaRef.CheckTemplateIdType(NNS, HasTypeMember, TemplateLoc, TAs);
40754078
}
40764079
return SemaRef.Context.getTemplateSpecializationType(
40774080
Name, TemplateArgs.arguments(), SugaredConverted, CanonicalConverted,
@@ -4219,7 +4222,8 @@ Sema::findFailedBooleanCondition(Expr *Cond) {
42194222
return { FailedCond, Description };
42204223
}
42214224

4222-
QualType Sema::CheckTemplateIdType(TemplateName Name,
4225+
QualType Sema::CheckTemplateIdType(const NestedNameSpecifier *NNS,
4226+
TemplateName Name,
42234227
SourceLocation TemplateLoc,
42244228
TemplateArgumentListInfo &TemplateArgs) {
42254229
// FIXME: 'getUnderlying' loses SubstTemplateTemplateParm nodes from alias
@@ -4298,9 +4302,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
42984302
if (!AliasTemplate->getDeclContext()->isFileContext())
42994303
SavedContext.emplace(*this, AliasTemplate->getDeclContext());
43004304

4301-
CanonType =
4302-
SubstType(Pattern->getUnderlyingType(), TemplateArgLists,
4303-
AliasTemplate->getLocation(), AliasTemplate->getDeclName());
4305+
QualType T = resugar(NNS, Pattern->getUnderlyingType());
4306+
CanonType = SubstType(T, TemplateArgLists, AliasTemplate->getLocation(),
4307+
AliasTemplate->getDeclName());
43044308
if (CanonType.isNull()) {
43054309
// If this was enable_if and we failed to find the nested type
43064310
// within enable_if in a SFINAE context, dig out the specific
@@ -4337,9 +4341,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
43374341
return QualType();
43384342
}
43394343
} else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) {
4340-
return checkBuiltinTemplateIdType(*this, Name, BTD, CTAI.SugaredConverted,
4341-
CTAI.CanonicalConverted, TemplateLoc,
4342-
TemplateArgs);
4344+
return checkBuiltinTemplateIdType(
4345+
*this, NNS, Name, BTD, CTAI.SugaredConverted, CTAI.CanonicalConverted,
4346+
TemplateLoc, TemplateArgs);
43434347
} else if (Name.isDependent() ||
43444348
TemplateSpecializationType::anyDependentTemplateArguments(
43454349
TemplateArgs, CTAI.CanonicalConverted)) {
@@ -4582,7 +4586,8 @@ TypeResult Sema::ActOnTemplateIdType(
45824586
return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
45834587
}
45844588

4585-
QualType SpecTy = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs);
4589+
QualType SpecTy = CheckTemplateIdType(SS.getScopeRep(), Template,
4590+
TemplateIILoc, TemplateArgs);
45864591
if (SpecTy.isNull())
45874592
return true;
45884593

@@ -4663,7 +4668,8 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
46634668
Diag(TAT->getLocation(), diag::note_declared_at);
46644669
}
46654670

4666-
QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs);
4671+
QualType Result = CheckTemplateIdType(SS.getScopeRep(), Template, TemplateLoc,
4672+
TemplateArgs);
46674673
if (Result.isNull())
46684674
return TypeResult(true);
46694675

@@ -11444,7 +11450,8 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
1144411450
return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
1144511451
}
1144611452

11447-
QualType T = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs);
11453+
QualType T = CheckTemplateIdType(SS.getScopeRep(), Template, TemplateIILoc,
11454+
TemplateArgs);
1144811455
if (T.isNull())
1144911456
return true;
1145011457

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6817,7 +6817,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
68176817
Args.addArgument(
68186818
getTrivialTemplateArgumentLoc(UnpackedArg, QualType(), Loc));
68196819
}
6820-
QualType T = CheckTemplateIdType(TemplateName(TD), Loc, Args);
6820+
QualType T =
6821+
CheckTemplateIdType(/*NNS=*/nullptr, TemplateName(TD), Loc, Args);
68216822
// We may get a non-null type with errors, in which case
68226823
// `getAsCXXRecordDecl` will return `nullptr`. For instance, this
68236824
// happens when one of the template arguments is an invalid

clang/lib/Sema/TreeTransform.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17349,7 +17349,8 @@ QualType TreeTransform<Derived>::RebuildTemplateSpecializationType(
1734917349
TemplateName Template,
1735017350
SourceLocation TemplateNameLoc,
1735117351
TemplateArgumentListInfo &TemplateArgs) {
17352-
return SemaRef.CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs);
17352+
return SemaRef.CheckTemplateIdType(nullptr, Template, TemplateNameLoc,
17353+
TemplateArgs);
1735317354
}
1735417355

1735517356
template<typename Derived>

clang/test/AST/ast-dump-template-decls.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ using type2 = typename C<int>::type1<void>;
126126
// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'void' sugar class depth 0 index 0 U final
127127
// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'type1'
128128
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void'
129-
// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 T
129+
// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 T final
130130
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'C'
131131
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int'
132132
} // namespace PR55886
@@ -138,7 +138,7 @@ template <typename... T> struct D {
138138
};
139139
};
140140
template struct D<float, char>::bind<int, short>;
141-
// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[1-9]+}}:5, col:45> col:11 bound_type 'int (int (*)(float, int), int (*)(char, short))'
141+
// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:5, col:45> col:11 bound_type 'int (int (*)(float, int), int (*)(char, short))'
142142
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (int (*)(float, int), int (*)(char, short))' cdecl
143143
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (float, int)' cdecl
144144
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... T pack_index 1{{$}}

clang/test/Sema/Resugar/resugar-types.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ template <class E> struct foo {
8888
};
8989
using T1 = foo<Bar>::apply<char>;
9090
TEST_NOT(T1::type1);
91-
TEST_NOT(T1::type2); // FIXME: Needs resugaring on the pattern of template type aliases.
91+
TEST(T1::type2);
9292

9393
using T2 = foo<int>::apply<Bar>;
9494
TEST(T2::type1);
@@ -106,7 +106,7 @@ template <typename... Cs> struct foo {
106106
};
107107
using T1 = foo<Bar>::bind<char>;
108108
TEST_NOT(T1::type1);
109-
TEST_NOT(T1::type2); // FIXME: Needs resugaring on the pattern of template type aliases.
109+
TEST(T1::type2);
110110

111111
using T2 = foo<int>::bind<Bar>;
112112
TEST(T2::type1);
@@ -148,7 +148,7 @@ template <typename... Ts> using Z = Y<Ts...>;
148148

149149
using T1 = typename foo<Z, Bar>::template bind<int>;
150150
TEST_NOT(typename T1::type1);
151-
TEST_NOT(typename T1::type2); // FIXME: Needs resugaring on the pattern of template type aliases.
151+
TEST(typename T1::type2);
152152

153153
using T2 = typename foo<Z, int>::template bind<Bar>;
154154
TEST(typename T2::type1);

0 commit comments

Comments
 (0)