hokein updated this revision to Diff 420805.
hokein marked an inline comment as done.
hokein added a comment.

address remaining comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D123127/new/

https://reviews.llvm.org/D123127

Files:
  clang-tools-extra/clangd/DumpAST.cpp
  clang-tools-extra/clangd/SemanticHighlighting.cpp
  clang/include/clang/AST/ASTContext.h
  clang/include/clang/AST/PropertiesBase.td
  clang/include/clang/AST/TemplateName.h
  clang/include/clang/AST/TextNodeDumper.h
  clang/lib/AST/ASTContext.cpp
  clang/lib/AST/ASTImporter.cpp
  clang/lib/AST/ASTStructuralEquivalence.cpp
  clang/lib/AST/ItaniumMangle.cpp
  clang/lib/AST/ODRHash.cpp
  clang/lib/AST/TemplateName.cpp
  clang/lib/AST/TextNodeDumper.cpp
  clang/lib/AST/Type.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaTemplate.cpp
  clang/test/AST/ast-dump-using-template.cpp
  clang/test/CXX/temp/temp.deduct.guide/p3.cpp
  clang/test/SemaTemplate/qualified-id.cpp
  clang/tools/libclang/CIndex.cpp
  clang/unittests/AST/ASTImporterTest.cpp

Index: clang/unittests/AST/ASTImporterTest.cpp
===================================================================
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -890,6 +890,18 @@
              functionDecl(hasDescendant(usingDecl(hasName("bar")))));
 }
 
+TEST_P(ImportDecl, ImportUsingTemplate) {
+  MatchVerifier<Decl> Verifier;
+  testImport("namespace ns { template <typename T> struct S {}; }"
+             "template <template <typename> class T> class X {};"
+             "void declToImport() {"
+             "using ns::S;  X<S> xi; }",
+             Lang_CXX11, "", Lang_CXX11, Verifier,
+             functionDecl(
+                 hasDescendant(varDecl(hasTypeLoc(templateSpecializationTypeLoc(
+                     hasAnyTemplateArgumentLoc(templateArgumentLoc())))))));
+}
+
 TEST_P(ImportDecl, ImportUsingEnumDecl) {
   MatchVerifier<Decl> Verifier;
   testImport("namespace foo { enum bar { baz, toto, quux }; }"
Index: clang/tools/libclang/CIndex.cpp
===================================================================
--- clang/tools/libclang/CIndex.cpp
+++ clang/tools/libclang/CIndex.cpp
@@ -1472,6 +1472,9 @@
     return Visit(MakeCursorTemplateRef(
         Name.getAsSubstTemplateTemplateParmPack()->getParameterPack(), Loc,
         TU));
+  case TemplateName::UsingTemplate:
+    return VisitTemplateName(
+        Name.getAsUsingTemplateName()->getUnderlyingTemplate(), Loc);
   }
 
   llvm_unreachable("Invalid TemplateName::Kind!");
Index: clang/test/SemaTemplate/qualified-id.cpp
===================================================================
--- clang/test/SemaTemplate/qualified-id.cpp
+++ clang/test/SemaTemplate/qualified-id.cpp
@@ -31,6 +31,17 @@
   };
 }
 
+namespace test3 {
+namespace ns {
+template<typename T> class S { S(T); }; // expected-note3{{candidate constructor}}
+}
+namespace ns2 {
+using ns::S;
+}
+// Verify we print the right name for the using template name.
+ns2::S<int> s; // expected-error{{no matching constructor for initialization of 'ns2::S<int>'}}
+}
+
 namespace PR6063 {
   template <typename T> void f(T, T);
   
Index: clang/test/CXX/temp/temp.deduct.guide/p3.cpp
===================================================================
--- clang/test/CXX/temp/temp.deduct.guide/p3.cpp
+++ clang/test/CXX/temp/temp.deduct.guide/p3.cpp
@@ -55,6 +55,9 @@
   }
   using N::NamedNS1;
   NamedNS1(int) -> NamedNS1<int>; // expected-error {{deduction guide must be declared in the same scope as template}}
