Skip to content

Commit 3f41f36

Browse files
committed
[clang] Track final substitution for SubstTemplateTypeParmType nodes
1 parent 2a7baa4 commit 3f41f36

File tree

12 files changed

+68
-41
lines changed

12 files changed

+68
-41
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1795,10 +1795,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
17951795
QualType Wrapped, QualType Contained,
17961796
const HLSLAttributedResourceType::Attributes &Attrs);
17971797

1798-
QualType
1799-
getSubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl,
1800-
unsigned Index,
1801-
std::optional<unsigned> PackIndex) const;
1798+
QualType getSubstTemplateTypeParmType(QualType Replacement,
1799+
Decl *AssociatedDecl, unsigned Index,
1800+
std::optional<unsigned> PackIndex,
1801+
bool Final) const;
18021802
QualType getSubstTemplateTypeParmPackType(Decl *AssociatedDecl,
18031803
unsigned Index, bool Final,
18041804
const TemplateArgument &ArgPack);

clang/include/clang/AST/Type.h

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2158,12 +2158,15 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
21582158
// The index of the template parameter this substitution represents.
21592159
unsigned Index : 15;
21602160

2161+
LLVM_PREFERRED_TYPE(bool)
2162+
unsigned Final : 1;
2163+
21612164
/// Represents the index within a pack if this represents a substitution
21622165
/// from a pack expansion. This index starts at the end of the pack and
21632166
/// increments towards the beginning.
21642167
/// Positive non-zero number represents the index + 1.
21652168
/// Zero means this is not substituted from an expansion.
2166-
unsigned PackIndex : 16;
2169+
unsigned PackIndex : 15;
21672170
};
21682171

21692172
class SubstTemplateTypeParmPackTypeBitfields {
@@ -6384,7 +6387,8 @@ class SubstTemplateTypeParmType final
63846387
Decl *AssociatedDecl;
63856388

63866389
SubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl,
6387-
unsigned Index, std::optional<unsigned> PackIndex);
6390+
unsigned Index, std::optional<unsigned> PackIndex,
6391+
bool Final);
63886392

63896393
public:
63906394
/// Gets the type that was substituted for the template
@@ -6407,6 +6411,10 @@ class SubstTemplateTypeParmType final
64076411
/// This should match the result of `getReplacedParameter()->getIndex()`.
64086412
unsigned getIndex() const { return SubstTemplateTypeParmTypeBits.Index; }
64096413

6414+
// This substitution is Final, which means the substitution is fully
6415+
// sugared: it doesn't need to be resugared later.
6416+
unsigned getFinal() const { return SubstTemplateTypeParmTypeBits.Final; }
6417+
64106418
std::optional<unsigned> getPackIndex() const {
64116419
if (SubstTemplateTypeParmTypeBits.PackIndex == 0)
64126420
return std::nullopt;
@@ -6418,17 +6426,12 @@ class SubstTemplateTypeParmType final
64186426

64196427
void Profile(llvm::FoldingSetNodeID &ID) {
64206428
Profile(ID, getReplacementType(), getAssociatedDecl(), getIndex(),
6421-
getPackIndex());
6429+
getPackIndex(), getFinal());
64226430
}
64236431

64246432
static void Profile(llvm::FoldingSetNodeID &ID, QualType Replacement,
64256433
const Decl *AssociatedDecl, unsigned Index,
6426-
std::optional<unsigned> PackIndex) {
6427-
Replacement.Profile(ID);
6428-
ID.AddPointer(AssociatedDecl);
6429-
ID.AddInteger(Index);
6430-
ID.AddInteger(PackIndex ? *PackIndex - 1 : 0);
6431-
}
6434+
std::optional<unsigned> PackIndex, bool Final);
64326435

64336436
static bool classof(const Type *T) {
64346437
return T->getTypeClass() == SubstTemplateTypeParm;

clang/include/clang/AST/TypeProperties.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -827,11 +827,11 @@ let Class = SubstTemplateTypeParmType in {
827827
def : Property<"PackIndex", Optional<UInt32>> {
828828
let Read = [{ node->getPackIndex() }];
829829
}
830+
def : Property<"Final", Bool> { let Read = [{ node->getFinal() }]; }
830831

831-
// The call to getCanonicalType here existed in ASTReader.cpp, too.
832832
def : Creator<[{
833833
return ctx.getSubstTemplateTypeParmType(
834-
replacementType, associatedDecl, Index, PackIndex);
834+
replacementType, associatedDecl, Index, PackIndex, Final);
835835
}]>;
836836
}
837837

