Skip to content

Commit 5b6f71b

Browse files
committed
WIP: [clang] store sugared converted arguments on TemplateSpecializationType
Not ready for review This is a quite large patch, half of which will be redone following a different approach. Although it improves sugar retention in template argument deduction on its own, this is an enabler for resugaring. This stores the sugared converted template arguments in a TST, in addition to the existing as-written ones, so this is quite wasteful. This is the biggest performance impact on the whole of resugaring so far, although it is hoped the new approach will have negligible impact. This is a continuation of https://reviews.llvm.org/D134113
1 parent cfee056 commit 5b6f71b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+695
-598
lines changed

clang-tools-extra/clang-tidy/modernize/UseTransparentFunctorsCheck.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,9 @@ void UseTransparentFunctorsCheck::check(
9494
unsigned ArgNum = 0;
9595
const auto *FunctorParentType =
9696
FunctorParentLoc.getType()->castAs<TemplateSpecializationType>();
97-
for (; ArgNum < FunctorParentType->template_arguments().size(); ++ArgNum) {
97+
for (; ArgNum < FunctorParentType->getSpecifiedArguments().size(); ++ArgNum) {
9898
const TemplateArgument &Arg =
99-
FunctorParentType->template_arguments()[ArgNum];
99+
FunctorParentType->getSpecifiedArguments()[ArgNum];
100100
if (Arg.getKind() != TemplateArgument::Type)
101101
continue;
102102
QualType ParentArgType = Arg.getAsType();
@@ -106,7 +106,7 @@ void UseTransparentFunctorsCheck::check(
106106
break;
107107
}
108108
// Functor is a default template argument.
109-
if (ArgNum == FunctorParentType->template_arguments().size())
109+
if (ArgNum == FunctorParentType->getSpecifiedArguments().size())
110110
return;
111111
TemplateArgumentLoc FunctorLoc = FunctorParentLoc.getArgLoc(ArgNum);
112112
auto FunctorTypeLoc = getInnerTypeLocAs<TemplateSpecializationTypeLoc>(

clang-tools-extra/clang-tidy/mpi/TypeMismatchCheck.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ isCXXComplexTypeMatching(const TemplateSpecializationType *const Template,
181181
if (Template->getAsCXXRecordDecl()->getName() != "complex")
182182
return true;
183183

184-
const auto *Builtin = Template->template_arguments()[0]
184+
const auto *Builtin = Template->getSpecifiedArguments()[0]
185185
.getAsType()
186186
.getTypePtr()
187187
->getAs<BuiltinType>();

clang-tools-extra/clangd/AST.cpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -437,9 +437,15 @@ bool hasReservedScope(const DeclContext &DC) {
437437
QualType declaredType(const TypeDecl *D) {
438438
ASTContext &Context = D->getASTContext();
439439
if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D))
440-
if (const auto *Args = CTSD->getTemplateArgsAsWritten())
440+
if (const auto *ArgList = CTSD->getTemplateArgsAsWritten()) {
441+
SmallVector<TemplateArgument, 4> Args(ArgList->arguments().size());
442+
for (unsigned I = 0, E = Args.size(); I < E; ++I)
443+
Args[I] = ArgList->arguments()[I].getArgument();
441444
return Context.getTemplateSpecializationType(
442-
TemplateName(CTSD->getSpecializedTemplate()), Args->arguments());
445+
TemplateName(CTSD->getSpecializedTemplate()), Args,
446+
/*SugaredConvertedArgs=*/std::nullopt,
447+
/*CanonicalConvertedArgs=*/std::nullopt);
448+
}
443449
return Context.getTypeDeclType(D);
444450
}
445451

clang/include/clang/AST/ASTContext.h

+24-16
Original file line numberDiff line numberDiff line change
@@ -1808,22 +1808,24 @@ class ASTContext : public RefCountedBase<ASTContext> {
18081808
bool ParameterPack,
18091809
TemplateTypeParmDecl *ParmDecl = nullptr) const;
18101810

1811-
QualType getTemplateSpecializationType(TemplateName T,
1812-
ArrayRef<TemplateArgument> Args,
1813-
QualType Canon = QualType()) const;
1814-
1815-
QualType
1816-
getCanonicalTemplateSpecializationType(TemplateName T,
1817-
ArrayRef<TemplateArgument> Args) const;
1818-
1819-
QualType getTemplateSpecializationType(TemplateName T,
1820-
ArrayRef<TemplateArgumentLoc> Args,
1821-
QualType Canon = QualType()) const;
1822-
1823-
TypeSourceInfo *
1824-
getTemplateSpecializationTypeInfo(TemplateName T, SourceLocation TLoc,
1825-
const TemplateArgumentListInfo &Args,
1826-
QualType Canon = QualType()) const;
1811+
QualType getTemplateSpecializationType(
1812+
TemplateName T, ArrayRef<TemplateArgument> SpecifiedArgs,
1813+
ArrayRef<TemplateArgument> SugaredConvertedArgs,
1814+
ArrayRef<TemplateArgument> CanonicalConvertedArgs,
1815+
QualType Canon = QualType()) const;
1816+
1817+
QualType getTemplateSpecializationType(
1818+
TemplateName T, ArrayRef<TemplateArgumentLoc> SpecifiedArgs,
1819+
ArrayRef<TemplateArgument> SugaredConvertedArgs,
1820+
ArrayRef<TemplateArgument> CanonicalConvertedArgs,
1821+
QualType Canon = QualType()) const;
1822+
1823+
TypeSourceInfo *getTemplateSpecializationTypeInfo(
1824+
TemplateName T, SourceLocation TLoc,
1825+
const TemplateArgumentListInfo &SpecifiedArgs,
1826+
ArrayRef<TemplateArgument> SugaredConvertedArgs,
1827+
ArrayRef<TemplateArgument> CanonicalConvertedArgs,
1828+
QualType Canon = QualType()) const;
18271829

18281830
QualType getParenType(QualType NamedType) const;
18291831

@@ -2939,6 +2941,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
29392941
TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg)
29402942
const;
29412943

2944+
/// Canonicalize the given template argument list.
2945+
///
2946+
/// Returns true if any arguments were non-canonical, false otherwise.
2947+
bool
2948+
canonicalizeTemplateArguments(MutableArrayRef<TemplateArgument> Args) const;
2949+
29422950
/// Type Query functions. If the type is an instance of the specified class,
29432951
/// return the Type pointer for the underlying maximally pretty type. This
29442952
/// is a member of ASTContext because this may need to do some amount of

clang/include/clang/AST/ASTNodeTraverser.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ class ASTNodeTraverser
456456
Visit(T->getArgumentPack());
457457
}
458458
void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
459-
for (const auto &Arg : T->template_arguments())
459+
for (const auto &Arg : T->getSpecifiedArguments())
460460
Visit(Arg);
461461
}
462462
void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {

clang/include/clang/AST/DeclTemplate.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -610,8 +610,10 @@ class FunctionTemplateSpecializationInfo final
610610
Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs,
611611
const ASTContext &Context) {
612612
ID.AddInteger(TemplateArgs.size());
613+
// We allow instantiating deduction guides with non-canonical template
614+
// arguments.
613615
for (const TemplateArgument &TemplateArg : TemplateArgs)
614-
TemplateArg.Profile(ID, Context);
616+
TemplateArg.Profile(ID, Context, /*Canonical=*/false);
615617
}
616618
};
617619

