Skip to content

Commit 6f70503

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 3b0ec61 commit 6f70503

File tree

61 files changed

+726
-635
lines changed

Some content is hidden

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

61 files changed

+726
-635
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
@@ -438,9 +438,15 @@ bool hasReservedScope(const DeclContext &DC) {
438438
QualType declaredType(const TypeDecl *D) {
439439
ASTContext &Context = D->getASTContext();
440440
if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D))
441-
if (const auto *Args = CTSD->getTemplateArgsAsWritten())
441+
if (const auto *ArgList = CTSD->getTemplateArgsAsWritten()) {
442+
SmallVector<TemplateArgument, 4> Args(ArgList->arguments().size());
443+
for (unsigned I = 0, E = Args.size(); I < E; ++I)
444+
Args[I] = ArgList->arguments()[I].getArgument();
442445
return Context.getTemplateSpecializationType(
443-
TemplateName(CTSD->getSpecializedTemplate()), Args->arguments());
446+
TemplateName(CTSD->getSpecializedTemplate()), Args,
447+
/*SugaredConvertedArgs=*/std::nullopt,
448+
/*CanonicalConvertedArgs=*/std::nullopt);
449+
}
444450
return Context.getTypeDeclType(D);
445451
}
446452

clang/include/clang/AST/ASTContext.h

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1810,22 +1810,24 @@ class ASTContext : public RefCountedBase<ASTContext> {
18101810
bool ParameterPack,
18111811
TemplateTypeParmDecl *ParmDecl = nullptr) const;
18121812

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

18301832
QualType getParenType(QualType NamedType) const;
18311833

@@ -1845,7 +1847,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
18451847
const IdentifierInfo *Name, ArrayRef<TemplateArgumentLoc> Args) const;
18461848
QualType getDependentTemplateSpecializationType(
18471849
ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
1848-
const IdentifierInfo *Name, ArrayRef<TemplateArgument> Args) const;
1850+
const IdentifierInfo *Name, ArrayRef<TemplateArgument> Args,
1851+
bool Canonical = false) const;
18491852

18501853
TemplateArgument getInjectedTemplateArg(NamedDecl *ParamDecl) const;
18511854

@@ -2936,6 +2939,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
29362939
TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg)
29372940
const;
29382941

2942+
/// Canonicalize the given template argument list.
2943+
///
2944+
/// Returns true if any arguments were non-canonical, false otherwise.
2945+
bool
2946+
canonicalizeTemplateArguments(MutableArrayRef<TemplateArgument> Args) const;
2947+
29392948
/// Type Query functions. If the type is an instance of the specified class,
29402949
/// return the Type pointer for the underlying maximally pretty type. This
29412950
/// 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
@@ -452,7 +452,7 @@ class ASTNodeTraverser
452452
Visit(T->getArgumentPack());
453453
}
454454
void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
455-
for (const auto &Arg : T->template_arguments())
455+
for (const auto &Arg : T->getSpecifiedArguments())
456456
Visit(Arg);
457457
}
458458
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
@@ -608,8 +608,10 @@ class FunctionTemplateSpecializationInfo final
608608
Profile(llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs,
609609
const ASTContext &Context) {
610610
ID.AddInteger(TemplateArgs.size());
611+
// We allow instantiating deduction guides with non-canonical template
612+
// arguments.
611613
for (const TemplateArgument &TemplateArg : TemplateArgs)
612-
TemplateArg.Profile(ID, Context);
614+
TemplateArg.Profile(ID, Context, /*Canonical=*/false);
613615
}
614616
};
615617

@@ -2096,7 +2098,7 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
20962098
const ASTContext &Context) {
20972099
ID.AddInteger(TemplateArgs.size());
20982100
for (const TemplateArgument &TemplateArg : TemplateArgs)
2099-
TemplateArg.Profile(ID, Context);
2101+
TemplateArg.Profile(ID, Context, /*Canonical=*/true);
21002102
}
21012103

21022104
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -2869,7 +2871,7 @@ class VarTemplateSpecializationDecl : public VarDecl,
28692871
const ASTContext &Context) {
28702872
ID.AddInteger(TemplateArgs.size());
28712873
for (const TemplateArgument &TemplateArg : TemplateArgs)
2872-
TemplateArg.Profile(ID, Context);
2874+
TemplateArg.Profile(ID, Context, /*Canonical=*/true);
28732875
}
28742876

28752877
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: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2208,10 +2208,9 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
22082208
/// specialization, which is expected to be able to hold at least 1024
22092209
/// according to [implimits]. However, as this limit is somewhat easy to
22102210
/// hit with template metaprogramming we'd prefer to keep it as large
2211-
/// as possible. At the moment it has been left as a non-bitfield since
2212-
/// this type safely fits in 64 bits as an unsigned, so there is no reason
2213-
/// to introduce the performance impact of a bitfield.
2214-
unsigned NumArgs;
2211+
/// as possible.
2212+
unsigned NumSpecifiedArgs : 16;
2213+
unsigned NumConvertedArgs : 16;
22152214
};
22162215

