Skip to content

Commit 4e6d18f

Browse files
authored
[Clang][AST] Track whether template template parameters used the 'typename' keyword (#88139)
This patch adds a `Typename` bit-field to `TemplateTemplateParmDecl` which stores whether the template template parameter was declared with the `typename` keyword.
1 parent f626a35 commit 4e6d18f

File tree

13 files changed

+75
-52
lines changed

13 files changed

+75
-52
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,9 @@ Improvements to Clang's diagnostics
360360
Added the ``-Wtentative-definition-array`` warning group to cover this.
361361
Fixes #GH87766
362362

363+
- Clang now uses the correct type-parameter-key (``class`` or ``typename``) when printing
364+
template template parameter declarations.
365+
363366
Improvements to Clang's time-trace
364367
----------------------------------
365368

@@ -535,6 +538,7 @@ Bug Fixes to C++ Support
535538
Bug Fixes to AST Handling
536539
^^^^^^^^^^^^^^^^^^^^^^^^^
537540
- Clang now properly preserves ``FoundDecls`` within a ``ConceptReference``. (#GH82628)
541+
- The presence of the ``typename`` keyword is now stored in ``TemplateTemplateParmDecl``.
538542

539543
Miscellaneous Bug Fixes
540544
^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/AST/DeclTemplate.h

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,26 +1581,36 @@ class TemplateTemplateParmDecl final
15811581
DefaultArgStorage<TemplateTemplateParmDecl, TemplateArgumentLoc *>;
15821582
DefArgStorage DefaultArgument;
15831583

1584+
/// Whether this template template parameter was declaration with
1585+
/// the 'typename' keyword.
1586+
///
1587+
/// If false, it was declared with the 'class' keyword.
1588+
LLVM_PREFERRED_TYPE(bool)
1589+
unsigned Typename : 1;
1590+
15841591
/// Whether this parameter is a parameter pack.
1585-
bool ParameterPack;
1592+
LLVM_PREFERRED_TYPE(bool)
1593+
unsigned ParameterPack : 1;
15861594

15871595
/// Whether this template template parameter is an "expanded"
15881596
/// parameter pack, meaning that it is a pack expansion and we
15891597
/// already know the set of template parameters that expansion expands to.
1590-
bool ExpandedParameterPack = false;
1598+
LLVM_PREFERRED_TYPE(bool)
1599+
unsigned ExpandedParameterPack : 1;
15911600

15921601
/// The number of parameters in an expanded parameter pack.
15931602
unsigned NumExpandedParams = 0;
15941603

1595-
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
1596-
unsigned D, unsigned P, bool ParameterPack,
1597-
IdentifierInfo *Id, TemplateParameterList *Params)
1604+
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
1605+
unsigned P, bool ParameterPack, IdentifierInfo *Id,
1606+
bool Typename, TemplateParameterList *Params)
15981607
: TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
1599-
TemplateParmPosition(D, P), ParameterPack(ParameterPack) {}
1608+
TemplateParmPosition(D, P), Typename(Typename),
1609+
ParameterPack(ParameterPack), ExpandedParameterPack(false) {}
16001610

1601-
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
1602-
unsigned D, unsigned P,
1603-
IdentifierInfo *Id, TemplateParameterList *Params,
1611+
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
1612+
unsigned P, IdentifierInfo *Id, bool Typename,
1613+
TemplateParameterList *Params,
16041614
ArrayRef<TemplateParameterList *> Expansions);
16051615

16061616
void anchor() override;
@@ -1613,14 +1623,13 @@ class TemplateTemplateParmDecl final
16131623
static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC,
16141624
SourceLocation L, unsigned D,
16151625
unsigned P, bool ParameterPack,
1616-
IdentifierInfo *Id,
1626+
IdentifierInfo *Id, bool Typename,
16171627
TemplateParameterList *Params);
1618-
static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC,
1619-
SourceLocation L, unsigned D,
1620-
unsigned P,
1621-
IdentifierInfo *Id,
1622-
TemplateParameterList *Params,
1623-
ArrayRef<TemplateParameterList *> Expansions);
1628+
static TemplateTemplateParmDecl *
1629+
Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
1630+
unsigned P, IdentifierInfo *Id, bool Typename,
1631+
TemplateParameterList *Params,
1632+
ArrayRef<TemplateParameterList *> Expansions);
16241633