@@ -2090,7 +2092,7 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
20902092
const ASTContext &Context) {
20912093
ID.AddInteger(TemplateArgs.size());
20922094
for (const TemplateArgument &TemplateArg : TemplateArgs)
2093-
TemplateArg.Profile(ID, Context);
2095+
TemplateArg.Profile(ID, Context, /*Canonical=*/true);
20942096
}
20952097

20962098
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -2864,7 +2866,7 @@ class VarTemplateSpecializationDecl : public VarDecl,
28642866
const ASTContext &Context) {
28652867
ID.AddInteger(TemplateArgs.size());
28662868
for (const TemplateArgument &TemplateArg : TemplateArgs)
2867-
TemplateArg.Profile(ID, Context);
2869+
TemplateArg.Profile(ID, Context, /*Canonical=*/true);
28682870
}
28692871

28702872
static bool classof(const Decl *D) { return classofKind(D->getKind()); }

clang/include/clang/AST/RecursiveASTVisitor.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -1134,7 +1134,10 @@ DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, {
11341134

11351135
DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
11361136
TRY_TO(TraverseTemplateName(T->getTemplateName()));
1137-
TRY_TO(TraverseTemplateArguments(T->template_arguments()));
1137+
if (T->isCanonicalUnqualified())
1138+
TRY_TO(TraverseTemplateArguments(T->getConvertedArguments()));
1139+
else
1140+
TRY_TO(TraverseTemplateArguments(T->getSpecifiedArguments()));
11381141
})
11391142