+  // FIXME: remove the following bogus diagnostic
+  // expected-error@-2{{deduction guide is not written as a specialization of template 'NamedNS1'}}
+
   using namespace N;
   NamedNS2(int) -> NamedNS2<int>; // expected-error {{deduction guide must be declared in the same scope as template}}
   struct ClassMemberA {
Index: clang/test/AST/ast-dump-using-template.cpp
===================================================================
--- /dev/null
+++ clang/test/AST/ast-dump-using-template.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++17 -ast-dump %s | FileCheck -strict-whitespace %s
+
+// Tests to verify we construct correct using template names.
+// TemplateNames are not dumped, so the sugar here isn't obvious. However
+// the "using" on the TemplateSpecializationTypes shows that the
+// UsingTemplateName is present.
+namespace ns {
+template<typename T> class S {
+ public:
+   S(T);
+};
+}
+using ns::S;
+
+// TemplateName in TemplateSpecializationType.
+template<typename T>
+using A = S<T>;
+// CHECK:      TypeAliasDecl
+// CHECK-NEXT: `-TemplateSpecializationType {{.*}} 'S<T>' dependent using S
+
+// TemplateName in TemplateArgument.
+template <template <typename> class T> class X {};
+using B = X<S>;
+// CHECK:      TypeAliasDecl
+// CHECK-NEXT: `-TemplateSpecializationType {{.*}} 'X<S>' sugar X
+// CHECK-NEXT:   |-TemplateArgument using template S
+// CHECK-NEXT:     `-RecordType {{.*}} 'X<S>'
+// CHECK-NEXT:       `-ClassTemplateSpecialization {{.*}} 'X'
+
+// TemplateName in DeducedTemplateSpecializationType.
+S DeducedTemplateSpecializationT(123);
+using C = decltype(DeducedTemplateSpecializationT);
+// CHECK:      DecltypeType {{.*}}
+// CHECK-NEXT:  |-DeclRefExpr {{.*}}
+// CHECK-NEXT:  `-DeducedTemplateSpecializationType {{.*}} 'ns::S<int>' sugar using
Index: clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -16,6 +16,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/TemplateName.h"
 #include "clang/AST/TypeVisitor.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/LangOptions.h"
@@ -283,10 +284,13 @@
 
     if (SS.isSet() && !SS.isInvalid()) {
       NestedNameSpecifier *Qualifier = SS.getScopeRep();
+      // FIXME: support inner UsingTemplateName for QualifiedTemplateName.
       Template = Context.getQualifiedTemplateName(Qualifier,
                                                   hasTemplateKeyword, TD);
     } else {
       Template = TemplateName(TD);
+      if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(*R.begin()))
+        Template = Context.getUsingTemplateName(Template, USD);
     }
 
     if (isa<FunctionTemplateDecl>(TD)) {
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -11023,6 +11023,8 @@
       TemplateName SpecifiedName = RetTST.getTypePtr()->getTemplateName();
       bool TemplateMatches =
           Context.hasSameTemplateName(SpecifiedName, GuidedTemplate);
+      // FIXME: we should consider UsingTemplateName and QualifiedTemplateName,
+      // otherwise we will emit bogus diagnostics.
       if (SpecifiedName.getKind() == TemplateName::Template && TemplateMatches)
         AcceptableReturnType = true;
       else {
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -503,9 +503,11 @@
     FoundUsingShadow = nullptr;
   } else if (AllowDeducedTemplate) {
     if (auto *TD = getAsTypeTemplateDecl(IIDecl)) {
-      // FIXME: TemplateName should include FoundUsingShadow sugar.
-      T = Context.getDeducedTemplateSpecializationType(TemplateName(TD),
-                                                       QualType(), false);
+      TemplateName Template(TD);
+      if (FoundUsingShadow)
+        Template = Context.getUsingTemplateName(Template, FoundUsingShadow);
+      T = Context.getDeducedTemplateSpecializationType(Template, QualType(),
+                                                       false);
       // Don't wrap in a further UsingType.
       FoundUsingShadow = nullptr;
     }
Index: clang/lib/AST/Type.cpp
===================================================================
--- clang/lib/AST/Type.cpp
+++ clang/lib/AST/Type.cpp
@@ -3686,7 +3686,8 @@
          "Use DependentTemplateSpecializationType for dependent template-name");
   assert((T.getKind() == TemplateName::Template ||
           T.getKind() == TemplateName::SubstTemplateTemplateParm ||
-          T.getKind() == TemplateName::SubstTemplateTemplateParmPack) &&
+          T.getKind() == TemplateName::SubstTemplateTemplateParmPack ||
+          T.getKind() == TemplateName::UsingTemplate) &&
          "Unexpected template name for TemplateSpecializationType");
 
   auto *TemplateArgs = reinterpret_cast<TemplateArgument *>(this + 1);