22172216
class DependentTemplateSpecializationTypeBitfields {
@@ -2830,6 +2829,18 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
28302829
/// immediately following this class.
28312830
template <typename T> const T *getAs() const;
28322831

2832+
/// Look through sugar for an instance of TemplateSpecializationType which
2833+
/// is not a type alias.
2834+
const TemplateSpecializationType *
2835+
getAsNonAliasTemplateSpecializationType() const;
2836+
2837+
const TemplateSpecializationType *
2838+
castAsNonAliasTemplateSpecializationType() const {
2839+
auto TST = getAsNonAliasTemplateSpecializationType();
2840+
assert(TST && "not a TemplateSpecializationType");
2841+
return TST;
2842+
}
2843+
28332844
/// Member-template getAsAdjusted<specific type>. Look through specific kinds
28342845
/// of sugar (parens, attributes, etc) for an instance of \<specific type>.
28352846
/// This is used when you need to walk over sugar nodes that represent some
@@ -6601,7 +6612,7 @@ class AutoType : public DeducedType {
66016612
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
66026613
QualType Deduced, AutoTypeKeyword Keyword,
66036614
bool IsDependent, ConceptDecl *CD,
6604-
ArrayRef<TemplateArgument> Arguments);
6615+
ArrayRef<TemplateArgument> Arguments, bool Canonical);
66056616

66066617
static bool classof(const Type *T) {
66076618
return T->getTypeClass() == Auto;
@@ -6679,10 +6690,10 @@ class TemplateSpecializationType : public Type, public llvm::FoldingSetNode {
66796690
/// replacement must, recursively, be one of these).
66806691
TemplateName Template;
66816692

6682-
TemplateSpecializationType(TemplateName T,
6683-
ArrayRef<TemplateArgument> Args,
6684-
QualType Canon,
6685-
QualType Aliased);
6693+
TemplateSpecializationType(TemplateName T, bool IsAlias,
6694+
ArrayRef<TemplateArgument> SpecifiedArgs,
6695+
ArrayRef<TemplateArgument> ConvertedArgs,
6696+
QualType Underlying);
66866697

66876698
public:
66886699
/// Determine whether any of the given template arguments are dependent.
@@ -6735,11 +6746,13 @@ class TemplateSpecializationType : public Type, public llvm::FoldingSetNode {
67356746
/// Retrieve the name of the template that we are specializing.
67366747
TemplateName getTemplateName() const { return Template; }
67376748

6738-
ArrayRef<TemplateArgument> template_arguments() const {
6749+
ArrayRef<TemplateArgument> getSpecifiedArguments() const {
67396750
return {reinterpret_cast<const TemplateArgument *>(this + 1),
6740-
TemplateSpecializationTypeBits.NumArgs};
6751+
TemplateSpecializationTypeBits.NumSpecifiedArgs};
67416752
}
67426753

6754+
ArrayRef<TemplateArgument> getConvertedArguments() const;
6755+
67436756
bool isSugared() const {
67446757
return !isDependentType() || isCurrentInstantiation() || isTypeAlias();
67456758
}
@@ -6750,8 +6763,10 @@ class TemplateSpecializationType : public Type, public llvm::FoldingSetNode {
67506763

67516764
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx);
67526765
static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T,
6753-
ArrayRef<TemplateArgument> Args,
6754-
const ASTContext &Context);
6766+
ArrayRef<TemplateArgument> SpecifiedArgs,
6767+
ArrayRef<TemplateArgument> ConvertedArgs,
6768+
QualType Underlying, const ASTContext &Context,
6769+
bool Canonical);
67556770

67566771
static bool classof(const Type *T) {
67576772
return T->getTypeClass() == TemplateSpecialization;
@@ -7110,15 +7125,15 @@ class DependentTemplateSpecializationType : public TypeWithKeyword,
71107125
QualType desugar() const { return QualType(this, 0); }
71117126

71127127
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) {
7113-
Profile(ID, Context, getKeyword(), NNS, Name, template_arguments());
7128+
Profile(ID, Context, getKeyword(), NNS, Name, template_arguments(),
7129+
isCanonicalUnqualified());
71147130
}
71157131

7116-
static void Profile(llvm::FoldingSetNodeID &ID,
7117-
const ASTContext &Context,
7132+
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
71187133
ElaboratedTypeKeyword Keyword,
71197134
NestedNameSpecifier *Qualifier,
71207135
const IdentifierInfo *Name,
7121-
ArrayRef<TemplateArgument> Args);
7136+
ArrayRef<TemplateArgument> Args, bool Canonical);
71227137

71237138
static bool classof(const Type *T) {
71247139
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() }];
748748
}
749-
def : Property<"underlyingType", Optional<QualType>> {
749+
def : Property<"convertedArguments", Array<TemplateArgument>> {
750+
let Read = [{ node->getConvertedArguments() }];
751+
}
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
@@ -6977,7 +6977,7 @@ def err_illegal_decl_mempointer_to_void : Error<
69776977
"'%0' declared as a member pointer to void">;
69786978
def err_illegal_decl_mempointer_in_nonclass
69796979
: Error<"'%0' does not point into a class">;
6980-
def err_reference_to_void : Error<"cannot form a reference to 'void'">;
6980+
def err_reference_to_void : Error<"cannot form a reference to %0">;
69816981
def err_nonfunction_block_type : Error<
69826982
"block pointer to non-function type is invalid">;
69836983
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
@@ -48,9 +48,9 @@ struct alignas(ConstraintAlignment) AtomicConstraint {
4848
for (unsigned I = 0, S = ParameterMapping->size(); I < S; ++I) {
4949
llvm::FoldingSetNodeID IDA, IDB;
5050
C.getCanonicalTemplateArgument((*ParameterMapping)[I].getArgument())
51-
.Profile(IDA, C);
51+
.Profile(IDA, C, /*Canonical=*/true);
5252
C.getCanonicalTemplateArgument((*Other.ParameterMapping)[I].getArgument())
53-
.Profile(IDB, C);
53+
.Profile(IDB, C, /*Canonical=*/true);
5454
if (IDA != IDB)
5555
return false;
5656
}

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)