11401143
DEF_TRAVERSE_TYPE(InjectedClassNameType, {})

clang/include/clang/AST/TemplateBase.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,8 @@ class TemplateArgument {
462462
void dump() const;
463463

464464
/// Used to insert TemplateArguments into FoldingSets.
465-
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
465+
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
466+
bool Canonical) const;
466467
};
467468

468469
/// Location information for a TemplateArgument.

clang/include/clang/AST/Type.h

+31-15
Original file line numberDiff line numberDiff line change
@@ -2199,10 +2199,9 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
21992199
/// specialization, which is expected to be able to hold at least 1024
22002200
/// according to [implimits]. However, as this limit is somewhat easy to
22012201
/// hit with template metaprogramming we'd prefer to keep it as large
2202-
/// as possible. At the moment it has been left as a non-bitfield since
2203-
/// this type safely fits in 64 bits as an unsigned, so there is no reason
2204-
/// to introduce the performance impact of a bitfield.
2205-
unsigned NumArgs;
2202+
/// as possible.
2203+
unsigned NumSpecifiedArgs : 16;
2204+
unsigned NumConvertedArgs : 16;
22062205
};
22072206

22082207
class DependentTemplateSpecializationTypeBitfields {
@@ -2821,6 +2820,18 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
28212820
/// immediately following this class.
28222821
template <typename T> const T *getAs() const;
28232822

2823+
/// Look through sugar for an instance of TemplateSpecializationType which
2824+
/// is not a type alias.
2825+
const TemplateSpecializationType *
2826+
getAsNonAliasTemplateSpecializationType() const;
2827+
2828+
const TemplateSpecializationType *
2829+
castAsNonAliasTemplateSpecializationType() const {
2830+
auto TST = getAsNonAliasTemplateSpecializationType();
2831+
assert(TST && "not a TemplateSpecializationType");
2832+
return TST;
2833+
}
2834+
28242835
/// Member-template getAsAdjusted<specific type>. Look through specific kinds
28252836
/// of sugar (parens, attributes, etc) for an instance of \<specific type>.
28262837
/// This is used when you need to walk over sugar nodes that represent some
@@ -6594,7 +6605,7 @@ class AutoType : public DeducedType {
65946605
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
65956606
QualType Deduced, AutoTypeKeyword Keyword,
65966607
bool IsDependent, ConceptDecl *CD,
6597-
ArrayRef<TemplateArgument> Arguments);
6608+
ArrayRef<TemplateArgument> Arguments, bool Canonical);
65986609

