Skip to content

Commit 67a0981

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 4571fad commit 67a0981

File tree

9 files changed

+43
-32
lines changed

9 files changed

+43
-32
lines changed

clang/include/clang/Sema/Sema.h

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

1150911509
void NoteAllFoundTemplates(TemplateName Name);
1151011510

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

clang/lib/Sema/SemaCXXScopeSpec.cpp

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

911911
// We were able to resolve the template name to an actual template.
912912
// Build an appropriate nested-name-specifier.
913-
QualType T = CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs);
913+
QualType T = CheckTemplateIdType(SS.getScopeRep(), Template, TemplateNameLoc,
914+
TemplateArgs);
914915
if (T.isNull())
915916
return true;
916917

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,
@@ -170,7 +170,7 @@ static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType,
170170

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

clang/lib/Sema/SemaDeclCXX.cpp

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

11441144
// Build the template-id.
1145-
QualType TraitTy = S.CheckTemplateIdType(TemplateName(TraitTD), Loc, Args);
1145+
QualType TraitTy =
1146+
S.CheckTemplateIdType(nullptr, TemplateName(TraitTD), Loc, Args);
11461147
if (TraitTy.isNull())
11471148
return true;
11481149
if (!S.isCompleteType(Loc, TraitTy)) {
@@ -12185,7 +12186,8 @@ QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) {
1218512186
return Context.getElaboratedType(
1218612187
ElaboratedTypeKeyword::None,
1218712188
NestedNameSpecifier::Create(Context, nullptr, getStdNamespace()),
12188-
CheckTemplateIdType(TemplateName(StdInitializerList), Loc, Args));
12189+
CheckTemplateIdType(nullptr, TemplateName(StdInitializerList), Loc,
12190+
Args));
1218912191
}
1219012192

1219112193
bool Sema::isInitListConstructor(const FunctionDecl *Ctor) {

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3817,15 +3817,16 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) {
38173817
}
38183818
}
38193819