Index: clang/lib/AST/TextNodeDumper.cpp
===================================================================
--- clang/lib/AST/TextNodeDumper.cpp
+++ clang/lib/AST/TextNodeDumper.cpp
@@ -900,12 +900,17 @@
 }
 
 void TextNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) {
+  if (TA.getAsTemplate().getKind() == TemplateName::UsingTemplate)
+    OS << " using";
   OS << " template ";
   TA.getAsTemplate().dump(OS);
 }
 
 void TextNodeDumper::VisitTemplateExpansionTemplateArgument(
     const TemplateArgument &TA) {
+  if (TA.getAsTemplateOrTemplatePattern().getKind() ==
+      TemplateName::UsingTemplate)
+    OS << " using";
   OS << " template expansion ";
   TA.getAsTemplateOrTemplatePattern().dump(OS);
 }
@@ -1575,10 +1580,18 @@
   }
 }
 
+void TextNodeDumper::VisitDeducedTemplateSpecializationType(
+    const DeducedTemplateSpecializationType *T) {
+  if (T->getTemplateName().getKind() == TemplateName::UsingTemplate)
+    OS << " using";
+}
+
 void TextNodeDumper::VisitTemplateSpecializationType(
     const TemplateSpecializationType *T) {
   if (T->isTypeAlias())
     OS << " alias";
+  if (T->getTemplateName().getKind() == TemplateName::UsingTemplate)
+    OS << " using";
   OS << " ";
   T->getTemplateName().dump(OS);
 }
Index: clang/lib/AST/TemplateName.cpp
===================================================================
--- clang/lib/AST/TemplateName.cpp
+++ clang/lib/AST/TemplateName.cpp
@@ -76,12 +76,15 @@
     : Storage(Storage) {}
 TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
 TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
+TemplateName::TemplateName(UsingTemplateName *Using) : Storage(Using) {}
 
 bool TemplateName::isNull() const { return Storage.isNull(); }
 
 TemplateName::NameKind TemplateName::getKind() const {
   if (Storage.is<TemplateDecl *>())
     return Template;
+  if (Storage.is<UsingTemplateName *>())
+    return UsingTemplate;
   if (Storage.is<DependentTemplateName *>())
     return DependentTemplate;
   if (Storage.is<QualifiedTemplateName *>())
@@ -108,6 +111,9 @@
   if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
     return sub->getReplacement().getAsTemplateDecl();
 
+  if (auto *UTN = getAsUsingTemplateName())
+    return UTN->getUnderlyingTemplate().getAsTemplateDecl();
+
   return nullptr;
 }
 
@@ -127,6 +133,10 @@
   return nullptr;
 }
 
