hokein created this revision.
hokein added a reviewer: sammccall.
Herald added a subscriber: martong.
Herald added a reviewer: shafik.
Herald added a project: All.
hokein requested review of this revision.
Herald added a project: clang.

This is a followup of https://reviews.llvm.org/D123127, adding support
for the QualifiedTemplateName.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D123775

Files:
  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

Index: clang/unittests/AST/TemplateNameTest.cpp
===================================================================
--- clang/unittests/AST/TemplateNameTest.cpp
+++ clang/unittests/AST/TemplateNameTest.cpp
@@ -58,5 +58,66 @@
             "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 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.
+  EXPECT_TRUE(QTN->getUsingShadowDecl());
+  EXPECT_EQ(QTN->getUsingShadowDecl()->getTargetDecl(), TN.getAsTemplateDecl());
+}
+
+TEST(TemplateName, UsingTemplate) {
+  auto AST = tooling::buildASTFromCode(R"cpp(
+    namespace std {
+      template <typename T> struct vector { public: vector(T); };
+    }
+    namespace absl { using std::vector; }
+    // absl::vector is a TemplateSpecializationType with an inner Using
+    // TemplateName (not a Qualified TemplateName, the qualifiers are
+    // stripped when constructing the TemplateSpecializationType)!
+    absl::vector<int>* Ptr;
+  )cpp");
+  auto Matcher = typeLoc(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 { public: vector(T); };
+    }
+    namespace absl { using std::vector; }
+    // Similiar to the TemplateSpecializationType, absl::vector is a
+    // DeducedTemplateSpecializationType with an inner Using TemplateName!
+    absl::vector DTST(123);
+    )cpp",
+                                          {"-std=c++17"});
+  Matcher = typeLoc(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
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -14714,7 +14714,7 @@
                                             bool TemplateKW,
                                             TemplateDecl *Template) {
   return SemaRef.Context.getQualifiedTemplateName(SS.getScopeRep(), TemplateKW,
-                                                  Template);
+                                                  TemplateName(Template));
 }
 
 template<typename Derived>
Index: clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -284,17 +284,13 @@
     }
 
     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)) {
@@ -1006,7 +1002,7 @@
       if (SS.isSet())
         Name = Context.getQualifiedTemplateName(SS.getScopeRep(),
                                                 /*HasTemplateKeyword*/ false,
-                                                Name.getAsTemplateDecl());
+                                                Name);
       ParsedTemplateArgument Result(SS, TemplateTy::make(Name),
                                     DTST.getTemplateNameLoc());
       if (EllipsisLoc.isValid())
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -1111,18 +1111,14 @@
 
       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.
Index: clang/lib/AST/QualTypeNames.cpp
===================================================================
--- clang/lib/AST/QualTypeNames.cpp
+++ clang/lib/AST/QualTypeNames.cpp
@@ -80,8 +80,12 @@
         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;
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -9185,11 +9185,19 @@
     auto QualifierOrErr = Import(QTN->getQualifier());
     if (!QualifierOrErr)
       return QualifierOrErr.takeError();
+    if (UsingShadowDecl *USD = QTN->getUsingShadowDecl()) {
+      if (ExpectedDecl ToUSDOrErr = Import(USD))
+        return ToContext.getQualifiedTemplateName(
+            *QualifierOrErr, QTN->hasTemplateKeyword(),
+            TemplateName(cast<UsingShadowDecl>(*ToUSDOrErr)));
+      else
+        return ToUSDOrErr.takeError();
+    }
 
     if (ExpectedDecl ToTemplateOrErr = Import(From.getAsTemplateDecl()))
       return ToContext.getQualifiedTemplateName(
           *QualifierOrErr, QTN->hasTemplateKeyword(),
-          cast<TemplateDecl>(*ToTemplateOrErr));
+          TemplateName(cast<TemplateDecl>(*ToTemplateOrErr)));
     else
       return ToTemplateOrErr.takeError();
   }
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -4851,12 +4851,15 @@
   assert(!Template.getAsDependentTemplateName() &&
          "No dependent template names here!");
   // Look through qualified template names.
