Skip to content

Commit 789dfa2

Browse files
committed
[clang] Track final substitution for SubstTemplateTypeParmType nodes
1 parent 6745c23 commit 789dfa2

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 {
@@ -6397,7 +6400,8 @@ class SubstTemplateTypeParmType final
63976400
Decl *AssociatedDecl;
63986401

63996402
SubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl,
6400-
unsigned Index, std::optional<unsigned> PackIndex);
6403+
unsigned Index, std::optional<unsigned> PackIndex,
6404+
bool Final);
64016405

64026406
public:
64036407
/// Gets the type that was substituted for the template
@@ -6420,6 +6424,10 @@ class SubstTemplateTypeParmType final
64206424
/// This should match the result of `getReplacedParameter()->getIndex()`.
64216425
unsigned getIndex() const { return SubstTemplateTypeParmTypeBits.Index; }
64226426

6427+
// This substitution is Final, which means the substitution is fully
6428+
// sugared: it doesn't need to be resugared later.
6429+
unsigned getFinal() const { return SubstTemplateTypeParmTypeBits.Final; }
6430+
64236431
std::optional<unsigned> getPackIndex() const {
64246432
if (SubstTemplateTypeParmTypeBits.PackIndex == 0)
64256433
return std::nullopt;
@@ -6431,17 +6439,12 @@ class SubstTemplateTypeParmType final
64316439

64326440
void Profile(llvm::FoldingSetNodeID &ID) {
64336441
Profile(ID, getReplacementType(), getAssociatedDecl(), getIndex(),
6434-
getPackIndex());
6442+
getPackIndex(), getFinal());
64356443
}
64366444

64376445
static void Profile(llvm::FoldingSetNodeID &ID, QualType Replacement,
64386446
const Decl *AssociatedDecl, unsigned Index,
6439-
std::optional<unsigned> PackIndex) {
6440-
Replacement.Profile(ID);
6441-
ID.AddPointer(AssociatedDecl);
6442-
ID.AddInteger(Index);
6443-
ID.AddInteger(PackIndex ? *PackIndex - 1 : 0);
6444-
}
6447+
std::optional<unsigned> PackIndex, bool Final);
64456448

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

clang/include/clang/AST/TypeProperties.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -842,11 +842,11 @@ let Class = SubstTemplateTypeParmType in {
842842
def : Property<"PackIndex", Optional<UInt32>> {
843843
let Read = [{ node->getPackIndex() }];
844844
}
845+
def : Property<"Final", Bool> { let Read = [{ node->getFinal() }]; }
845846

846-
// The call to getCanonicalType here existed in ASTReader.cpp, too.
847847
def : Creator<[{
848848
return ctx.getSubstTemplateTypeParmType(
849-
replacementType, associatedDecl, Index, PackIndex);
849+
replacementType, associatedDecl, Index, PackIndex, Final);
850850
}]>;
851851
}
852852

