[clang] 1234b1c - [AST] Support template declaration found through using-decl for QualifiedTemplateName.
Haojian Wu via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 21 01:53:35 PDT 2022
Author: Haojian Wu
Date: 2022-04-21T10:53:23+02:00
New Revision: 1234b1c6d8113d50beef5801be607ad1d502b2f7
URL: https://github.com/llvm/llvm-project/commit/1234b1c6d8113d50beef5801be607ad1d502b2f7
DIFF: https://github.com/llvm/llvm-project/commit/1234b1c6d8113d50beef5801be607ad1d502b2f7.diff
LOG: [AST] Support template declaration found through using-decl for QualifiedTemplateName.
This is a followup of https://reviews.llvm.org/D123127, adding support
for the QualifiedTemplateName.
Reviewed By: sammccall
Differential Revision: https://reviews.llvm.org/D123775
Added:
Modified:
clang/include/clang/AST/ASTContext.h
clang/include/clang/AST/PropertiesBase.td
clang/include/clang/AST/TemplateName.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/ASTImporter.cpp
clang/lib/AST/QualTypeNames.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/lib/Sema/TreeTransform.h
clang/unittests/AST/TemplateNameTest.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 9e10571740de4..03d6a0fbe6eea 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2182,7 +2182,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
bool TemplateKeyword,
- TemplateDecl *Template) const;
+ TemplateName Template) const;
TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
const IdentifierInfo *Name) const;
diff --git a/clang/include/clang/AST/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td
index 0ab18b6d59c3d..559f29edcf0fe 100644
--- a/clang/include/clang/AST/PropertiesBase.td
+++ b/clang/include/clang/AST/PropertiesBase.td
@@ -663,12 +663,12 @@ let Class = PropertyTypeCase<TemplateName, "QualifiedTemplate"> in {
def : Property<"hasTemplateKeyword", Bool> {
let Read = [{ qtn->hasTemplateKeyword() }];
}
- def : Property<"declaration", TemplateDeclRef> {
- let Read = [{ qtn->getTemplateDecl() }];
+ def : Property<"underlyingTemplateName", TemplateName> {
+ let Read = [{ qtn->getUnderlyingTemplate() }];
}
def : Creator<[{
return ctx.getQualifiedTemplateName(qualifier, hasTemplateKeyword,
- declaration);
+ underlyingTemplateName);
}]>;
}
let Class = PropertyTypeCase<TemplateName, "DependentTemplate"> in {
diff --git a/clang/include/clang/AST/TemplateName.h b/clang/include/clang/AST/TemplateName.h
index 1bd86b0bdcf11..b6f4332830c8f 100644
--- a/clang/include/clang/AST/TemplateName.h
+++ b/clang/include/clang/AST/TemplateName.h
@@ -414,13 +414,19 @@ class QualifiedTemplateName : public llvm::FoldingSetNode {
/// this name with DependentTemplateName).
llvm::PointerIntPair<NestedNameSpecifier *, 1> Qualifier;
- /// The template declaration or set of overloaded function templates
- /// that this qualified name refers to.
- TemplateDecl *Template;
+ /// The underlying template name, it is either
+ /// 1) a Template -- a template declaration that this qualified name refers
+ /// to.
+ /// 2) or a UsingTemplate -- a template declaration introduced by a
+ /// using-shadow declaration.
+ TemplateName UnderlyingTemplate;
QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword,
- TemplateDecl *Template)
- : Qualifier(NNS, TemplateKeyword? 1 : 0), Template(Template) {}
+ TemplateName Template)
+ : Qualifier(NNS, TemplateKeyword ? 1 : 0), UnderlyingTemplate(Template) {
+ assert(UnderlyingTemplate.getKind() == TemplateName::Template ||
+ UnderlyingTemplate.getKind() == TemplateName::UsingTemplate);
+ }
public:
/// Return the nested name specifier that qualifies this name.
@@ -430,19 +436,25 @@ class QualifiedTemplateName : public llvm::FoldingSetNode {
/// keyword.
bool hasTemplateKeyword() const { return Qualifier.getInt(); }
+ /// Return the underlying template name.
+ TemplateName getUnderlyingTemplate() const { return UnderlyingTemplate; }
+
/// The template declaration to which this qualified name
/// refers.
- TemplateDecl *getTemplateDecl() const { return Template; }
+ /// FIXME: remove this and use getUnderlyingTemplate() instead.
+ TemplateDecl *getTemplateDecl() const {
+ return UnderlyingTemplate.getAsTemplateDecl();
+ }
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getQualifier(), hasTemplateKeyword(), getTemplateDecl());
+ Profile(ID, getQualifier(), hasTemplateKeyword(), UnderlyingTemplate);
}
static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
- bool TemplateKeyword, TemplateDecl *Template) {
+ bool TemplateKeyword, TemplateName TN) {
ID.AddPointer(NNS);
ID.AddBoolean(TemplateKeyword);
- ID.AddPointer(Template);
+ ID.AddPointer(TN.getAsVoidPointer());
}
};
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index dacc4f3ae855e..eb8d53a20012b 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -4859,11 +4859,10 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
"No dependent template names here!");
// Look through qualified template names.
if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
- Template = TemplateName(QTN->getTemplateDecl());
+ Template = QTN->getUnderlyingTemplate();
bool IsTypeAlias =
- Template.getAsTemplateDecl() &&
- isa<TypeAliasTemplateDecl>(Template.getAsTemplateDecl());
+ isa_and_nonnull<TypeAliasTemplateDecl>(Template.getAsTemplateDecl());
QualType CanonType;
if (!Underlying.isNull())
CanonType = getCanonicalType(Underlying);
@@ -4915,7 +4914,7 @@ QualType ASTContext::getCanonicalTemplateSpecializationType(
// Look through qualified template names.
if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
- Template = TemplateName(QTN->getTemplateDecl());
+ Template = TemplateName(QTN->getUnderlyingTemplate());
// Build the canonical template specialization type.
TemplateName CanonTemplate = getCanonicalTemplateName(Template);
@@ -8978,10 +8977,9 @@ TemplateName ASTContext::getAssumedTemplateName(DeclarationName Name) const {
/// Retrieve the template name that represents a qualified
/// template name such as \c std::vector.
-TemplateName
-ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS,
- bool TemplateKeyword,
- TemplateDecl *Template) const {
+TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS,
+ bool TemplateKeyword,
+ TemplateName Template) const {
assert(NNS && "Missing nested-name-specifier in qualified template name");
// FIXME: Canonicalization?
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 319f39b43264c..537ccc22ed050 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -9185,13 +9185,11 @@ Expected<TemplateName> ASTImporter::Import(TemplateName From) {
auto QualifierOrErr = Import(QTN->getQualifier());
if (!QualifierOrErr)
return QualifierOrErr.takeError();
-
- if (ExpectedDecl ToTemplateOrErr = Import(From.getAsTemplateDecl()))
- return ToContext.getQualifiedTemplateName(
- *QualifierOrErr, QTN->hasTemplateKeyword(),
- cast<TemplateDecl>(*ToTemplateOrErr));
- else
- return ToTemplateOrErr.takeError();
+ auto TNOrErr = Import(QTN->getUnderlyingTemplate());
+ if (!TNOrErr)
+ return TNOrErr.takeError();
+ return ToContext.getQualifiedTemplateName(
+ *QualifierOrErr, QTN->hasTemplateKeyword(), *TNOrErr);
}
case TemplateName::DependentTemplate: {
diff --git a/clang/lib/AST/QualTypeNames.cpp b/clang/lib/AST/QualTypeNames.cpp
index 561757b1ba645..26aaa96a1dc68 100644
--- a/clang/lib/AST/QualTypeNames.cpp
+++ b/clang/lib/AST/QualTypeNames.cpp
@@ -80,8 +80,12 @@ static bool getFullyQualifiedTemplateName(const ASTContext &Ctx,
Ctx, ArgTDecl, true, WithGlobalNsPrefix);
}
if (NNS) {
- TName = Ctx.getQualifiedTemplateName(NNS,
- /*TemplateKeyword=*/false, ArgTDecl);
+ TemplateName UnderlyingTN(ArgTDecl);
+ if (UsingShadowDecl *USD = TName.getAsUsingShadowDecl())
+ UnderlyingTN = TemplateName(USD);
+ TName =
+ Ctx.getQualifiedTemplateName(NNS,
+ /*TemplateKeyword=*/false, UnderlyingTN);
Changed = true;
}
return Changed;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index a854de6479781..250a553c414ea 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1114,18 +1114,14 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS,
UsingShadowDecl *FoundUsingShadow =
dyn_cast<UsingShadowDecl>(*Result.begin());
-
- if (SS.isNotEmpty()) {
- // FIXME: support using shadow-declaration in qualified template name.
- Template =
- Context.getQualifiedTemplateName(SS.getScopeRep(),
- /*TemplateKeyword=*/false, TD);
- } else {
- assert(!FoundUsingShadow ||
- TD == cast<TemplateDecl>(FoundUsingShadow->getTargetDecl()));
- Template = FoundUsingShadow ? TemplateName(FoundUsingShadow)
- : TemplateName(TD);
- }
+ assert(!FoundUsingShadow ||
+ TD == cast<TemplateDecl>(FoundUsingShadow->getTargetDecl()));
+ Template =
+ FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD);
+ if (SS.isNotEmpty())
+ Template = Context.getQualifiedTemplateName(SS.getScopeRep(),
+ /*TemplateKeyword=*/false,
+ Template);
} else {
// All results were non-template functions. This is a function template
// name.
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e7195edc9a268..4a42969c34d3f 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -284,17 +284,13 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
}
TemplateDecl *TD = cast<TemplateDecl>(D);
-
+ Template =
+ FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD);
+ assert(!FoundUsingShadow || FoundUsingShadow->getTargetDecl() == TD);
if (SS.isSet() && !SS.isInvalid()) {
NestedNameSpecifier *Qualifier = SS.getScopeRep();
- // FIXME: store the using TemplateName in QualifiedTemplateName if
- // the TD is referred via a using-declaration.
- Template =
- Context.getQualifiedTemplateName(Qualifier, hasTemplateKeyword, TD);
- } else {
- Template =
- FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD);
- assert(!FoundUsingShadow || FoundUsingShadow->getTargetDecl() == TD);
+ Template = Context.getQualifiedTemplateName(Qualifier, hasTemplateKeyword,
+ Template);
}
if (isa<FunctionTemplateDecl>(TD)) {
@@ -1005,8 +1001,8 @@ ParsedTemplateArgument Sema::ActOnTemplateTypeArgument(TypeResult ParsedType) {
TemplateName Name = DTST.getTypePtr()->getTemplateName();
if (SS.isSet())
Name = Context.getQualifiedTemplateName(SS.getScopeRep(),
- /*HasTemplateKeyword*/ false,
- Name.getAsTemplateDecl());
+ /*HasTemplateKeyword=*/false,
+ Name);
ParsedTemplateArgument Result(SS, TemplateTy::make(Name),
DTST.getTemplateNameLoc());
if (EllipsisLoc.isValid())
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 5eff7cfd7a253..282163cf4c923 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -14714,7 +14714,7 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
bool TemplateKW,
TemplateDecl *Template) {
return SemaRef.Context.getQualifiedTemplateName(SS.getScopeRep(), TemplateKW,
- Template);
+ TemplateName(Template));
}
template<typename Derived>
diff --git a/clang/unittests/AST/TemplateNameTest.cpp b/clang/unittests/AST/TemplateNameTest.cpp
index 30986920ce28e..5844af6cc957f 100644
--- a/clang/unittests/AST/TemplateNameTest.cpp
+++ b/clang/unittests/AST/TemplateNameTest.cpp
@@ -58,5 +58,69 @@ TEST(TemplateName, PrintUsingTemplate) {
"vector");
}
+TEST(TemplateName, QualifiedUsingTemplate) {
+ std::string Code = R"cpp(
+ namespace std {
+ template <typename> struct vector {};
+ }
+ namespace absl { using std::vector; }
+
+ template<template <typename> class T> class X;
+
+ using A = X<absl::vector>; // QualifiedTemplateName in a template argument.
+ )cpp";
+ auto AST = tooling::buildASTFromCode(Code);
+ // Match the template argument absl::vector in X<absl::vector>.
+ auto Matcher = templateArgumentLoc().bind("id");
+ auto MatchResults = match(Matcher, AST->getASTContext());
+ const auto *TAL = MatchResults.front().getNodeAs<TemplateArgumentLoc>("id");
+ ASSERT_TRUE(TAL);
+ TemplateName TN = TAL->getArgument().getAsTemplate();
+ EXPECT_EQ(TN.getKind(), TemplateName::QualifiedTemplate);
+ const auto *QTN = TN.getAsQualifiedTemplateName();
+ // Verify that we have the Using template name in the QualifiedTemplateName.
+ const auto *USD = QTN->getUnderlyingTemplate().getAsUsingShadowDecl();
+ EXPECT_TRUE(USD);
+ EXPECT_EQ(USD->getTargetDecl(), TN.getAsTemplateDecl());
+}
+
+TEST(TemplateName, UsingTemplate) {
+ auto AST = tooling::buildASTFromCode(R"cpp(
+ namespace std {
+ template <typename T> struct vector { vector(T); };
+ }
+ namespace absl { using std::vector; }
+ // The "absl::vector<int>" is an elaborated TemplateSpecializationType with
+ // an inner Using TemplateName (not a Qualified TemplateName, the qualifiers
+ // are rather part of the ElaboratedType)!
+ absl::vector<int> v(123);
+ )cpp");
+ auto Matcher = elaboratedTypeLoc(
+ hasNamedTypeLoc(loc(templateSpecializationType().bind("id"))));
+ auto MatchResults = match(Matcher, AST->getASTContext());
+ const auto *TST =
+ MatchResults.front().getNodeAs<TemplateSpecializationType>("id");
+ ASSERT_TRUE(TST);
+ EXPECT_EQ(TST->getTemplateName().getKind(), TemplateName::UsingTemplate);
+
+ AST = tooling::buildASTFromCodeWithArgs(R"cpp(
+ namespace std {
+ template <typename T> struct vector { vector(T); };
+ }
+ namespace absl { using std::vector; }
+ // Similiar to the TemplateSpecializationType, absl::vector is an elaborated
+ // DeducedTemplateSpecializationType with an inner Using TemplateName!
+ absl::vector DTST(123);
+ )cpp",
+ {"-std=c++17"});
+ Matcher = elaboratedTypeLoc(
+ hasNamedTypeLoc(loc(deducedTemplateSpecializationType().bind("id"))));
+ MatchResults = match(Matcher, AST->getASTContext());
+ const auto *DTST =
+ MatchResults.front().getNodeAs<DeducedTemplateSpecializationType>("id");
+ ASSERT_TRUE(DTST);
+ EXPECT_EQ(DTST->getTemplateName().getKind(), TemplateName::UsingTemplate);
+}
+
} // namespace
} // namespace clang
More information about the cfe-commits
mailing list