16251634
static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C,
16261635
unsigned ID);
@@ -1634,6 +1643,14 @@ class TemplateTemplateParmDecl final
16341643
using TemplateParmPosition::setPosition;
16351644
using TemplateParmPosition::getIndex;
16361645

1646+
/// Whether this template template parameter was declared with
1647+
/// the 'typename' keyword.
1648+
bool wasDeclaredWithTypename() const { return Typename; }
1649+
1650+
/// Set whether this template template parameter was declared with
1651+
/// the 'typename' or 'class' keyword.
1652+
void setDeclaredWithTypename(bool withTypename) { Typename = withTypename; }
1653+
16371654
/// Whether this template template parameter is a template
16381655
/// parameter pack.
16391656
///

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9064,7 +9064,7 @@ class Sema final : public SemaBase {
90649064
Expr *DefaultArg);
90659065
NamedDecl *ActOnTemplateTemplateParameter(
90669066
Scope *S, SourceLocation TmpLoc, TemplateParameterList *Params,
9067-
SourceLocation EllipsisLoc, IdentifierInfo *ParamName,
9067+
bool Typename, SourceLocation EllipsisLoc, IdentifierInfo *ParamName,
90689068
SourceLocation ParamNameLoc, unsigned Depth, unsigned Position,
90699069
SourceLocation EqualLoc, ParsedTemplateArgument DefaultArg);
90709070

clang/lib/AST/ASTContext.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
799799

800800
TemplateTemplateParmDecl *CanonTTP = TemplateTemplateParmDecl::Create(
801801
*this, getTranslationUnitDecl(), SourceLocation(), TTP->getDepth(),
802-
TTP->getPosition(), TTP->isParameterPack(), nullptr,
802+
TTP->getPosition(), TTP->isParameterPack(), nullptr, /*Typename=*/false,
803803
TemplateParameterList::Create(*this, SourceLocation(), SourceLocation(),
804804
CanonParams, SourceLocation(),
805805
/*RequiresClause=*/nullptr));

clang/lib/AST/ASTImporter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5952,7 +5952,8 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
59525952
ToD, D, Importer.getToContext(),
59535953
Importer.getToContext().getTranslationUnitDecl(), *LocationOrErr,
59545954
D->getDepth(), D->getPosition(), D->isParameterPack(),
5955-
(*NameOrErr).getAsIdentifierInfo(), *TemplateParamsOrErr))
5955+
(*NameOrErr).getAsIdentifierInfo(), D->wasDeclaredWithTypename(),
5956+
*TemplateParamsOrErr))
59565957
return ToD;
59575958

59585959
if (D->hasDefaultArgument()) {

clang/lib/AST/DeclPrinter.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1218,7 +1218,10 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
12181218

12191219
if (const TemplateTemplateParmDecl *TTP =
12201220
dyn_cast<TemplateTemplateParmDecl>(D)) {
1221-
Out << "class";
1221+
if (TTP->wasDeclaredWithTypename())
1222+
Out << "typename";
1223+
else
1224+
Out << "class";
12221225

12231226
if (TTP->isParameterPack())
12241227
Out << " ...";

clang/lib/AST/DeclTemplate.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -805,10 +805,10 @@ void TemplateTemplateParmDecl::anchor() {}
805805

806806
TemplateTemplateParmDecl::TemplateTemplateParmDecl(
807807
DeclContext *DC, SourceLocation L, unsigned D, unsigned P,
808-
IdentifierInfo *Id, TemplateParameterList *Params,
808+
IdentifierInfo *Id, bool Typename, TemplateParameterList *Params,
809809
ArrayRef<TemplateParameterList *> Expansions)
810810
: TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
811-
TemplateParmPosition(D, P), ParameterPack(true),
811+
TemplateParmPosition(D, P), Typename(Typename), ParameterPack(true),
812812
ExpandedParameterPack(true), NumExpandedParams(Expansions.size()) {
813813
if (!Expansions.empty())
814814
std::uninitialized_copy(Expansions.begin(), Expansions.end(),
@@ -819,26 +819,26 @@ TemplateTemplateParmDecl *
819819
TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
820820
SourceLocation L, unsigned D, unsigned P,
821821
bool ParameterPack, IdentifierInfo *Id,
822-
TemplateParameterList *Params) {
822+
bool Typename, TemplateParameterList *Params) {
823823
return new (C, DC) TemplateTemplateParmDecl(DC, L, D, P, ParameterPack, Id,
824-
Params);
824+
Typename, Params);
825825
}
826826

827827
TemplateTemplateParmDecl *
828828
TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
829829
SourceLocation L, unsigned D, unsigned P,
830-
IdentifierInfo *Id,
830+
IdentifierInfo *Id, bool Typename,
831831
TemplateParameterList *Params,
832832
ArrayRef<TemplateParameterList *> Expansions) {
833833
return new (C, DC,
834834
additionalSizeToAlloc<TemplateParameterList *>(Expansions.size()))
835-
TemplateTemplateParmDecl(DC, L, D, P, Id, Params, Expansions);
835+
TemplateTemplateParmDecl(DC, L, D, P, Id, Typename, Params, Expansions);
836836
}
837837

838838
TemplateTemplateParmDecl *
839839
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
840840
return new (C, ID) TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0,
841-
false, nullptr, nullptr);
841+
false, nullptr, false, nullptr);
842842
}
843843

