-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang] Template Specialization Resugaring - Template Type Alias #132442
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: users/mizvekov/clang-resugar-typedecl
Are you sure you want to change the base?
[clang] Template Specialization Resugaring - Template Type Alias #132442
Conversation
@llvm/pr-subscribers-coroutines @llvm/pr-subscribers-clang Author: Matheus Izvekov (mizvekov) ChangesThis implements an additional user of the resugaring transform: the pattern of template type aliases. For more details and discussion see: Differential Revision: https://reviews.llvm.org/D137199 Full diff: https://github.com/llvm/llvm-project/pull/132442.diff 9 Files Affected:
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 047ba88511dac..d45fc14e7b3c4 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11508,7 +11508,8 @@ class Sema final : public SemaBase {
void NoteAllFoundTemplates(TemplateName Name);
- QualType CheckTemplateIdType(TemplateName Template,
+ QualType CheckTemplateIdType(const NestedNameSpecifier *NNS,
+ TemplateName Template,
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs);
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index e8fe1cdd7336a..fe39696a6c6b6 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -910,7 +910,8 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
// We were able to resolve the template name to an actual template.
// Build an appropriate nested-name-specifier.
- QualType T = CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs);
+ QualType T = CheckTemplateIdType(SS.getScopeRep(), Template, TemplateNameLoc,
+ TemplateArgs);
if (T.isNull())
return true;
diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index 88d849b27db07..8cca65edc84e3 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -90,7 +90,7 @@ static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD,
// Build the template-id.
QualType CoroTrait =
- S.CheckTemplateIdType(TemplateName(CoroTraits), KwLoc, Args);
+ S.CheckTemplateIdType(nullptr, TemplateName(CoroTraits), KwLoc, Args);
if (CoroTrait.isNull())
return QualType();
if (S.RequireCompleteType(KwLoc, CoroTrait,
@@ -170,7 +170,7 @@ static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType,
// Build the template-id.
QualType CoroHandleType =
- S.CheckTemplateIdType(TemplateName(CoroHandle), Loc, Args);
+ S.CheckTemplateIdType(nullptr, TemplateName(CoroHandle), Loc, Args);
if (CoroHandleType.isNull())
return QualType();
if (S.RequireCompleteType(Loc, CoroHandleType,
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 330afbfa2d19d..26a3f86a718c4 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1142,7 +1142,8 @@ static bool lookupStdTypeTraitMember(Sema &S, LookupResult &TraitMemberLookup,
}
// Build the template-id.
- QualType TraitTy = S.CheckTemplateIdType(TemplateName(TraitTD), Loc, Args);
+ QualType TraitTy =
+ S.CheckTemplateIdType(nullptr, TemplateName(TraitTD), Loc, Args);
if (TraitTy.isNull())
return true;
if (!S.isCompleteType(Loc, TraitTy)) {
@@ -12185,7 +12186,8 @@ QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) {
return Context.getElaboratedType(
ElaboratedTypeKeyword::None,
NestedNameSpecifier::Create(Context, nullptr, getStdNamespace()),
- CheckTemplateIdType(TemplateName(StdInitializerList), Loc, Args));
+ CheckTemplateIdType(nullptr, TemplateName(StdInitializerList), Loc,
+ Args));
}
bool Sema::isInitListConstructor(const FunctionDecl *Ctor) {
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 0b26f79ea3bfc..63a4dab9a41f3 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3817,7 +3817,8 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) {
}
}
-static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate,
+static QualType builtinCommonTypeImpl(Sema &S, const NestedNameSpecifier *NNS,
+ TemplateName BaseTemplate,
SourceLocation TemplateLoc,
ArrayRef<TemplateArgument> Ts) {
auto lookUpCommonType = [&](TemplateArgument T1,
@@ -3825,7 +3826,7 @@ static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate,
// Don't bother looking for other specializations if both types are
// builtins - users aren't allowed to specialize for them
if (T1.getAsType()->isBuiltinType() && T2.getAsType()->isBuiltinType())
- return builtinCommonTypeImpl(S, BaseTemplate, TemplateLoc, {T1, T2});
+ return builtinCommonTypeImpl(S, NNS, BaseTemplate, TemplateLoc, {T1, T2});
TemplateArgumentListInfo Args;
Args.addArgument(TemplateArgumentLoc(
@@ -3839,7 +3840,7 @@ static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate,
Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());
QualType BaseTemplateInst =
- S.CheckTemplateIdType(BaseTemplate, TemplateLoc, Args);
+ S.CheckTemplateIdType(NNS, BaseTemplate, TemplateLoc, Args);
if (SFINAE.hasErrorOccurred())
return QualType();
@@ -3952,8 +3953,8 @@ static QualType builtinCommonTypeImpl(Sema &S, TemplateName BaseTemplate,
}
static QualType checkBuiltinTemplateIdType(
- Sema &SemaRef, TemplateName Name, BuiltinTemplateDecl *BTD,
- ArrayRef<TemplateArgument> SugaredConverted,
+ Sema &SemaRef, const NestedNameSpecifier *NNS, TemplateName Name,
+ BuiltinTemplateDecl *BTD, ArrayRef<TemplateArgument> SugaredConverted,
ArrayRef<TemplateArgument> CanonicalConverted, SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs) {
ASTContext &Context = SemaRef.getASTContext();
@@ -4005,7 +4006,7 @@ static QualType checkBuiltinTemplateIdType(
// The first template argument will be reused as the template decl that
// our synthetic template arguments will be applied to.
QualType Result =
- SemaRef.CheckTemplateIdType(SugaredConverted[0].getAsTemplate(),
+ SemaRef.CheckTemplateIdType(NNS, SugaredConverted[0].getAsTemplate(),
TemplateLoc, SyntheticTemplateArgs);
return SemaRef.Context.getTemplateSpecializationType(
Name, TemplateArgs.arguments(), SugaredConverted, CanonicalConverted,
@@ -4055,14 +4056,16 @@ static QualType checkBuiltinTemplateIdType(
QualType HasNoTypeMember = SugaredConverted[2].getAsType();
ArrayRef<TemplateArgument> Ts = SugaredConverted[3].getPackAsArray();
QualType Result = HasNoTypeMember;
- if (auto CT = builtinCommonTypeImpl(SemaRef, BaseTemplate, TemplateLoc, Ts);
+ if (auto CT =
+ builtinCommonTypeImpl(SemaRef, NNS, BaseTemplate, TemplateLoc, Ts);
!CT.isNull()) {
TemplateArgumentListInfo TAs;
TAs.addArgument(TemplateArgumentLoc(
TemplateArgument(CT), SemaRef.Context.getTrivialTypeSourceInfo(
CT, TemplateArgs[1].getLocation())));
- Result = SemaRef.CheckTemplateIdType(HasTypeMember, TemplateLoc, TAs);
+ Result =
+ SemaRef.CheckTemplateIdType(NNS, HasTypeMember, TemplateLoc, TAs);
}
return SemaRef.Context.getTemplateSpecializationType(
Name, TemplateArgs.arguments(), SugaredConverted, CanonicalConverted,
@@ -4210,7 +4213,8 @@ Sema::findFailedBooleanCondition(Expr *Cond) {
return { FailedCond, Description };
}
-QualType Sema::CheckTemplateIdType(TemplateName Name,
+QualType Sema::CheckTemplateIdType(const NestedNameSpecifier *NNS,
+ TemplateName Name,
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs) {
DependentTemplateName *DTN =
@@ -4294,9 +4298,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
if (!AliasTemplate->getDeclContext()->isFileContext())
SavedContext.emplace(*this, AliasTemplate->getDeclContext());
- CanonType =
- SubstType(Pattern->getUnderlyingType(), TemplateArgLists,
- AliasTemplate->getLocation(), AliasTemplate->getDeclName());
+ QualType T = resugar(NNS, Pattern->getUnderlyingType());
+ CanonType = SubstType(T, 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
@@ -4333,9 +4337,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
return QualType();
}
} else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) {
- return checkBuiltinTemplateIdType(*this, Name, BTD, CTAI.SugaredConverted,
- CTAI.CanonicalConverted, TemplateLoc,
- TemplateArgs);
+ return checkBuiltinTemplateIdType(
+ *this, NNS, Name, BTD, CTAI.SugaredConverted, CTAI.CanonicalConverted,
+ TemplateLoc, TemplateArgs);
} else if (Name.isDependent() ||
TemplateSpecializationType::anyDependentTemplateArguments(
TemplateArgs, CTAI.CanonicalConverted)) {
@@ -4579,7 +4583,8 @@ TypeResult Sema::ActOnTemplateIdType(
return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
}
- QualType SpecTy = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs);
+ QualType SpecTy = CheckTemplateIdType(SS.getScopeRep(), Template,
+ TemplateIILoc, TemplateArgs);
if (SpecTy.isNull())
return true;
@@ -4661,7 +4666,8 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK,
Diag(TAT->getLocation(), diag::note_declared_at);
}
- QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs);
+ QualType Result = CheckTemplateIdType(SS.getScopeRep(), Template, TemplateLoc,
+ TemplateArgs);
if (Result.isNull())
return TypeResult(true);
@@ -11451,7 +11457,8 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc,
return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
}
- QualType T = CheckTemplateIdType(Template, TemplateIILoc, TemplateArgs);
+ QualType T = CheckTemplateIdType(SS.getScopeRep(), Template, TemplateIILoc,
+ TemplateArgs);
if (T.isNull())
return true;
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 9c1eb3f4c88b5..5846b19a5c57b 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -6816,7 +6816,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
Args.addArgument(
getTrivialTemplateArgumentLoc(UnpackedArg, QualType(), Loc));
}
- QualType T = CheckTemplateIdType(TemplateName(TD), Loc, Args);
+ QualType T =
+ CheckTemplateIdType(/*NNS=*/nullptr, TemplateName(TD), Loc, Args);
// We may get a non-null type with errors, in which case
// `getAsCXXRecordDecl` will return `nullptr`. For instance, this
// happens when one of the template arguments is an invalid
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 4ee943ea5597e..ffe944fc53558 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -17330,7 +17330,8 @@ QualType TreeTransform<Derived>::RebuildTemplateSpecializationType(
TemplateName Template,
SourceLocation TemplateNameLoc,
TemplateArgumentListInfo &TemplateArgs) {
- return SemaRef.CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs);
+ return SemaRef.CheckTemplateIdType(nullptr, Template, TemplateNameLoc,
+ TemplateArgs);
}
template<typename Derived>
diff --git a/clang/test/AST/ast-dump-template-decls.cpp b/clang/test/AST/ast-dump-template-decls.cpp
index 9f578e5afe561..8ffcaeb879ee9 100644
--- a/clang/test/AST/ast-dump-template-decls.cpp
+++ b/clang/test/AST/ast-dump-template-decls.cpp
@@ -124,8 +124,6 @@ using type2 = typename C<int>::type1<void>;
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void'
// CHECK-NEXT: FunctionProtoType 0x{{[^ ]*}} 'void (int)' cdecl
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void'
-// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 T
-// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'C'
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int'
} // namespace PR55886
@@ -136,7 +134,7 @@ template <typename... T> struct D {
};
};
template struct D<float, char>::bind<int, short>;
-// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[1-9]+}}:5, col:45> col:11 bound_type 'int (int (*)(float, int), int (*)(char, short))'
+// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:5, col:45> col:11 bound_type 'int (int (*)(float, int), int (*)(char, short))'
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (int (*)(float, int), int (*)(char, short))' cdecl
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (float, int)' cdecl
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... T pack_index 1
diff --git a/clang/test/Sema/Resugar/resugar-types.cpp b/clang/test/Sema/Resugar/resugar-types.cpp
index baa3b4ed65f20..296a79a05b6be 100644
--- a/clang/test/Sema/Resugar/resugar-types.cpp
+++ b/clang/test/Sema/Resugar/resugar-types.cpp
@@ -88,7 +88,7 @@ template <class E> struct foo {
};
using T1 = foo<Bar>::apply<char>;
TEST_NOT(T1::type1);
-TEST_NOT(T1::type2); // FIXME: Needs resugaring on the pattern of template type aliases.
+TEST(T1::type2);
using T2 = foo<int>::apply<Bar>;
TEST(T2::type1);
@@ -106,7 +106,7 @@ template <typename... Cs> struct foo {
};
using T1 = foo<Bar>::bind<char>;
TEST_NOT(T1::type1);
-TEST_NOT(T1::type2); // FIXME: Needs resugaring on the pattern of template type aliases.
+TEST(T1::type2);
using T2 = foo<int>::bind<Bar>;
TEST(T2::type1);
@@ -148,7 +148,7 @@ template <typename... Ts> using Z = Y<Ts...>;
using T1 = typename foo<Z, Bar>::template bind<int>;
TEST_NOT(typename T1::type1);
-TEST_NOT(typename T1::type2); // FIXME: Needs resugaring on the pattern of template type aliases.
+TEST(typename T1::type2);
using T2 = typename foo<Z, int>::template bind<Bar>;
TEST(typename T2::type1);
|
e621da3
to
4571fad
Compare
3022927
to
67a0981
Compare
67a0981
to
9d5d428
Compare
4571fad
to
0793555
Compare
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
0793555
to
a010f37
Compare
9d5d428
to
900a26a
Compare
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