[llvm-branch-commits] [clang] [clang] Template Specialization Resugaring - Template Type Alias (PR #132442)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Mar 21 11:19:44 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Matheus Izvekov (mizvekov)
<details>
<summary>Changes</summary>
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
---
Full diff: https://github.com/llvm/llvm-project/pull/132442.diff
9 Files Affected:
- (modified) clang/include/clang/Sema/Sema.h (+2-1)
- (modified) clang/lib/Sema/SemaCXXScopeSpec.cpp (+2-1)
- (modified) clang/lib/Sema/SemaCoroutine.cpp (+2-2)
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+4-2)
- (modified) clang/lib/Sema/SemaTemplate.cpp (+25-18)
- (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+2-1)
- (modified) clang/lib/Sema/TreeTransform.h (+2-1)
- (modified) clang/test/AST/ast-dump-template-decls.cpp (+1-3)
- (modified) clang/test/Sema/Resugar/resugar-types.cpp (+3-3)
``````````diff
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);
``````````
</details>
https://github.com/llvm/llvm-project/pull/132442
More information about the llvm-branch-commits
mailing list