Skip to content

Commit a3a9dd9

Browse files
committed
[Clang][AST] Track whether template template parameters used the 'typename' keyword
1 parent 4657ab1 commit a3a9dd9

File tree

13 files changed

+69
-52
lines changed

13 files changed

+69
-52
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,7 @@ Bug Fixes to C++ Support
517517
Bug Fixes to AST Handling
518518
^^^^^^^^^^^^^^^^^^^^^^^^^
519519
- Clang now properly preserves ``FoundDecls`` within a ``ConceptReference``. (#GH82628)
520+
- The presence of the ``typename`` keyword is now stored in ``TemplateTemplateParmDecl``.
520521

521522
Miscellaneous Bug Fixes
522523
^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/AST/DeclTemplate.h

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,26 +1581,33 @@ 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+
bool Typename : 1;
1589+
15841590
/// Whether this parameter is a parameter pack.
1585-
bool ParameterPack;
1591+
bool ParameterPack : 1;
15861592

15871593
/// Whether this template template parameter is an "expanded"
15881594
/// parameter pack, meaning that it is a pack expansion and we
15891595
/// already know the set of template parameters that expansion expands to.
1590-
bool ExpandedParameterPack = false;
1596+
bool ExpandedParameterPack : 1;
15911597

15921598
/// The number of parameters in an expanded parameter pack.
15931599
unsigned NumExpandedParams = 0;
15941600

1595-
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
1596-
unsigned D, unsigned P, bool ParameterPack,
1597-
IdentifierInfo *Id, TemplateParameterList *Params)
1601+
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
1602+
unsigned P, bool ParameterPack, IdentifierInfo *Id,
1603+
bool Typename, TemplateParameterList *Params)
15981604
: TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
1599-
TemplateParmPosition(D, P), ParameterPack(ParameterPack) {}
1605+
TemplateParmPosition(D, P), Typename(Typename),
1606+
ParameterPack(ParameterPack), ExpandedParameterPack(false) {}
16001607

1601-
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
1602-
unsigned D, unsigned P,
1603-
IdentifierInfo *Id, TemplateParameterList *Params,
1608+
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
1609+
unsigned P, IdentifierInfo *Id, bool Typename,
1610+
TemplateParameterList *Params,
16041611
ArrayRef<TemplateParameterList *> Expansions);
16051612

16061613
void anchor() override;
@@ -1613,14 +1620,13 @@ class TemplateTemplateParmDecl final
16131620
static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC,
16141621
SourceLocation L, unsigned D,
16151622
unsigned P, bool ParameterPack,
1616-
IdentifierInfo *Id,
1623+
IdentifierInfo *Id, bool Typename,
16171624
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);
1625+
static TemplateTemplateParmDecl *
1626+
Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
1627+
unsigned P, IdentifierInfo *Id, bool Typename,
1628+
TemplateParameterList *Params,
1629+
ArrayRef<TemplateParameterList *> Expansions);
16241630

16251631
static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C,
16261632
unsigned ID);
@@ -1634,6 +1640,14 @@ class TemplateTemplateParmDecl final
16341640
using TemplateParmPosition::setPosition;
16351641
using TemplateParmPosition::getIndex;
16361642

1643+
/// Whether this template template parameter was declared with
1644+
/// the 'typename' keyword.
1645+
bool wasDeclaredWithTypename() const { return Typename; }
1646+
1647+
/// Set whether this template template parameter was declared with
1648+
/// the 'typename' or 'class' keyword.
1649+
void setDeclaredWithTypename(bool withTypename) { Typename = withTypename; }
1650+
16371651
/// Whether this template template parameter is a template
16381652
/// parameter pack.
16391653
///

clang/include/clang/Sema/Sema.h

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

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
@@ -807,10 +807,10 @@ void TemplateTemplateParmDecl::anchor() {}
807807

808808
TemplateTemplateParmDecl::TemplateTemplateParmDecl(
809809
DeclContext *DC, SourceLocation L, unsigned D, unsigned P,
810-
IdentifierInfo *Id, TemplateParameterList *Params,
810+
IdentifierInfo *Id, bool Typename, TemplateParameterList *Params,
811811
ArrayRef<TemplateParameterList *> Expansions)
812812
: TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
813-
TemplateParmPosition(D, P), ParameterPack(true),
813+
TemplateParmPosition(D, P), Typename(Typename), ParameterPack(true),
814814
ExpandedParameterPack(true), NumExpandedParams(Expansions.size()) {
815815
if (!Expansions.empty())
816816
std::uninitialized_copy(Expansions.begin(), Expansions.end(),
@@ -821,26 +821,26 @@ TemplateTemplateParmDecl *
821821
TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
822822
SourceLocation L, unsigned D, unsigned P,
823823
bool ParameterPack, IdentifierInfo *Id,
824-
TemplateParameterList *Params) {
824+
bool Typename, TemplateParameterList *Params) {
825825
return new (C, DC) TemplateTemplateParmDecl(DC, L, D, P, ParameterPack, Id,
826-
Params);
826+
Typename, Params);
827827
}
828828

829829
TemplateTemplateParmDecl *
830830
TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
831831
SourceLocation L, unsigned D, unsigned P,
832-
IdentifierInfo *Id,
832+
IdentifierInfo *Id, bool Typename,
833833
TemplateParameterList *Params,
834834
ArrayRef<TemplateParameterList *> Expansions) {
835835
return new (C, DC,
836836
additionalSizeToAlloc<TemplateParameterList *>(Expansions.size()))
837-
TemplateTemplateParmDecl(DC, L, D, P, Id, Params, Expansions);
837+
TemplateTemplateParmDecl(DC, L, D, P, Id, Typename, Params, Expansions);
838838
}
839839

840840
TemplateTemplateParmDecl *
841841
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
842842
return new (C, ID) TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0,
843-
false, nullptr, nullptr);
843+
false, nullptr, false, nullptr);
844844
}
845845

846846
TemplateTemplateParmDecl *
@@ -849,7 +849,7 @@ TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
849849
auto *TTP =
850850
new (C, ID, additionalSizeToAlloc<TemplateParameterList *>(NumExpansions))
851851
TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, nullptr,
852-
nullptr, std::nullopt);
852+
false, nullptr, std::nullopt);
853853
TTP->NumExpandedParams = NumExpansions;
854854
return TTP;
855855
}
@@ -1471,7 +1471,7 @@ createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
14711471
// template <typename T, ...Ints> class IntSeq
14721472
auto *TemplateTemplateParm = TemplateTemplateParmDecl::Create(
14731473
C, DC, SourceLocation(), /*Depth=*/0, /*Position=*/0,
1474-
/*ParameterPack=*/false, /*Id=*/nullptr, TPL);
1474+
/*ParameterPack=*/false, /*Id=*/nullptr, /*Typename=*/false, TPL);
14751475
TemplateTemplateParm->setImplicit(true);
14761476

14771477
// 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)