-  if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
-    Template = TemplateName(QTN->getTemplateDecl());
+  if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) {
+    if (UsingShadowDecl *USD = QTN->getUsingShadowDecl())
+      Template = TemplateName(USD);
+    else
+      Template = TemplateName(QTN->getTemplateDecl());
+  }
 
   bool IsTypeAlias =
-    Template.getAsTemplateDecl() &&
-    isa<TypeAliasTemplateDecl>(Template.getAsTemplateDecl());
+      isa_and_nonnull<TypeAliasTemplateDecl>(Template.getAsTemplateDecl());
   QualType CanonType;
   if (!Underlying.isNull())
     CanonType = getCanonicalType(Underlying);
@@ -4907,8 +4910,12 @@
          "No dependent template names here!");
 
   // Look through qualified template names.
-  if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
-    Template = TemplateName(QTN->getTemplateDecl());
+  if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) {
+    if (UsingShadowDecl *USD = QTN->getUsingShadowDecl())
+      Template = TemplateName(USD);
+    else
+      Template = TemplateName(QTN->getTemplateDecl());
+  }
 
   // Build the canonical template specialization type.
   TemplateName CanonTemplate = getCanonicalTemplateName(Template);
@@ -8971,15 +8978,15 @@
 
 /// 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?
   llvm::FoldingSetNodeID ID;
-  QualifiedTemplateName::Profile(ID, NNS, TemplateKeyword, Template);
+  QualifiedTemplateName::Profile(ID, NNS, TemplateKeyword,
+                                 TemplateName(Template));
 
   void *InsertPos = nullptr;
   QualifiedTemplateName *QTN =
Index: clang/include/clang/AST/TemplateName.h
===================================================================
--- clang/include/clang/AST/TemplateName.h
+++ clang/include/clang/AST/TemplateName.h
@@ -414,13 +414,16 @@
   /// 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 TemplateName -- a template declaration or set of overloaded
+  //     function templates that this qualified name refers to.
+  //  2) or a UsingTemplate TemplateName -- 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) {}
 
 public:
   /// Return the nested name specifier that qualifies this name.
@@ -432,17 +435,25 @@
 
   /// The template declaration to which this qualified name
   /// refers.
-  TemplateDecl *getTemplateDecl() const { return Template; }
+  TemplateDecl *getTemplateDecl() const {
+    return UnderlyingTemplate.getAsTemplateDecl();
+  }
+
+  /// If the underlying template declaration is found through a using-shadow
+  /// declaration, returns the using-shadow declaration.
+  UsingShadowDecl *getUsingShadowDecl() const {
+    return UnderlyingTemplate.getAsUsingShadowDecl();
+  }
 
   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());
   }
 };
 
Index: clang/include/clang/AST/PropertiesBase.td
===================================================================
--- clang/include/clang/AST/PropertiesBase.td
+++ clang/include/clang/AST/PropertiesBase.td
@@ -663,12 +663,16 @@
   def : Property<"hasTemplateKeyword", Bool> {
     let Read = [{ qtn->hasTemplateKeyword() }];
   }
-  def : Property<"declaration", TemplateDeclRef> {
+  def : Property<"templateDecl", TemplateDeclRef> {
     let Read = [{ qtn->getTemplateDecl() }];
   }
+  def : Property<"usingShadowDecl", UsingShadowDeclRef> {
+    let Read = [{ qtn->getUsingShadowDecl() }];
+  }
   def : Creator<[{
     return ctx.getQualifiedTemplateName(qualifier, hasTemplateKeyword,
-                                        declaration);
+                usingShadowDecl ? TemplateName(usingShadowDecl) :
+                                  TemplateName(templateDecl));
   }]>;
 }
 let Class = PropertyTypeCase<TemplateName, "DependentTemplate"> in {
Index: clang/include/clang/AST/ASTContext.h
===================================================================
--- clang/include/clang/AST/ASTContext.h
+++ clang/include/clang/AST/ASTContext.h
@@ -2182,7 +2182,7 @@
 
   TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS,
                                         bool TemplateKeyword,
-                                        TemplateDecl *Template) const;
+                                        TemplateName Template) const;
 
   TemplateName getDependentTemplateName(NestedNameSpecifier *NNS,
                                         const IdentifierInfo *Name) const;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to