clang/lib/AST/ASTContext.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5449,10 +5449,10 @@ QualType ASTContext::getHLSLAttributedResourceType(
54495449
/// Retrieve a substitution-result type.
54505450
QualType ASTContext::getSubstTemplateTypeParmType(
54515451
QualType Replacement, Decl *AssociatedDecl, unsigned Index,
5452-
std::optional<unsigned> PackIndex) const {
5452+
std::optional<unsigned> PackIndex, bool Final) const {
54535453
llvm::FoldingSetNodeID ID;
54545454
SubstTemplateTypeParmType::Profile(ID, Replacement, AssociatedDecl, Index,
5455-
PackIndex);
5455+
PackIndex, Final);
54565456
void *InsertPos = nullptr;
54575457
SubstTemplateTypeParmType *SubstParm =
54585458
SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
@@ -5462,7 +5462,7 @@ QualType ASTContext::getSubstTemplateTypeParmType(
54625462
!Replacement.isCanonical()),
54635463
alignof(SubstTemplateTypeParmType));
54645464
SubstParm = new (Mem) SubstTemplateTypeParmType(Replacement, AssociatedDecl,
5465-
Index, PackIndex);
5465+
Index, PackIndex, Final);
54665466
Types.push_back(SubstParm);
54675467
SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos);
54685468
}
@@ -14250,7 +14250,8 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
1425014250
if (PackIndex != SY->getPackIndex())
1425114251
return QualType();
1425214252
return Ctx.getSubstTemplateTypeParmType(Ctx.getQualifiedType(Underlying),
14253-
CD, Index, PackIndex);
14253+
CD, Index, PackIndex,
14254+
SX->getFinal() && SY->getFinal());
1425414255
}
1425514256
case Type::ObjCTypeParam:
1425614257
// FIXME: Try to merge these.

clang/lib/AST/ASTImporter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1631,8 +1631,8 @@ ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmType(
16311631
return ToReplacementTypeOrErr.takeError();
16321632

16331633
return Importer.getToContext().getSubstTemplateTypeParmType(
1634-
*ToReplacementTypeOrErr, *ReplacedOrErr, T->getIndex(),
1635-
T->getPackIndex());
1634+
*ToReplacementTypeOrErr, *ReplacedOrErr, T->getIndex(), T->getPackIndex(),
1635+
T->getFinal());
16361636
}
16371637