3820-
static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate,
3820+
static QualType builtinCommonTypeImpl(Sema &S, const NestedNameSpecifier *NNS,
3821+
TemplateName BaseTemplate,
38213822
SourceLocation TemplateLoc,
38223823
ArrayRef<TemplateArgument> Ts) {
38233824
auto lookUpCommonType = [&](TemplateArgument T1,
38243825
TemplateArgument T2) -> QualType {
38253826
// Don't bother looking for other specializations if both types are
38263827
// builtins - users aren't allowed to specialize for them
38273828
if (T1.getAsType()->isBuiltinType() && T2.getAsType()->isBuiltinType())
3828-
return builtinCommonTypeImpl(S, BaseTemplate, TemplateLoc, {T1, T2});
3829+
return builtinCommonTypeImpl(S, NNS, BaseTemplate, TemplateLoc, {T1, T2});
38293830

38303831
TemplateArgumentListInfo Args;
38313832
Args.addArgument(TemplateArgumentLoc(
@@ -3839,7 +3840,7 @@ static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate,
38393840
Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());
38403841

38413842
QualType BaseTemplateInst =
3842-
S.CheckTemplateIdType(BaseTemplate, TemplateLoc, Args);
3843+
S.CheckTemplateIdType(NNS, BaseTemplate, TemplateLoc, Args);
38433844

38443845
if (SFINAE.hasErrorOccurred())
38453846
return QualType();
@@ -3952,8 +3953,8 @@ static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate,
39523953
}
39533954

39543955
static QualType checkBuiltinTemplateIdType(
3955-
Sema &SemaRef, TemplateName Name, BuiltinTemplateDecl *BTD,
3956-
ArrayRef<TemplateArgument> SugaredConverted,
3956+
Sema &SemaRef, const NestedNameSpecifier *NNS, TemplateName Name,
3957+
BuiltinTemplateDecl *BTD, ArrayRef<TemplateArgument> SugaredConverted,
39573958
ArrayRef<TemplateArgument> CanonicalConverted, SourceLocation TemplateLoc,
39583959
TemplateArgumentListInfo &TemplateArgs) {
39593960
ASTContext &Context = SemaRef.getASTContext();
@@ -4005,7 +4006,7 @@ static QualType checkBuiltinTemplateIdType(
40054006
// The first template argument will be reused as the template decl that
40064007
// our synthetic template arguments will be applied to.
40074008
QualType Result =
4008-
SemaRef.CheckTemplateIdType(SugaredConverted[0].getAsTemplate(),
4009+
SemaRef.CheckTemplateIdType(NNS, SugaredConverted[0].getAsTemplate(),
40094010
TemplateLoc, SyntheticTemplateArgs);
40104011
return SemaRef.Context.getTemplateSpecializationType(
40114012
Name, TemplateArgs.arguments(), SugaredConverted, CanonicalConverted,
@@ -4055,14 +4056,16 @@ static QualType checkBuiltinTemplateIdType(
40554056
QualType HasNoTypeMember = SugaredConverted[2].getAsType();
40564057
ArrayRef<TemplateArgument> Ts = SugaredConverted[3].getPackAsArray();
40574058
QualType Result = HasNoTypeMember;
4058-
if (auto CT = builtinCommonTypeImpl(SemaRef, BaseTemplate, TemplateLoc, Ts);
4059+
if (auto CT =
4060+
builtinCommonTypeImpl(SemaRef, NNS, BaseTemplate, TemplateLoc, Ts);
40594061
!CT.isNull()) {
40604062
TemplateArgumentListInfo TAs;
40614063
TAs.addArgument(TemplateArgumentLoc(
40624064
TemplateArgument(CT), SemaRef.Context.getTrivialTypeSourceInfo(
40634065
CT, TemplateArgs[1].getLocation())));
40644066

4065-
Result = SemaRef.CheckTemplateIdType(HasTypeMember, TemplateLoc, TAs);
4067+
Result =
4068+
SemaRef.CheckTemplateIdType(NNS, HasTypeMember, TemplateLoc, TAs);
40664069
}
40674070
return SemaRef.Context.getTemplateSpecializationType(
40684071
Name, TemplateArgs.arguments(), SugaredConverted, CanonicalConverted,
@@ -4210,7 +4213,8 @@ Sema::findFailedBooleanCondition(Expr *Cond) {
42104213
return { FailedCond, Description };
42114214
}
42124215

4213-
QualType Sema::CheckTemplateIdType(TemplateName Name,
4216+
QualType Sema::CheckTemplateIdType(const NestedNameSpecifier *NNS,
4217+
TemplateName Name,
42144218
SourceLocation TemplateLoc,
42154219
TemplateArgumentListInfo &TemplateArgs) {
42164220
DependentTemplateName *DTN =
@@ -4294,9 +4298,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
42944298
if (!AliasTemplate->getDeclContext()->isFileContext())
42954299
SavedContext.emplace(*this, AliasTemplate->getDeclContext());
42964300

4297-
CanonType =
4298-
SubstType(Pattern->getUnderlyingType(), TemplateArgLists,
4299-
AliasTemplate->getLocation(), AliasTemplate->getDeclName());
4301+
QualType T = resugar(NNS, Pattern->getUnderlyingType());
4302+
CanonType = SubstType(T, TemplateArgLists, AliasTemplate->getLocation(),
4303+
AliasTemplate->getDeclName());
43004304
if (CanonType.isNull()) {
43014305
// If this was enable_if and we failed to find the nested type
43024306
// within enable_if in a SFINAE context, dig out the specific
@@ -4333,9 +4337,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
43334337
return QualType();
43344338
}
43354339
} else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) {
4336-
return checkBuiltinTemplateIdType(*this, Name, BTD, CTAI.SugaredConverted,
4337-
CTAI.CanonicalConverted, TemplateLoc,
4338-
TemplateArgs);
4340+
return checkBuiltinTemplateIdType(
4341+
*this, NNS, Name, BTD, CTAI.SugaredConverted, CTAI.CanonicalConverted,
4342+
TemplateLoc, TemplateArgs);
43394343
} else if (Name.isDependent() ||
43404344
TemplateSpecializationType::anyDependentTemplateArguments(
43414345
TemplateArgs, CTAI.CanonicalConverted)) {
@@ -4579,7 +4583,8 @@ TypeResult Sema::ActOnTemplateIdType(
45794583
return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
45804584
}
45814585

4582-
QualType SpecTy = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs);
4586+
QualType SpecTy = CheckTemplateIdType(SS.getScopeRep(), Template,
4587+
TemplateIILoc, TemplateArgs);
45834588
if (SpecTy.isNull())
45844589
return true;
45854590

@@ -4661,7 +4666,8 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
46614666
Diag(TAT->getLocation(), diag::note_declared_at);
46624667
}
46634668

4664-
QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs);
4669+
QualType Result = CheckTemplateIdType(SS.getScopeRep(), Template, TemplateLoc,
4670+
TemplateArgs);
46654671
if (Result.isNull())
46664672
return TypeResult(true);
46674673

@@ -11451,7 +11457,8 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
1145111457
return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
1145211458
}
1145311459

11454-
QualType T = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs);
11460+
QualType T = CheckTemplateIdType(SS.getScopeRep(), Template, TemplateIILoc,
11461+
TemplateArgs);
1145511462
if (T.isNull())
1145611463
return true;
1145711464

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
@@ -17330,7 +17330,8 @@ QualType TreeTransform<Derived>::RebuildTemplateSpecializationType(
1733017330
TemplateName Template,
1733117331
SourceLocation TemplateNameLoc,
1733217332
TemplateArgumentListInfo &TemplateArgs) {
17333-
return SemaRef.CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs);
17333+
return SemaRef.CheckTemplateIdType(nullptr, Template, TemplateNameLoc,
17334+
TemplateArgs);
1733417335
}
1733517336

1733617337
template<typename Derived>

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,6 @@ using type2 = typename C<int>::type1<void>;
124124
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void'
125125
// CHECK-NEXT: FunctionProtoType 0x{{[^ ]*}} 'void (int)' cdecl
126126
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void'
127-
// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 T
128-
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'C'
129127
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int'
130128
} // namespace PR55886
131129

@@ -136,7 +134,7 @@ template <typename... T> struct D {
136134
};
137135
};
138136
template struct D<float, char>::bind<int, short>;
139-
// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[1-9]+}}:5, col:45> col:11 bound_type 'int (int (*)(float, int), int (*)(char, short))'
137+
// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:5, col:45> col:11 bound_type 'int (int (*)(float, int), int (*)(char, short))'
140138
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (int (*)(float, int), int (*)(char, short))' cdecl
141139
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (float, int)' cdecl
142140
// 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)