+UsingTemplateName *TemplateName::getAsUsingTemplateName() const {
+  return Storage.dyn_cast<UsingTemplateName *>();
+}
+
 SubstTemplateTemplateParmStorage *
 TemplateName::getAsSubstTemplateTemplateParm() const {
   if (UncommonTemplateNameStorage *uncommon =
@@ -261,6 +271,8 @@
     OS << *SubstPack->getParameterPack();
   else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
     Assumed->getDeclName().print(OS, Policy);
+  } else if (auto *U = getAsUsingTemplateName()) {
+    U->getUnderlyingTemplate().print(OS, Policy, Qualified::None);
   } else {
     OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
     (*OTS->begin())->printName(OS);
Index: clang/lib/AST/ODRHash.cpp
===================================================================
--- clang/lib/AST/ODRHash.cpp
+++ clang/lib/AST/ODRHash.cpp
@@ -150,6 +150,7 @@
   case TemplateName::DependentTemplate:
   case TemplateName::SubstTemplateTemplateParm:
   case TemplateName::SubstTemplateTemplateParmPack:
+  case TemplateName::UsingTemplate:
     break;
   }
 }
Index: clang/lib/AST/ItaniumMangle.cpp
===================================================================
--- clang/lib/AST/ItaniumMangle.cpp
+++ clang/lib/AST/ItaniumMangle.cpp
@@ -2252,6 +2252,10 @@
     Out << "_SUBSTPACK_";
     break;
   }
+  case TemplateName::UsingTemplate: {
+    mangleType(TN.getAsUsingTemplateName()->getUnderlyingTemplate());
+    break;
+  }
   }
 
   addSubstitution(TN);
@@ -2383,6 +2387,12 @@
       Out << "_SUBSTPACK_";
       break;
     }
+    case TemplateName::UsingTemplate: {
+      TemplateDecl *TD = TN.getAsTemplateDecl();
+      assert(TD && !isa<TemplateTemplateParmDecl>(TD));
+      mangleSourceNameWithAbiTags(TD);
+      break;
+    }
     }
 
     // Note: we don't pass in the template name here. We are mangling the
Index: clang/lib/AST/ASTStructuralEquivalence.cpp
===================================================================
--- clang/lib/AST/ASTStructuralEquivalence.cpp
+++ clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -514,6 +514,12 @@
                                     P2->getParameterPack());
   }
 
+  case TemplateName::UsingTemplate: {
+    return IsStructurallyEquivalent(
+        Context, N1.getAsUsingTemplateName()->getUnderlyingTemplate(),
+        N2.getAsUsingTemplateName()->getUnderlyingTemplate());
+  }
+
    case TemplateName::Template:
    case TemplateName::QualifiedTemplate:
    case TemplateName::SubstTemplateTemplateParm:
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -9190,6 +9190,17 @@
     return ToContext.getSubstTemplateTemplateParmPack(
         cast<TemplateTemplateParmDecl>(*ParamOrErr), *ArgPackOrErr);
   }
+  case TemplateName::UsingTemplate: {
+    auto *UTN = From.getAsUsingTemplateName();
+    auto UsingOrError = Import(UTN->getFoundDecl());
+    if (!UsingOrError)
+      return UsingOrError.takeError();
+    auto UnderlyingOrError = Import(UTN->getUnderlyingTemplate());
+    if (!UnderlyingOrError)
+      return UnderlyingOrError.takeError();
+    return ToContext.getUsingTemplateName(*UnderlyingOrError,
+                                          cast<UsingShadowDecl>(*UsingOrError));
+  }
   }
 
   llvm_unreachable("Invalid template name kind");
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -6125,6 +6125,10 @@
     return DeclarationNameInfo(subst->getParameterPack()->getDeclName(),
                                NameLoc);
   }
+  case TemplateName::UsingTemplate: {
+    return DeclarationNameInfo(
+        Name.getAsUsingTemplateName()->getFoundDecl()->getDeclName(), NameLoc);
+  }
   }
 
   llvm_unreachable("bad template name kind!");
@@ -6168,6 +6172,9 @@
       = getCanonicalTemplateArgument(subst->getArgumentPack());
     return getSubstTemplateTemplateParmPack(canonParameter, canonArgPack);
   }
+  case TemplateName::UsingTemplate:
+    return getCanonicalTemplateName(
+        Name.getAsUsingTemplateName()->getUnderlyingTemplate());
   }
 
   llvm_unreachable("bad template name!");
