Skip to content

Commit 9d5d428

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 0793555 commit 9d5d428

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
@@ -11509,7 +11509,8 @@ class Sema final : public SemaBase {
1150911509

1151011510
void NoteAllFoundTemplates(TemplateName Name);
1151111511

11512-
QualType CheckTemplateIdType(TemplateName Template,
11512+
QualType CheckTemplateIdType(const NestedNameSpecifier *NNS,
11513+
TemplateName Template,
1151311514
SourceLocation TemplateLoc,
1151411515
TemplateArgumentListInfo &TemplateArgs);
1151511516

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)) {
@@ -12163,7 +12164,8 @@ QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) {
1216312164
Context.getTrivialTypeSourceInfo(Element,
1216412165
Loc)));
1216512166

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

clang/lib/Sema/SemaTemplate.cpp

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

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

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

38513852
QualType BaseTemplateInst =
3852-
S.CheckTemplateIdType(BaseTemplate, TemplateLoc, Args);
3853+
S.CheckTemplateIdType(NNS, BaseTemplate, TemplateLoc, Args);
38533854

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

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

4075-
Result = SemaRef.CheckTemplateIdType(HasTypeMember, TemplateLoc, TAs);
4077+
Result =
4078+
SemaRef.CheckTemplateIdType(NNS, HasTypeMember, TemplateLoc, TAs);
40764079
}
40774080
return SemaRef.Context.getTemplateSpecializationType(
40784081
Name, TemplateArgs.arguments(), SugaredConverted, CanonicalConverted,
@@ -4220,7 +4223,8 @@ Sema::findFailedBooleanCondition(Expr *Cond) {
42204223
return { FailedCond, Description };
42214224
}
42224225

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

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

4586-
QualType SpecTy = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs);
4590+
QualType SpecTy = CheckTemplateIdType(SS.getScopeRep(), Template,
4591+
TemplateIILoc, TemplateArgs);
45874592
if (SpecTy.isNull())
45884593
return true;
45894594

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

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

@@ -11446,7 +11452,8 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
1144611452
return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
1144711453
}
1144811454

11449-
QualType T = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs);
11455+
QualType T = CheckTemplateIdType(SS.getScopeRep(), Template, TemplateIILoc,
11456+
TemplateArgs);
1145011457
if (T.isNull())
1145111458
return true;
1145211459

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6816,7 +6816,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
68166816
Args.addArgument(
68176817
getTrivialTemplateArgumentLoc(UnpackedArg, QualType(), Loc));
68186818
}
6819-
QualType T = CheckTemplateIdType(TemplateName(TD), Loc, Args);
6819+
QualType T =
6820+
CheckTemplateIdType(/*NNS=*/nullptr, TemplateName(TD), Loc, Args);
68206821
// We may get a non-null type with errors, in which case
68216822
// `getAsCXXRecordDecl` will return `nullptr`. For instance, this
68226823
// 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
@@ -17347,7 +17347,8 @@ QualType TreeTransform<Derived>::RebuildTemplateSpecializationType(
1734717347
TemplateName Template,
1734817348
SourceLocation TemplateNameLoc,
1734917349
TemplateArgumentListInfo &TemplateArgs) {
17350-
return SemaRef.CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs);
17350+
return SemaRef.CheckTemplateIdType(nullptr, Template, TemplateNameLoc,
17351+
TemplateArgs);
1735117352
}
1735217353

1735317354
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)