Skip to content

[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

Open
wants to merge 1 commit into
base: users/mizvekov/clang-resugar-typedecl
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -11512,7 +11512,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);

Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaCXXScopeSpec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -907,7 +907,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;

Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Sema/SemaCoroutine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -169,7 +169,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,
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1140,7 +1140,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)) {
Expand Down Expand Up @@ -12162,7 +12163,8 @@ QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) {
Context.getTrivialTypeSourceInfo(Element,
Loc)));

QualType T = CheckTemplateIdType(TemplateName(StdInitializerList), Loc, Args);
QualType T =
CheckTemplateIdType(nullptr, TemplateName(StdInitializerList), Loc, Args);
if (T.isNull())
return QualType();

Expand Down
43 changes: 25 additions & 18 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3826,15 +3826,16 @@ 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,
TemplateArgument T2) -> QualType {
// 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(
Expand All @@ -3848,7 +3849,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();
Expand Down Expand Up @@ -3961,8 +3962,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();
Expand Down Expand Up @@ -4014,7 +4015,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,
Expand Down Expand Up @@ -4064,14 +4065,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,
Expand Down Expand Up @@ -4219,7 +4222,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) {
// FIXME: 'getUnderlying' loses SubstTemplateTemplateParm nodes from alias
Expand Down Expand Up @@ -4298,9 +4302,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
Expand Down Expand Up @@ -4337,9 +4341,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)) {
Expand Down Expand Up @@ -4582,7 +4586,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;

Expand Down Expand Up @@ -4663,7 +4668,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);

Expand Down Expand Up @@ -11444,7 +11450,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;

Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6817,7 +6817,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
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -17349,7 +17349,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>
Expand Down
4 changes: 2 additions & 2 deletions clang/test/AST/ast-dump-template-decls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ using type2 = typename C<int>::type1<void>;
// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'void' sugar class depth 0 index 0 U final
// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'type1'
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void'
// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 T
// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 T final
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'C'
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int'
} // namespace PR55886
Expand All @@ -138,7 +138,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{{$}}
Expand Down
6 changes: 3 additions & 3 deletions clang/test/Sema/Resugar/resugar-types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
Loading