@@ -8989,6 +8996,24 @@
   return TemplateName(QTN);
 }
 
+TemplateName ASTContext::getUsingTemplateName(TemplateName Underlying,
+                                              UsingShadowDecl *USD) const {
+
+  assert(USD);
+  llvm::FoldingSetNodeID ID;
+  UsingTemplateName::Profile(ID, Underlying, USD);
+
+  void *InsertPos = nullptr;
+  UsingTemplateName *T = UsingTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
+  if (T)
+    return TemplateName(T);
+
+  UsingTemplateName *NewType = new (*this, alignof(UsingTemplateName))
+      UsingTemplateName(Underlying, USD);
+  UsingTemplateNames.InsertNode(NewType, InsertPos);
+  return TemplateName(NewType);
+}
+
 /// Retrieve the template name that represents a dependent
 /// template name such as \c MetaFun::template apply.
 TemplateName
Index: clang/include/clang/AST/TextNodeDumper.h
===================================================================
--- clang/include/clang/AST/TextNodeDumper.h
+++ clang/include/clang/AST/TextNodeDumper.h
@@ -317,6 +317,8 @@
   void VisitTagType(const TagType *T);
   void VisitTemplateTypeParmType(const TemplateTypeParmType *T);
   void VisitAutoType(const AutoType *T);
+  void VisitDeducedTemplateSpecializationType(
+      const DeducedTemplateSpecializationType *T);
   void VisitTemplateSpecializationType(const TemplateSpecializationType *T);
   void VisitInjectedClassNameType(const InjectedClassNameType *T);
   void VisitObjCInterfaceType(const ObjCInterfaceType *T);
Index: clang/include/clang/AST/TemplateName.h
===================================================================
--- clang/include/clang/AST/TemplateName.h
+++ clang/include/clang/AST/TemplateName.h
@@ -39,6 +39,8 @@
 class TemplateArgument;
 class TemplateDecl;
 class TemplateTemplateParmDecl;
+class UsingShadowDecl;
+class UsingTemplateName;
 
 /// Implementation class used to describe either a set of overloaded
 /// template names or an already-substituted template template parameter pack.
@@ -190,7 +192,8 @@
 class TemplateName {
   using StorageType =
       llvm::PointerUnion<TemplateDecl *, UncommonTemplateNameStorage *,
-                         QualifiedTemplateName *, DependentTemplateName *>;
+                         QualifiedTemplateName *, DependentTemplateName *,
+                         UsingTemplateName *>;
 
   StorageType Storage;
 
@@ -224,7 +227,11 @@
     /// A template template parameter pack that has been substituted for
     /// a template template argument pack, but has not yet been expanded into
     /// individual arguments.
-    SubstTemplateTemplateParmPack
+    SubstTemplateTemplateParmPack,
+
+    /// A template name that refers to a template through a specific using
+    /// shadow declaration.
+    UsingTemplate,
   };
 
   TemplateName() = default;
@@ -235,6 +242,7 @@
   explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage);
   explicit TemplateName(QualifiedTemplateName *Qual);
   explicit TemplateName(DependentTemplateName *Dep);
+  explicit TemplateName(UsingTemplateName *Using);
 
   /// Determine whether this template name is NULL.
   bool isNull() const;
@@ -287,6 +295,9 @@
   /// structure, if any.
   DependentTemplateName *getAsDependentTemplateName() const;
 
+  /// Retrieve the underlying using template name, if any.
+  UsingTemplateName *getAsUsingTemplateName() const;
+
   TemplateName getUnderlying() const;
 
   /// Get the template name to substitute when this template name is used as a
@@ -376,6 +387,42 @@
   return *this;
 }
 