16381638
ExpectedType ASTNodeImporter::VisitSubstTemplateTypeParmPackType(

clang/lib/AST/TextNodeDumper.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2130,6 +2130,8 @@ void TextNodeDumper::VisitSubstTemplateTypeParmType(
21302130
VisitTemplateTypeParmDecl(T->getReplacedParameter());
21312131
if (auto PackIndex = T->getPackIndex())
21322132
OS << " pack_index " << *PackIndex;
2133+
if (T->getFinal())
2134+
OS << " final";
21332135
}
21342136

21352137
void TextNodeDumper::VisitSubstTemplateTypeParmPackType(

clang/lib/AST/Type.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,9 +1294,9 @@ struct SimpleTransformVisitor : public TypeVisitor<Derived, QualType> {
12941294
== T->getReplacementType().getAsOpaquePtr())
12951295
return QualType(T, 0);
12961296

1297-
return Ctx.getSubstTemplateTypeParmType(replacementType,
1298-
T->getAssociatedDecl(),
1299-
T->getIndex(), T->getPackIndex());
1297+
return Ctx.getSubstTemplateTypeParmType(
1298+
replacementType, T->getAssociatedDecl(), T->getIndex(),
1299+
T->getPackIndex(), T->getFinal());
13001300
}
13011301

13021302
// FIXME: Non-trivial to implement, but important for C++
@@ -4270,7 +4270,7 @@ static const TemplateTypeParmDecl *getReplacedParameter(Decl *D,
42704270

42714271
SubstTemplateTypeParmType::SubstTemplateTypeParmType(
42724272
QualType Replacement, Decl *AssociatedDecl, unsigned Index,
4273-
std::optional<unsigned> PackIndex)
4273+
std::optional<unsigned> PackIndex, bool Final)
42744274
: Type(SubstTemplateTypeParm, Replacement.getCanonicalType(),
42754275
Replacement->getDependence()),
42764276
AssociatedDecl(AssociatedDecl) {
@@ -4280,6 +4280,7 @@ SubstTemplateTypeParmType::SubstTemplateTypeParmType(
42804280
*getTrailingObjects<QualType>() = Replacement;
42814281

42824282
SubstTemplateTypeParmTypeBits.Index = Index;
4283+
SubstTemplateTypeParmTypeBits.Final = Final;
42834284
SubstTemplateTypeParmTypeBits.PackIndex = PackIndex ? *PackIndex + 1 : 0;
42844285
assert(AssociatedDecl != nullptr);
42854286
}
@@ -4289,6 +4290,19 @@ SubstTemplateTypeParmType::getReplacedParameter() const {
42894290
return ::getReplacedParameter(getAssociatedDecl(), getIndex());
42904291
}
42914292

4293+
void SubstTemplateTypeParmType::Profile(llvm::FoldingSetNodeID &ID,
4294+
QualType Replacement,
4295+
const Decl *AssociatedDecl,
4296+
unsigned Index,
4297+
std::optional<unsigned> PackIndex,
4298+
bool Final) {
4299+
Replacement.Profile(ID);
4300+
ID.AddPointer(AssociatedDecl);
4301+
ID.AddInteger(Index);
4302+
ID.AddInteger(PackIndex ? *PackIndex - 1 : 0);
4303+
ID.AddBoolean(Final);
4304+
}
4305+
42924306
SubstTemplateTypeParmPackType::SubstTemplateTypeParmPackType(
42934307
QualType Canon, Decl *AssociatedDecl, unsigned Index, bool Final,
42944308
const TemplateArgument &ArgPack)

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2546,13 +2546,9 @@ QualType TemplateInstantiator::BuildSubstTemplateTypeParmType(
25462546
SemaRef.Context.getQualifiedType(Replacement.getUnqualifiedType(), RQs);
25472547
}
25482548

2549-
if (Final) {
2550-
TLB.pushTrivial(SemaRef.Context, Replacement, NameLoc);
2551-
return Replacement;
2552-
}
25532549
// TODO: only do this uniquing once, at the start of instantiation.
25542550
QualType Result = getSema().Context.getSubstTemplateTypeParmType(
2555-
Replacement, AssociatedDecl, Index, PackIndex);
2551+
Replacement, AssociatedDecl, Index, PackIndex, Final);
25562552
SubstTemplateTypeParmTypeLoc NewTL =
25572553
TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
25582554
NewTL.setNameLoc(NameLoc);

clang/lib/Sema/TreeTransform.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7082,7 +7082,8 @@ QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
70827082
return QualType();
70837083

70847084
QualType Result = SemaRef.Context.getSubstTemplateTypeParmType(
7085-
Replacement, NewReplaced, T->getIndex(), T->getPackIndex());
7085+
Replacement, NewReplaced, T->getIndex(), T->getPackIndex(),
7086+
T->getFinal());
70867087

70877088
// Propagate type-source information.
70887089
SubstTemplateTypeParmTypeLoc NewTL

clang/test/AST/ast-dump-template-decls.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ using type2 = typename C<int>::type1<void>;
123123
// CHECK-NEXT: TemplateArgument type 'void'
124124
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void'
125125
// CHECK-NEXT: FunctionProtoType 0x{{[^ ]*}} 'void (int)' cdecl
126+
// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'void' sugar class depth 0 index 0 U final
127+
// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'type1'
126128
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void'
127129
// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 T
128130
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'C'
@@ -139,14 +141,14 @@ template struct D<float, char>::bind<int, short>;
139141
// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[1-9]+}}:5, col:45> col:11 bound_type 'int (int (*)(float, int), int (*)(char, short))'
140142
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (int (*)(float, int), int (*)(char, short))' cdecl
141143
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (float, int)' cdecl
142-
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... T pack_index 1
144+
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... T pack_index 1{{$}}
143145
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'D'
144-
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar typename depth 0 index 0 ... U pack_index 1
146+
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar typename depth 0 index 0 ... U pack_index 1{{$}}
145147
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'bind'
146148
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (char, short)' cdecl
147-
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar typename depth 0 index 0 ... T pack_index 0
149+
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar typename depth 0 index 0 ... T pack_index 0{{$}}
148150
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'D'
149-
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar typename depth 0 index 0 ... U pack_index 0
151+
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar typename depth 0 index 0 ... U pack_index 0{{$}}
150152
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'bind'
151153
} // namespace PR56099
152154

