Skip to content

Commit 8ccbff4

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 c57b9c2 commit 8ccbff4

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

Lines changed: 3 additions & 3 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 8 additions & 2 deletions
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

Lines changed: 24 additions & 16 deletions
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

@@ -2932,6 +2934,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
29322934
TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg)
29332935
const;
29342936

2937+
/// Canonicalize the given template argument list.
2938+
///
2939+
/// Returns true if any arguments were non-canonical, false otherwise.
2940+
bool
2941+
canonicalizeTemplateArguments(MutableArrayRef<TemplateArgument> Args) const;
2942+
29352943
/// Type Query functions. If the type is an instance of the specified class,
29362944
/// return the Type pointer for the underlying maximally pretty type. This
29372945
/// is a member of ASTContext because this may need to do some amount of

clang/include/clang/AST/ASTNodeTraverser.h

Lines changed: 1 addition & 1 deletion
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

Lines changed: 5 additions & 3 deletions
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

@@ -2102,7 +2104,7 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
21022104
const ASTContext &Context) {
21032105
ID.AddInteger(TemplateArgs.size());
21042106
for (const TemplateArgument &TemplateArg : TemplateArgs)
2105-
TemplateArg.Profile(ID, Context);
2107+
TemplateArg.Profile(ID, Context, /*Canonical=*/true);
21062108
}
21072109

21082110
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -2876,7 +2878,7 @@ class VarTemplateSpecializationDecl : public VarDecl,
28762878
const ASTContext &Context) {
28772879
ID.AddInteger(TemplateArgs.size());
28782880
for (const TemplateArgument &TemplateArg : TemplateArgs)
2879-
TemplateArg.Profile(ID, Context);
2881+
TemplateArg.Profile(ID, Context, /*Canonical=*/true);
28802882
}
28812883

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

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 4 additions & 1 deletion
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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,8 @@ class TemplateArgument {
465465
void dump() const;
466466

467467
/// Used to insert TemplateArguments into FoldingSets.
468-
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
468+
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
469+
bool Canonical) const;
469470
};
470471

471472
/// Location information for a TemplateArgument.

clang/include/clang/AST/Type.h

Lines changed: 31 additions & 15 deletions
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
@@ -6595,7 +6606,7 @@ class AutoType : public DeducedType {
65956606
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
65966607
QualType Deduced, AutoTypeKeyword Keyword,
65976608
bool IsDependent, ConceptDecl *CD,
6598-
ArrayRef<TemplateArgument> Arguments);
6609+
ArrayRef<TemplateArgument> Arguments, bool Canonical);
65996610

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

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

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

6732-
ArrayRef<TemplateArgument> template_arguments() const {
6743+
ArrayRef<TemplateArgument> getSpecifiedArguments() const {
67336744
return {reinterpret_cast<const TemplateArgument *>(this + 1),
6734-
TemplateSpecializationTypeBits.NumArgs};
6745+
TemplateSpecializationTypeBits.NumSpecifiedArgs};
67356746
}
67366747

6748+
ArrayRef<TemplateArgument> getConvertedArguments() const;
6749+
67376750
bool isSugared() const {
67386751
return !isDependentType() || isCurrentInstantiation() || isTypeAlias();
67396752
}
@@ -6744,8 +6757,10 @@ class TemplateSpecializationType : public Type, public llvm::FoldingSetNode {
67446757

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

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

71027117
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) {
7103-
Profile(ID, Context, getKeyword(), Name, template_arguments());
7118+
Profile(ID, Context, getKeyword(), Name, template_arguments(),
7119+
isCanonicalUnqualified());
71047120
}
71057121

71067122
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
71077123
ElaboratedTypeKeyword Keyword,
71087124
const DependentTemplateStorage &Name,
7109-
ArrayRef<TemplateArgument> Args);
7125+
ArrayRef<TemplateArgument> Args, bool IsCanonical);
71107126

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

clang/include/clang/AST/TypeLoc.h

Lines changed: 3 additions & 3 deletions
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

Lines changed: 13 additions & 15 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6981,7 +6981,7 @@ def err_illegal_decl_mempointer_to_void : Error<
69816981
"'%0' declared as a member pointer to void">;
69826982
def err_illegal_decl_mempointer_in_nonclass
69836983
: Error<"%0 does not point into a class">;
6984-
def err_reference_to_void : Error<"cannot form a reference to 'void'">;
6984+
def err_reference_to_void : Error<"cannot form a reference to %0">;
69856985
def err_nonfunction_block_type : Error<
69866986
"block pointer to non-function type is invalid">;
69876987
def err_return_block_has_expr : Error<"void block should not return a value">;

clang/include/clang/Sema/SemaConcept.h

Lines changed: 2 additions & 2 deletions
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

Lines changed: 4 additions & 0 deletions
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

Lines changed: 1 addition & 1 deletion
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)