+/// Represents a template name that refers to a template introduced by a using
+/// declaration. For example,
+///
+/// \code
+/// using std::vector;
+///
+/// vector<int> v;
+/// \endcode
+/// The `vector` in \c vector<int> is a UsingTemplateName where its underlying
+/// template name is a normal template name which refers to the vector class
+/// template.
+class UsingTemplateName : public llvm::FoldingSetNode {
+  friend class ASTContext;
+
+  TemplateName UnderlyingTN;
+  UsingShadowDecl *USD = nullptr;
+
+  UsingTemplateName(TemplateName UnderlyingTN, UsingShadowDecl *USD)
+      : UnderlyingTN(UnderlyingTN), USD(USD) {}
+
+public:
+  /// Returns the using shadow declaration through which the underlying template
+  /// is introduced.
+  UsingShadowDecl *getFoundDecl() const { return USD; }
+  /// Returns the underlying template name, which refers to the a template
+  /// introduced by the using decl.
+  TemplateName getUnderlyingTemplate() const { return UnderlyingTN; }
+
+  void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, UnderlyingTN, USD); }
+  static void Profile(llvm::FoldingSetNodeID &ID, TemplateName Underlying,
+                      UsingShadowDecl *USD) {
+    ID.AddPointer(USD);
+    ID.AddPointer(Underlying.getAsVoidPointer());
+  }
+};
+
 /// Represents a template name that was expressed as a
 /// qualified name.
 ///
Index: clang/include/clang/AST/PropertiesBase.td
===================================================================
--- clang/include/clang/AST/PropertiesBase.td
+++ clang/include/clang/AST/PropertiesBase.td
@@ -620,6 +620,19 @@
     return TemplateName(declaration);
   }]>;
 }
+
+let Class = PropertyTypeCase<TemplateName, "UsingTemplate"> in {
+  def : Property<"foundDecl", UsingShadowDeclRef> {
+    let Read = [{ node.getAsUsingTemplateName()->getFoundDecl() }];
+  }
+  def : Property<"underlyingTemplate", TemplateName> {
+    let Read = [{ node.getAsUsingTemplateName()->getUnderlyingTemplate() }];
+  }
+  def : Creator<[{
+    return ctx.getUsingTemplateName(underlyingTemplate, foundDecl);
+  }]>;
+}
+
 let Class = PropertyTypeCase<TemplateName, "OverloadedTemplate"> in {
   def : Property<"overloads", Array<NamedDeclRef>> {
     let Read = [{ node.getAsOverloadedTemplate()->decls() }];
Index: clang/include/clang/AST/ASTContext.h
===================================================================
--- clang/include/clang/AST/ASTContext.h
+++ clang/include/clang/AST/ASTContext.h
@@ -273,6 +273,7 @@
   mutable llvm::ContextualFoldingSet<SubstTemplateTemplateParmPackStorage,
                                      ASTContext&>
     SubstTemplateTemplateParmPacks;
+  mutable llvm::FoldingSet<UsingTemplateName> UsingTemplateNames;
 
   /// The set of nested name specifiers.
   ///
@@ -2189,6 +2190,9 @@
   TemplateName getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param,
                                         const TemplateArgument &ArgPack) const;
 
+  TemplateName getUsingTemplateName(TemplateName Underlying,
+                                    UsingShadowDecl *USD) const;
+
   enum GetBuiltinTypeError {
     /// No error
     GE_None,
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===================================================================
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -762,6 +762,7 @@
     case TemplateName::QualifiedTemplate:
     case TemplateName::SubstTemplateTemplateParm:
     case TemplateName::SubstTemplateTemplateParmPack:
+    case TemplateName::UsingTemplate:
       // Names that could be resolved to a TemplateDecl are handled elsewhere.
       break;
     }
Index: clang-tools-extra/clangd/DumpAST.cpp
===================================================================
--- clang-tools-extra/clangd/DumpAST.cpp
+++ clang-tools-extra/clangd/DumpAST.cpp
@@ -184,6 +184,7 @@
       TEMPLATE_KIND(DependentTemplate);
       TEMPLATE_KIND(SubstTemplateTemplateParm);
       TEMPLATE_KIND(SubstTemplateTemplateParmPack);
+      TEMPLATE_KIND(UsingTemplate);
 #undef TEMPLATE_KIND
     }
     llvm_unreachable("Unhandled NameKind enum");
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to