@@ -156,12 +158,16 @@ template<template<class C1, class C2 = A<C1>> class D1, class D2> using D = D1<D
156158

157159
template<class E1, class E2> class E {};
158160
using test1 = D<E, int>;
159-
// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[1-9]+}}:1, col:23> col:7 test1 'D<E, int>':'subst_default_argument::E<int, subst_default_argument::A<int>>'
161+
// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[0-9]+}}:1, col:23> col:7 test1 'D<E, int>':'subst_default_argument::E<int, subst_default_argument::A<int>>'
160162
// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'A<int>' sugar
161163
// CHECK-NEXT: |-name: 'A':'subst_default_argument::A' qualified
162164
// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} A
163165
// CHECK-NEXT: |-TemplateArgument type 'int'
164-
// CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'int'
166+
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 E1 final
167+
// CHECK-NEXT: | |-ClassTemplate 0x{{[^ ]*}} 'E'
168+
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 1 D2 final
169+
// CHECK-NEXT: | |-TypeAliasTemplate 0x{{[^ ]*}} 'D'
170+
// CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'int'
165171
// CHECK-NEXT: `-RecordType 0x{{[^ ]*}} 'subst_default_argument::A<int>'
166172
// CHECK-NEXT: `-ClassTemplateSpecialization 0x{{[^ ]*}} 'A'
167173
} // namespace subst_default_argument

clang/test/Misc/diag-template-diffing-cxx11.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,14 +265,14 @@ int k9 = f9(V9<double>());
265265
// CHECK-ELIDE-TREE: S9<
266266
// CHECK-ELIDE-TREE: [2 * ...],
267267
// CHECK-ELIDE-TREE: U9<
268-
// CHECK-ELIDE-TREE: [(no qualifiers) != const] double>>
268+
// CHECK-ELIDE-TREE: [double != const double]>>
269269
// CHECK-NOELIDE-TREE: no matching function for call to 'f9'
270270
// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
271271
// CHECK-NOELIDE-TREE: S9<
272272
// CHECK-NOELIDE-TREE: int,
273273
// CHECK-NOELIDE-TREE: char,
274274
// CHECK-NOELIDE-TREE: U9<
275-
// CHECK-NOELIDE-TREE: [(no qualifiers) != const] double>>
275+
// CHECK-NOELIDE-TREE: [double != const double]>>
276276

277277
template<typename ...A> class class_types {};
278278
void set10(class_types<int, int>) {}

clang/test/SemaTemplate/make_integer_seq.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ using test2 = B<int, 1>;
4848
// CHECK-NEXT: |-TemplateArgument template 'A'
4949
// CHECK-NEXT: | `-ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:1, col:41> col:38 A
5050
// CHECK-NEXT: |-TemplateArgument type 'int'
51-
// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
51+
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar class depth 0 index 0 B1 final
52+
// CHECK-NEXT: | |-TypeAliasTemplate 0x{{[0-9A-Fa-f]+}} 'B'
53+
// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
5254
// CHECK-NEXT: |-TemplateArgument expr '1'
5355
// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:64> 'int'
5456
// CHECK-NEXT: | |-value: Int 1
@@ -59,7 +61,9 @@ using test2 = B<int, 1>;
5961
// CHECK-NEXT: |-name: 'A' qualified
6062
// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} A
6163
// CHECK-NEXT: |-TemplateArgument type 'int'
62-
// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
64+
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar class depth 0 index 0 B1 final
65+
// CHECK-NEXT: | |-TypeAliasTemplate 0x{{[0-9A-Fa-f]+}} 'B'
66+
// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
6367
// CHECK-NEXT: |-TemplateArgument expr '0'
6468
// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <line:{{.+}}:64> 'int'
6569
// CHECK-NEXT: | |-value: Int 0

0 commit comments

Comments
 (0)