65996610
static bool classof(const Type *T) {
66006611
return T->getTypeClass() == Auto;
@@ -6672,10 +6683,10 @@ class TemplateSpecializationType : public Type, public llvm::FoldingSetNode {
66726683
/// replacement must, recursively, be one of these).
66736684
TemplateName Template;
66746685

6675-
TemplateSpecializationType(TemplateName T,
6676-
ArrayRef<TemplateArgument> Args,
6677-
QualType Canon,
6678-
QualType Aliased);
6686+
TemplateSpecializationType(TemplateName T, bool IsAlias,
6687+
ArrayRef<TemplateArgument> SpecifiedArgs,
6688+
ArrayRef<TemplateArgument> ConvertedArgs,
6689+
QualType Underlying);
66796690

66806691
public:
66816692
/// Determine whether any of the given template arguments are dependent.
@@ -6728,11 +6739,13 @@ class TemplateSpecializationType : public Type, public llvm::FoldingSetNode {
67286739
/// Retrieve the name of the template that we are specializing.
67296740
TemplateName getTemplateName() const { return Template; }
67306741

6731-
ArrayRef<TemplateArgument> template_arguments() const {
6742+
ArrayRef<TemplateArgument> getSpecifiedArguments() const {
67326743
return {reinterpret_cast<const TemplateArgument *>(this + 1),
6733-
TemplateSpecializationTypeBits.NumArgs};
6744+
TemplateSpecializationTypeBits.NumSpecifiedArgs};
67346745
}
67356746

6747+
ArrayRef<TemplateArgument> getConvertedArguments() const;
6748+
67366749
bool isSugared() const {
67376750
return !isDependentType() || isCurrentInstantiation() || isTypeAlias();
67386751
}
@@ -6743,8 +6756,10 @@ class TemplateSpecializationType : public Type, public llvm::FoldingSetNode {
67436756

67446757
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx);
67456758
static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T,
6746-
ArrayRef<TemplateArgument> Args,
6747-
const ASTContext &Context);
6759+
ArrayRef<TemplateArgument> SpecifiedArgs,
6760+
ArrayRef<TemplateArgument> ConvertedArgs,
6761+
QualType Underlying, const ASTContext &Context,
6762+
bool Canonical);
67486763

67496764
static bool classof(const Type *T) {
67506765
return T->getTypeClass() == TemplateSpecialization;
@@ -7099,13 +7114,14 @@ class DependentTemplateSpecializationType : public TypeWithKeyword,
70997114
QualType desugar() const { return QualType(this, 0); }
71007115

71017116
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) {
7102-
Profile(ID, Context, getKeyword(), Name, template_arguments());
7117+
Profile(ID, Context, getKeyword(), Name, template_arguments(),
7118+
isCanonicalUnqualified());
71037119
}
71047120

71057121
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
71067122
ElaboratedTypeKeyword Keyword,
71077123
const DependentTemplateStorage &Name,
7108-
ArrayRef<TemplateArgument> Args);
7124+
ArrayRef<TemplateArgument> Args, bool IsCanonical);
71097125

71107126
static bool classof(const Type *T) {
71117127
return T->getTypeClass() == DependentTemplateSpecialization;

clang/include/clang/AST/TypeLoc.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -1718,7 +1718,7 @@ class TemplateSpecializationTypeLoc :
17181718
}
17191719

17201720
unsigned getNumArgs() const {
1721-
return getTypePtr()->template_arguments().size();
1721+
return getTypePtr()->getSpecifiedArguments().size();
17221722
}
17231723

17241724
void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
@@ -1730,7 +1730,7 @@ class TemplateSpecializationTypeLoc :
17301730
}
17311731