844844
TemplateTemplateParmDecl *
@@ -847,7 +847,7 @@ TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
847847
auto *TTP =
848848
new (C, ID, additionalSizeToAlloc<TemplateParameterList *>(NumExpansions))
849849
TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, nullptr,
850-
nullptr, std::nullopt);
850+
false, nullptr, std::nullopt);
851851
TTP->NumExpandedParams = NumExpansions;
852852
return TTP;
853853
}
@@ -1469,7 +1469,7 @@ createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
14691469
// template <typename T, ...Ints> class IntSeq
14701470
auto *TemplateTemplateParm = TemplateTemplateParmDecl::Create(
14711471
C, DC, SourceLocation(), /*Depth=*/0, /*Position=*/0,
1472-
/*ParameterPack=*/false, /*Id=*/nullptr, TPL);
1472+
/*ParameterPack=*/false, /*Id=*/nullptr, /*Typename=*/false, TPL);
14731473
TemplateTemplateParm->setImplicit(true);
14741474

14751475
// typename T

clang/lib/Parse/ParseTemplate.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -805,10 +805,12 @@ NamedDecl *Parser::ParseTemplateTemplateParameter(unsigned Depth,
805805
// identifier, comma, or greater. Provide a fixit if the identifier, comma,
806806
// or greater appear immediately or after 'struct'. In the latter case,
807807
// replace the keyword with 'class'.
808+
bool TypenameKeyword = false;
808809
if (!TryConsumeToken(tok::kw_class)) {
809810
bool Replace = Tok.isOneOf(tok::kw_typename, tok::kw_struct);
810811
const Token &Next = Tok.is(tok::kw_struct) ? NextToken() : Tok;
811812
if (Tok.is(tok::kw_typename)) {
813+
TypenameKeyword = true;
812814
Diag(Tok.getLocation(),
813815
getLangOpts().CPlusPlus17
814816
? diag::warn_cxx14_compat_template_template_param_typename
@@ -878,10 +880,9 @@ NamedDecl *Parser::ParseTemplateTemplateParameter(unsigned Depth,
878880
}
879881
}
880882

881-
return Actions.ActOnTemplateTemplateParameter(getCurScope(), TemplateLoc,
882-
ParamList, EllipsisLoc,
883-
ParamName, NameLoc, Depth,
884-
Position, EqualLoc, DefaultArg);
883+
return Actions.ActOnTemplateTemplateParameter(
884+
getCurScope(), TemplateLoc, ParamList, TypenameKeyword, EllipsisLoc,
885+
ParamName, NameLoc, Depth, Position, EqualLoc, DefaultArg);
885886
}
886887

887888
/// ParseNonTypeTemplateParameter - Handle the parsing of non-type

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1630,26 +1630,20 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
16301630
/// ActOnTemplateTemplateParameter - Called when a C++ template template
16311631
/// parameter (e.g. T in template <template \<typename> class T> class array)
16321632
/// has been parsed. S is the current scope.
1633-
NamedDecl *Sema::ActOnTemplateTemplateParameter(Scope* S,
1634-
SourceLocation TmpLoc,
1635-
TemplateParameterList *Params,
1636-
SourceLocation EllipsisLoc,
1637-
IdentifierInfo *Name,
1638-
SourceLocation NameLoc,
1639-
unsigned Depth,
1640-
unsigned Position,
1641-
SourceLocation EqualLoc,
1642-
ParsedTemplateArgument Default) {
1633+
NamedDecl *Sema::ActOnTemplateTemplateParameter(
1634+
Scope *S, SourceLocation TmpLoc, TemplateParameterList *Params,
1635+
bool Typename, SourceLocation EllipsisLoc, IdentifierInfo *Name,
1636+
SourceLocation NameLoc, unsigned Depth, unsigned Position,
1637+
SourceLocation EqualLoc, ParsedTemplateArgument Default) {
16431638
assert(S->isTemplateParamScope() &&
16441639
"Template template parameter not in template parameter scope!");
16451640

16461641
// Construct the parameter object.
16471642
bool IsParameterPack = EllipsisLoc.isValid();
1648-
TemplateTemplateParmDecl *Param =
1649-
TemplateTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
1650-
NameLoc.isInvalid()? TmpLoc : NameLoc,
1651-
Depth, Position, IsParameterPack,
1652-
Name, Params);
1643+
TemplateTemplateParmDecl *Param = TemplateTemplateParmDecl::Create(
1644+
Context, Context.getTranslationUnitDecl(),
1645+
NameLoc.isInvalid() ? TmpLoc : NameLoc, Depth, Position, IsParameterPack,
1646+
Name, Typename, Params);
16531647
Param->setAccess(AS_public);
16541648

16551649
if (Param->isParameterPack())

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3233,12 +3233,14 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
32333233
Param = TemplateTemplateParmDecl::Create(
32343234
SemaRef.Context, Owner, D->getLocation(),
32353235
D->getDepth() - TemplateArgs.getNumSubstitutedLevels(),
3236-
D->getPosition(), D->getIdentifier(), InstParams, ExpandedParams);
3236+
D->getPosition(), D->getIdentifier(), D->wasDeclaredWithTypename(),
3237+
InstParams, ExpandedParams);
32373238
else
32383239
Param = TemplateTemplateParmDecl::Create(
32393240
SemaRef.Context, Owner, D->getLocation(),
32403241
D->getDepth() - TemplateArgs.getNumSubstitutedLevels(),
3241-
D->getPosition(), D->isParameterPack(), D->getIdentifier(), InstParams);
3242+
D->getPosition(), D->isParameterPack(), D->getIdentifier(),
3243+
D->wasDeclaredWithTypename(), InstParams);
32423244
if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) {
32433245
NestedNameSpecifierLoc QualifierLoc =
32443246
D->getDefaultArgument().getTemplateQualifierLoc();

clang/lib/Serialization/ASTReaderDecl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2715,6 +2715,7 @@ void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
27152715

27162716
void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
27172717
VisitTemplateDecl(D);
2718+
D->setDeclaredWithTypename(Record.readBool());
27182719
// TemplateParmPosition.
27192720
D->setDepth(Record.readInt());
27202721
D->setPosition(Record.readInt());

clang/lib/Serialization/ASTWriterDecl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1921,6 +1921,7 @@ void ASTDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
19211921
Record.push_back(D->getNumExpansionTemplateParameters());
19221922

19231923
VisitTemplateDecl(D);
1924+
Record.push_back(D->wasDeclaredWithTypename());
19241925
// TemplateParmPosition.
19251926
Record.push_back(D->getDepth());
19261927
Record.push_back(D->getPosition());

clang/unittests/AST/DeclPrinterTest.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,8 +1220,7 @@ TEST(DeclPrinter, TestTemplateTemplateParameterWrittenWithTypename) {
12201220
ASSERT_TRUE(PrintedDeclCXX17Matches(
12211221
"template <template <typename> typename Z> void A();",
12221222
functionTemplateDecl(hasName("A")).bind("id"),
1223-
"template <template <typename> class Z> void A()"));
1224-
// WRONG: We should use typename if the parameter was written with it.
1223+
"template <template <typename> typename Z> void A()"));
12251224
}
12261225

12271226
TEST(DeclPrinter, TestTemplateArgumentList1) {

0 commit comments

Comments
 (0)