clang/lib/AST/ASTContext.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5447,10 +5447,10 @@ QualType ASTContext::getHLSLAttributedResourceType(
54475447
/// Retrieve a substitution-result type.
54485448
QualType ASTContext::getSubstTemplateTypeParmType(
54495449
QualType Replacement, Decl *AssociatedDecl, unsigned Index,
5450-
std::optional<unsigned> PackIndex) const {
5450+
std::optional<unsigned> PackIndex, bool Final) const {
54515451
llvm::FoldingSetNodeID ID;
54525452
SubstTemplateTypeParmType::Profile(ID, Replacement, AssociatedDecl, Index,
5453-
PackIndex);
5453+
PackIndex, Final);
54545454
void *InsertPos = nullptr;
54555455
SubstTemplateTypeParmType *SubstParm =
54565456
SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos);
@@ -5460,7 +5460,7 @@ QualType ASTContext::getSubstTemplateTypeParmType(
54605460
!Replacement.isCanonical()),
54615461
alignof(SubstTemplateTypeParmType));
54625462
SubstParm = new (Mem) SubstTemplateTypeParmType(Replacement, AssociatedDecl,
5463-
Index, PackIndex);
5463+
Index, PackIndex, Final);
54645464
Types.push_back(SubstParm);
54655465
SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos);
54665466
}
@@ -14202,7 +14202,8 @@ static QualType getCommonSugarTypeNode(ASTContext &Ctx, const Type *X,
1420214202
if (PackIndex != SY->getPackIndex())
1420314203
return QualType();
1420414204
return Ctx.getSubstTemplateTypeParmType(Ctx.getQualifiedType(Underlying),
14205-
CD, Index, PackIndex);
14205+
CD, Index, PackIndex,
14206+
SX->getFinal() && SY->getFinal());
1420614207
}
1420714208
case Type::ObjCTypeParam:
1420814209
// 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
@@ -2126,6 +2126,8 @@ void TextNodeDumper::VisitSubstTemplateTypeParmType(
21262126
VisitTemplateTypeParmDecl(T->getReplacedParameter());
21272127
if (auto PackIndex = T->getPackIndex())
21282128
OS << " pack_index " << *PackIndex;
2129+
if (T->getFinal())
2130+
OS << " final";
21292131
}
21302132

21312133
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++
@@ -4263,7 +4263,7 @@ static const TemplateTypeParmDecl *getReplacedParameter(Decl *D,
42634263

42644264
SubstTemplateTypeParmType::SubstTemplateTypeParmType(
42654265
QualType Replacement, Decl *AssociatedDecl, unsigned Index,
4266-
std::optional<unsigned> PackIndex)
4266+
std::optional<unsigned> PackIndex, bool Final)
42674267
: Type(SubstTemplateTypeParm, Replacement.getCanonicalType(),
42684268
Replacement->getDependence()),
42694269
AssociatedDecl(AssociatedDecl) {
@@ -4273,6 +4273,7 @@ SubstTemplateTypeParmType::SubstTemplateTypeParmType(
42734273
*getTrailingObjects<QualType>() = Replacement;
42744274

42754275
SubstTemplateTypeParmTypeBits.Index = Index;
4276+
SubstTemplateTypeParmTypeBits.Final = Final;
42764277
SubstTemplateTypeParmTypeBits.PackIndex = PackIndex ? *PackIndex + 1 : 0;
42774278
assert(AssociatedDecl != nullptr);
42784279
}
@@ -4282,6 +4283,19 @@ SubstTemplateTypeParmType::getReplacedParameter() const {
42824283
return ::getReplacedParameter(getAssociatedDecl(), getIndex());
42834284
}
42844285

4286+
void SubstTemplateTypeParmType::Profile(llvm::FoldingSetNodeID &ID,
4287+
QualType Replacement,
4288+
const Decl *AssociatedDecl,
4289+
unsigned Index,
4290+
std::optional<unsigned> PackIndex,
4291+
bool Final) {
4292+
Replacement.Profile(ID);
4293+
ID.AddPointer(AssociatedDecl);
4294+
ID.AddInteger(Index);
4295+
ID.AddInteger(PackIndex ? *PackIndex - 1 : 0);
4296+
ID.AddBoolean(Final);
4297+
}
4298+
42854299
SubstTemplateTypeParmPackType::SubstTemplateTypeParmPackType(
42864300
QualType Canon, Decl *AssociatedDecl, unsigned Index, bool Final,
42874301
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
@@ -7076,7 +7076,8 @@ QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
70767076
return QualType();
70777077

70787078
QualType Result = SemaRef.Context.getSubstTemplateTypeParmType(
7079-
Replacement, NewReplaced, T->getIndex(), T->getPackIndex());
7079+
Replacement, NewReplaced, T->getIndex(), T->getPackIndex(),
7080+
T->getFinal());
70807081

70817082
// Propagate type-source information.
70827083
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)