17321732
TemplateArgumentLoc getArgLoc(unsigned i) const {
1733-
return TemplateArgumentLoc(getTypePtr()->template_arguments()[i],
1733+
return TemplateArgumentLoc(getTypePtr()->getSpecifiedArguments()[i],
17341734
getArgLocInfo(i));
17351735
}
17361736

@@ -1766,7 +1766,7 @@ class TemplateSpecializationTypeLoc :
17661766
setTemplateNameLoc(Loc);
17671767
setLAngleLoc(Loc);
17681768
setRAngleLoc(Loc);
1769-
initializeArgLocs(Context, getTypePtr()->template_arguments(),
1769+
initializeArgLocs(Context, getTypePtr()->getSpecifiedArguments(),
17701770
getArgInfos(), Loc);
17711771
}
17721772

clang/include/clang/AST/TypeProperties.td

+13-15
Original file line numberDiff line numberDiff line change
@@ -743,29 +743,27 @@ let Class = TemplateSpecializationType in {
743743
def : Property<"templateName", TemplateName> {
744744
let Read = [{ node->getTemplateName() }];
745745
}
746-
def : Property<"templateArguments", Array<TemplateArgument>> {
747-
let Read = [{ node->template_arguments() }];
746+
def : Property<"specifiedArguments", Array<TemplateArgument>> {
747+
let Read = [{ node->getSpecifiedArguments() }];
748+
}
749+
def : Property<"convertedArguments", Array<TemplateArgument>> {
750+
let Read = [{ node->getConvertedArguments() }];
748751
}
749-
def : Property<"underlyingType", Optional<QualType>> {
752+
def : Property<"underlyingType", QualType> {
750753
let Read = [{
751754
node->isTypeAlias()
752-
? std::optional<QualType>(node->getAliasedType())
755+
? node->getAliasedType()
753756
: node->isCanonicalUnqualified()
754-
? std::nullopt
755-
: std::optional<QualType>(node->getCanonicalTypeInternal())
757+
? QualType() : node->getCanonicalTypeInternal()
756758
}];
757759
}
758760

759761
def : Creator<[{
760-
QualType result;
761-
if (!underlyingType) {
762-
result = ctx.getCanonicalTemplateSpecializationType(templateName,
763-
templateArguments);
764-
} else {
765-
result = ctx.getTemplateSpecializationType(templateName,
766-
templateArguments,
767-
*underlyingType);
768-
}
762+
QualType result = ctx.getTemplateSpecializationType(templateName,
763+
specifiedArguments,
764+
convertedArguments,
765+
/*CanonicalConvertedArguments=*/{},
766+
underlyingType);
769767
if (dependent)
770768
const_cast<Type *>(result.getTypePtr())
771769
->addDependence(TypeDependence::DependentInstantiation);

clang/include/clang/ASTMatchers/ASTMatchersInternal.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1949,7 +1949,7 @@ getTemplateSpecializationArgs(const VarTemplateSpecializationDecl &D) {
19491949

19501950
inline ArrayRef<TemplateArgument>
19511951
getTemplateSpecializationArgs(const TemplateSpecializationType &T) {
1952-
return T.template_arguments();
1952+
return T.getSpecifiedArguments();
19531953
}
19541954

19551955
inline ArrayRef<TemplateArgument>

clang/include/clang/Basic/DiagnosticSemaKinds.td

+1-1
Original file line numberDiff line numberDiff line change
@@ -6983,7 +6983,7 @@ def err_illegal_decl_mempointer_to_void : Error<
69836983
"'%0' declared as a member pointer to void">;
69846984
def err_illegal_decl_mempointer_in_nonclass
69856985
: Error<"%0 does not point into a class">;
6986-
def err_reference_to_void : Error<"cannot form a reference to 'void'">;
6986+
def err_reference_to_void : Error<"cannot form a reference to %0">;
69876987
def err_nonfunction_block_type : Error<
69886988
"block pointer to non-function type is invalid">;
69896989
def err_return_block_has_expr : Error<"void block should not return a value">;

clang/include/clang/Sema/SemaConcept.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ struct alignas(ConstraintAlignment) AtomicConstraint {
4949
for (unsigned I = 0, S = ParameterMapping->size(); I < S; ++I) {
5050
llvm::FoldingSetNodeID IDA, IDB;
5151
C.getCanonicalTemplateArgument((*ParameterMapping)[I].getArgument())
52-
.Profile(IDA, C);
52+
.Profile(IDA, C, /*Canonical=*/true);
5353
C.getCanonicalTemplateArgument((*Other.ParameterMapping)[I].getArgument())
54-
.Profile(IDB, C);
54+
.Profile(IDB, C, /*Canonical=*/true);
5555
if (IDA != IDB)
5656
return false;
5757
}

clang/include/clang/Serialization/ASTRecordReader.h

+4
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@ class ASTRecordReader
247247
void readTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs,
248248
bool Canonicalize = false);
249249

250+
/// Read a template argument list.
251+
const TemplateArgumentList *
252+
readTemplateArgumentList(bool Canonicalize = false);
253+
250254
/// Read a UnresolvedSet structure, advancing Idx.
251255
void readUnresolvedSet(LazyASTUnresolvedSet &Set);
252256

clang/lib/AST/ASTConcept.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ void ConstraintSatisfaction::Profile(
8080
ID.AddPointer(ConstraintOwner);
8181
ID.AddInteger(TemplateArgs.size());
8282
for (auto &Arg : TemplateArgs)
83-
Arg.Profile(ID, C);
83+
Arg.Profile(ID, C, /*Canonical=*/false);
8484
}
8585

8686
ConceptReference *

0 commit comments

Comments
 (0)