https://github.com/zwuis updated 
https://github.com/llvm/llvm-project/pull/134522

>From ccab3dc1f18ffeda9acb07c0bd5f80f65cc788b9 Mon Sep 17 00:00:00 2001
From: Yanzuo Liu <zw...@outlook.com>
Date: Sun, 6 Apr 2025 15:06:56 +0800
Subject: [PATCH 1/3] Handle invalid variable template specialization whose
 type depends on itself

---
 clang/docs/ReleaseNotes.rst                    |  2 ++
 .../include/clang/Basic/DiagnosticSemaKinds.td |  3 +++
 clang/lib/Sema/SemaTemplate.cpp                |  7 +++++++
 .../SemaTemplate/instantiate-var-template.cpp  | 18 ++++++++++++++++++
 4 files changed, 30 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5217e04b5e83f..9e0fe8a94729b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -414,6 +414,8 @@ Bug Fixes to C++ Support
 - Clang now issues an error when placement new is used to modify a 
const-qualified variable
   in a ``constexpr`` function. (#GH131432)
 - Clang now emits a warning when class template argument deduction for alias 
templates is used in C++17. (#GH133806)
+- No longer crashes when instantiating invalid variable template specialization
+  whose type depends on itself. (#GH51347)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 393bfecf9a36b..0c1da40dba388 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5259,6 +5259,9 @@ def err_template_member_noparams : Error<
   "extraneous 'template<>' in declaration of member %0">;
 def err_template_tag_noparams : Error<
   "extraneous 'template<>' in declaration of %0 %1">;
+def err_var_template_spec_type_depends_on_self : Error<
+  "the type of variable template specialization %0 declared with deduced type "
+  "%1 depends on itself">;
 
 def warn_unqualified_call_to_std_cast_function : Warning<
   "unqualified call to '%0'">, InGroup<DiagGroup<"unqualified-std-cast-call">>;
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 153f44f8ec67a..ce54dbbb3b9fe 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4377,6 +4377,13 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, 
SourceLocation TemplateLoc,
   if (VarTemplateSpecializationDecl *Spec =
           Template->findSpecialization(CTAI.CanonicalConverted, InsertPos)) {
     checkSpecializationReachability(TemplateNameLoc, Spec);
+    if (Spec->getType()->isUndeducedType()) {
+      // We are substituting the initializer of this variable template
+      // specialization.
+      Diag(TemplateNameLoc, diag::err_var_template_spec_type_depends_on_self)
+          << Spec << Spec->getType();
+      return true;
+    }
     // If we already have a variable template specialization, return it.
     return Spec;
   }
diff --git a/clang/test/SemaTemplate/instantiate-var-template.cpp 
b/clang/test/SemaTemplate/instantiate-var-template.cpp
index 60d3bd3b59f53..34a1b9710814b 100644
--- a/clang/test/SemaTemplate/instantiate-var-template.cpp
+++ b/clang/test/SemaTemplate/instantiate-var-template.cpp
@@ -47,3 +47,21 @@ namespace InvalidInsertPos {
   template<> int v<int, 0>;
   int k = v<int, 500>;
 }
+
+namespace GH51347 {
+  template <typename T>
+  auto p = p<T>; // expected-error {{the type of variable template 
specialization 'p<int>'}}
+
+  auto x = p<int>; // expected-note {{in instantiation of variable template 
specialization 'GH51347::p'}}
+}
+
+namespace GH97881_comment {
+  template <bool B>
+  auto g = sizeof(g<!B>);
+  // expected-error@-1 {{the type of variable template specialization 
'g<false>'}}
+  // expected-note@-2 {{in instantiation of variable template specialization 
'GH97881_comment::g'}}
+
+  void test() {
+    (void)sizeof(g<false>); // expected-note {{in instantiation of variable 
template specialization 'GH97881_comment::g'}}
+  }
+}

>From c23525e5ff672e679b76717033205e84d1c70c02 Mon Sep 17 00:00:00 2001
From: Yanzuo Liu <zw...@outlook.com>
Date: Mon, 28 Apr 2025 23:03:20 +0800
Subject: [PATCH 2/3] Recognize things like current instantiation

---
 .../clang/Basic/DiagnosticSemaKinds.td        | 11 ++-
 clang/lib/Sema/SemaExpr.cpp                   |  3 +-
 clang/lib/Sema/SemaTemplate.cpp               | 68 +++++++++++++++++--
 .../cxx1y-variable-templates_top_level.cpp    | 17 +++++
 .../SemaTemplate/instantiate-var-template.cpp |  7 --
 5 files changed, 90 insertions(+), 16 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0c1da40dba388..5afd824fad4f1 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2495,9 +2495,14 @@ def note_implicit_deduction_guide : Note<"implicit 
deduction guide declared as '
 def warn_cxx98_compat_auto_type_specifier : Warning<
   "'auto' type specifier is incompatible with C++98">,
   InGroup<CXX98Compat>, DefaultIgnore;
-def err_auto_variable_cannot_appear_in_own_initializer : Error<
-  "variable %0 declared with deduced type %1 "
-  "cannot appear in its own initializer">;
+def err_auto_variable_cannot_appear_in_own_initializer
+    : Error<
+          "%enum_select<ParsingInitFor>{%Var{variable}|"
+          "%VarTemplate{variable template}|"
+          "%VarTemplatePartialSpec{variable template partial specialization}|"
+          "%VarTemplateExplicitSpec{variable template explicit "
+          "specialization}}0 %1 "
+          "declared with deduced type %2 cannot appear in its own 
initializer">;
 def err_binding_cannot_appear_in_own_initializer : Error<
   "binding %0 cannot appear in the initializer of its own "
   "decomposition declaration">;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index e7f418ae6802e..82b581d7d1dc2 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -251,7 +251,8 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, 
ArrayRef<SourceLocation> Locs,
         << D->getDeclName();
     } else {
       Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
-        << D->getDeclName() << cast<VarDecl>(D)->getType();
+          << diag::ParsingInitFor::Var << D->getDeclName()
+          << cast<VarDecl>(D)->getType();
     }
     return true;
   }
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index ce54dbbb3b9fe..2212d8eca9c39 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4348,6 +4348,23 @@ struct PartialSpecMatchResult {
   VarTemplatePartialSpecializationDecl *Partial;
   TemplateArgumentList *Args;
 };
+
+struct TemplateArgEqualityComparator {
+  const ASTContext &Context;
+
+  bool operator()(const TemplateArgument &Canonical,
+                  const TemplateArgument &Unknown) const {
+    llvm::FoldingSetNodeID ID1, ID2;
+    Canonical.Profile(ID1, Context);
+    Context.getCanonicalTemplateArgument(Unknown).Profile(ID2, Context);
+#ifndef NDEBUG
+    llvm::FoldingSetNodeID ID3;
+    Context.getCanonicalTemplateArgument(Canonical).Profile(ID3, Context);
+    assert(ID1 == ID3);
+#endif
+    return ID1 == ID2;
+  }
+};
 } // end anonymous namespace
 
 DeclResult
@@ -4368,8 +4385,40 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, 
SourceLocation TemplateLoc,
   // Produce a placeholder value if the specialization is dependent.
   if (Template->getDeclContext()->isDependentContext() ||
       TemplateSpecializationType::anyDependentTemplateArguments(
-          TemplateArgs, CTAI.CanonicalConverted))
+          TemplateArgs, CTAI.CanonicalConverted)) {
+    if (ParsingInitForAutoVars.empty())
+      return DeclResult();
+
+    if (VarDecl *Var = Template->getTemplatedDecl();
+        ParsingInitForAutoVars.count(Var) &&
+        llvm::equal(
+            CTAI.CanonicalConverted,
+            
Template->getTemplateParameters()->getInjectedTemplateArgs(Context),
+            TemplateArgEqualityComparator{Context})) {
+      Diag(TemplateNameLoc,
+           diag::err_auto_variable_cannot_appear_in_own_initializer)
+          << diag::ParsingInitFor::VarTemplate << Var << Var->getType()
+          << SourceRange(TemplateNameLoc, TemplateArgs.getRAngleLoc());
+      return true;
+    }
+
+    SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs;
+    Template->getPartialSpecializations(PartialSpecs);
+    for (VarTemplatePartialSpecializationDecl *Partial : PartialSpecs)
+      if (ParsingInitForAutoVars.count(Partial) &&
+          llvm::equal(CTAI.CanonicalConverted,
+                      Partial->getTemplateArgs().asArray(),
+                      TemplateArgEqualityComparator{Context})) {
+        Diag(TemplateNameLoc,
+             diag::err_auto_variable_cannot_appear_in_own_initializer)
+            << diag::ParsingInitFor::VarTemplatePartialSpec << Partial
+            << Partial->getType()
+            << SourceRange(TemplateNameLoc, TemplateArgs.getRAngleLoc());
+        return true;
+      }
+
     return DeclResult();
+  }
 
   // Find the variable template specialization declaration that
   // corresponds to these arguments.
@@ -4378,10 +4427,19 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, 
SourceLocation TemplateLoc,
           Template->findSpecialization(CTAI.CanonicalConverted, InsertPos)) {
     checkSpecializationReachability(TemplateNameLoc, Spec);
     if (Spec->getType()->isUndeducedType()) {
-      // We are substituting the initializer of this variable template
-      // specialization.
-      Diag(TemplateNameLoc, diag::err_var_template_spec_type_depends_on_self)
-          << Spec << Spec->getType();
+      if (ParsingInitForAutoVars.count(Spec))
+        Diag(TemplateNameLoc,
+             diag::err_auto_variable_cannot_appear_in_own_initializer)
+            << diag::ParsingInitFor::VarTemplateExplicitSpec << Spec
+            << Spec->getType()
+            << SourceRange(TemplateNameLoc, TemplateArgs.getRAngleLoc());
+      else
+        // We are substituting the initializer of this variable template
+        // specialization.
+        Diag(TemplateNameLoc, diag::err_var_template_spec_type_depends_on_self)
+            << Spec << Spec->getType()
+            << SourceRange(TemplateNameLoc, TemplateArgs.getRAngleLoc());
+
       return true;
     }
     // If we already have a variable template specialization, return it.
diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp 
b/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
index 6fc2032ee7fb4..1fe0ce9aabf29 100644
--- a/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
+++ b/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
@@ -492,4 +492,21 @@ static_assert(C<int, 0,1,2,3,4>::VALUEARRAY[3] == 3, "");
 static_assert(C<int, 0,1,2,3,4>::VALUEARRAY[0] == 0, "");
 
 }
+
+namespace appear_in_its_own_init {
+template <class T>
+auto GH51347 = GH51347<T>; // expected-error {{variable template 'GH51347' 
declared with deduced type 'auto' cannot appear in its own initializer}}
+
+template <class T, class... Ts>
+auto a = [] {
+  using U = T;
+  a<U, Ts...>; // expected-error {{variable template 'a' declared with deduced 
type 'auto' cannot appear in its own initializer}}
+};
+
+template <int...> int b;
+template <int I>
+auto b<I, I * 2, 5> = b<I, I * 2, 5l>; // expected-error {{variable template 
partial specialization 'b<I, I * 2, 5>' declared with deduced type 'auto' 
cannot appear in its own initializer}}
+template <> auto b<0, 0, 0> = b<0, 0, 0>; // expected-error {{variable 
template explicit specialization 'b<0, 0, 0>' declared with deduced type 'auto' 
cannot appear in its own initializer}}
+}
+
 #endif
diff --git a/clang/test/SemaTemplate/instantiate-var-template.cpp 
b/clang/test/SemaTemplate/instantiate-var-template.cpp
index 34a1b9710814b..50b7219af4bea 100644
--- a/clang/test/SemaTemplate/instantiate-var-template.cpp
+++ b/clang/test/SemaTemplate/instantiate-var-template.cpp
@@ -48,13 +48,6 @@ namespace InvalidInsertPos {
   int k = v<int, 500>;
 }
 
-namespace GH51347 {
-  template <typename T>
-  auto p = p<T>; // expected-error {{the type of variable template 
specialization 'p<int>'}}
-
-  auto x = p<int>; // expected-note {{in instantiation of variable template 
specialization 'GH51347::p'}}
-}
-
 namespace GH97881_comment {
   template <bool B>
   auto g = sizeof(g<!B>);

>From 50d40656f62ae98d428db474ba683cbb2e98179f Mon Sep 17 00:00:00 2001
From: Yanzuo Liu <zw...@outlook.com>
Date: Tue, 29 Apr 2025 23:50:39 +0800
Subject: [PATCH 3/3] Introduce `ASTContext::isSameTemplateArgument`, remove
 underlines in diagnostic messages, and add test

---
 clang/docs/ReleaseNotes.rst                   |  2 +-
 clang/include/clang/AST/ASTContext.h          |  5 ++
 clang/lib/AST/ASTContext.cpp                  | 48 +++++++++++++++++++
 clang/lib/Sema/SemaTemplate.cpp               | 38 +++++----------
 clang/lib/Sema/SemaTemplateDeduction.cpp      | 24 ++--------
 .../cxx1y-variable-templates_in_class.cpp     | 20 ++++++++
 6 files changed, 88 insertions(+), 49 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 9e0fe8a94729b..4c0513f6a849f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -415,7 +415,7 @@ Bug Fixes to C++ Support
   in a ``constexpr`` function. (#GH131432)
 - Clang now emits a warning when class template argument deduction for alias 
templates is used in C++17. (#GH133806)
 - No longer crashes when instantiating invalid variable template specialization
-  whose type depends on itself. (#GH51347)
+  whose type depends on itself. (#GH51347), (#GH55872)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index 3ff9f308f3a5e..99ab20473df92 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2939,6 +2939,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
   TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg)
     const;
 
+  /// Determine whether the given template arguments \p Arg1 and \p Arg2 are
+  /// equivalent.
+  bool isSameTemplateArgument(const TemplateArgument &Arg1,
+                              const TemplateArgument &Arg2) const;
+
   /// Type Query functions.  If the type is an instance of the specified class,
   /// return the Type pointer for the underlying maximally pretty type.  This
   /// is a member of ASTContext because this may need to do some amount of
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 1b6b3d06ddc1e..3e43c529cf676 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -7594,6 +7594,54 @@ ASTContext::getCanonicalTemplateArgument(const 
TemplateArgument &Arg) const {
   llvm_unreachable("Unhandled template argument kind");
 }
 
+bool ASTContext::isSameTemplateArgument(const TemplateArgument &Arg1,
+                                        const TemplateArgument &Arg2) const {
+  if (Arg1.getKind() != Arg2.getKind())
+    return false;
+
+  switch (Arg1.getKind()) {
+  case TemplateArgument::Null:
+    return true;
+
+  case TemplateArgument::Type:
+    return hasSameType(Arg1.getAsType(), Arg2.getAsType());
+
+  case TemplateArgument::Declaration:
+    return Arg1.getAsDecl()->getUnderlyingDecl()->getCanonicalDecl() ==
+           Arg2.getAsDecl()->getUnderlyingDecl()->getCanonicalDecl();
+
+  case TemplateArgument::NullPtr:
+    return hasSameType(Arg1.getNullPtrType(), Arg2.getNullPtrType());
+
+  case TemplateArgument::Template:
+  case TemplateArgument::TemplateExpansion:
+    return getCanonicalTemplateName(Arg1.getAsTemplateOrTemplatePattern()) ==
+           getCanonicalTemplateName(Arg2.getAsTemplateOrTemplatePattern());
+
+  case TemplateArgument::Integral:
+    return Arg1.getAsIntegral() == Arg2.getAsIntegral();
+
+  case TemplateArgument::StructuralValue:
+    return Arg1.structurallyEquals(Arg2);
+
+  case TemplateArgument::Expression: {
+    llvm::FoldingSetNodeID ID1, ID2;
+    Arg1.getAsExpr()->Profile(ID1, *this, /*Canonical=*/true);
+    Arg2.getAsExpr()->Profile(ID2, *this, /*Canonical=*/true);
+    return ID1 == ID2;
+  }
+
+  case TemplateArgument::Pack:
+    return llvm::equal(
+        Arg1.getPackAsArray(), Arg2.getPackAsArray(),
+        [&](const TemplateArgument &Arg1, const TemplateArgument &Arg2) {
+          return isSameTemplateArgument(Arg1, Arg2);
+        });
+  }
+
+  llvm_unreachable("Unhandled template argument kind");
+}
+
 NestedNameSpecifier *
 ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
   if (!NNS)
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 2212d8eca9c39..94c69e1a18e6a 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4348,23 +4348,6 @@ struct PartialSpecMatchResult {
   VarTemplatePartialSpecializationDecl *Partial;
   TemplateArgumentList *Args;
 };
-
-struct TemplateArgEqualityComparator {
-  const ASTContext &Context;
-
-  bool operator()(const TemplateArgument &Canonical,
-                  const TemplateArgument &Unknown) const {
-    llvm::FoldingSetNodeID ID1, ID2;
-    Canonical.Profile(ID1, Context);
-    Context.getCanonicalTemplateArgument(Unknown).Profile(ID2, Context);
-#ifndef NDEBUG
-    llvm::FoldingSetNodeID ID3;
-    Context.getCanonicalTemplateArgument(Canonical).Profile(ID3, Context);
-    assert(ID1 == ID3);
-#endif
-    return ID1 == ID2;
-  }
-};
 } // end anonymous namespace
 
 DeclResult
@@ -4389,16 +4372,20 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, 
SourceLocation TemplateLoc,
     if (ParsingInitForAutoVars.empty())
       return DeclResult();
 
+    auto IsSameTemplateArg = [&](const TemplateArgument &Arg1,
+                                 const TemplateArgument &Arg2) {
+      return Context.isSameTemplateArgument(Arg1, Arg2);
+    };
+
     if (VarDecl *Var = Template->getTemplatedDecl();
         ParsingInitForAutoVars.count(Var) &&
         llvm::equal(
             CTAI.CanonicalConverted,
             
Template->getTemplateParameters()->getInjectedTemplateArgs(Context),
-            TemplateArgEqualityComparator{Context})) {
+            IsSameTemplateArg)) {
       Diag(TemplateNameLoc,
            diag::err_auto_variable_cannot_appear_in_own_initializer)
-          << diag::ParsingInitFor::VarTemplate << Var << Var->getType()
-          << SourceRange(TemplateNameLoc, TemplateArgs.getRAngleLoc());
+          << diag::ParsingInitFor::VarTemplate << Var << Var->getType();
       return true;
     }
 
@@ -4408,12 +4395,11 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, 
SourceLocation TemplateLoc,
       if (ParsingInitForAutoVars.count(Partial) &&
           llvm::equal(CTAI.CanonicalConverted,
                       Partial->getTemplateArgs().asArray(),
-                      TemplateArgEqualityComparator{Context})) {
+                      IsSameTemplateArg)) {
         Diag(TemplateNameLoc,
              diag::err_auto_variable_cannot_appear_in_own_initializer)
             << diag::ParsingInitFor::VarTemplatePartialSpec << Partial
-            << Partial->getType()
-            << SourceRange(TemplateNameLoc, TemplateArgs.getRAngleLoc());
+            << Partial->getType();
         return true;
       }
 
@@ -4431,14 +4417,12 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, 
SourceLocation TemplateLoc,
         Diag(TemplateNameLoc,
              diag::err_auto_variable_cannot_appear_in_own_initializer)
             << diag::ParsingInitFor::VarTemplateExplicitSpec << Spec
-            << Spec->getType()
-            << SourceRange(TemplateNameLoc, TemplateArgs.getRAngleLoc());
+            << Spec->getType();
       else
         // We are substituting the initializer of this variable template
         // specialization.
         Diag(TemplateNameLoc, diag::err_var_template_spec_type_depends_on_self)
-            << Spec << Spec->getType()
-            << SourceRange(TemplateNameLoc, TemplateArgs.getRAngleLoc());
+            << Spec << Spec->getType();
 
       return true;
     }
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 170b9f05002b1..4a23b6efc4da6 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2844,35 +2844,17 @@ static bool isSameTemplateArg(ASTContext &Context,
       llvm_unreachable("Comparing NULL template argument");
 
     case TemplateArgument::Type:
-      return Context.getCanonicalType(X.getAsType()) ==
-             Context.getCanonicalType(Y.getAsType());
-
     case TemplateArgument::Declaration:
-      return isSameDeclaration(X.getAsDecl(), Y.getAsDecl());
-
     case TemplateArgument::NullPtr:
-      return Context.hasSameType(X.getNullPtrType(), Y.getNullPtrType());
-
     case TemplateArgument::Template:
     case TemplateArgument::TemplateExpansion:
-      return Context.getCanonicalTemplateName(
-                    X.getAsTemplateOrTemplatePattern()).getAsVoidPointer() ==
-             Context.getCanonicalTemplateName(
-                    Y.getAsTemplateOrTemplatePattern()).getAsVoidPointer();
+    case TemplateArgument::StructuralValue:
+    case TemplateArgument::Expression:
+      return Context.isSameTemplateArgument(X, Y);
 
     case TemplateArgument::Integral:
       return hasSameExtendedValue(X.getAsIntegral(), Y.getAsIntegral());
 
-    case TemplateArgument::StructuralValue:
-      return X.structurallyEquals(Y);
-
-    case TemplateArgument::Expression: {
-      llvm::FoldingSetNodeID XID, YID;
-      X.getAsExpr()->Profile(XID, Context, true);
-      Y.getAsExpr()->Profile(YID, Context, true);
-      return XID == YID;
-    }
-
     case TemplateArgument::Pack: {
       unsigned PackIterationSize = X.pack_size();
       if (X.pack_size() != Y.pack_size()) {
diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp 
b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
index eafadb07b29e1..57a48fac56cd6 100644
--- a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
+++ b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
@@ -412,6 +412,26 @@ namespace dependent_static_var_template {
   }
 
   int cf() { return F<int>(); }
+
+#ifdef CPP1Y
+  namespace GH55872 {
+    struct s {
+      template<typename T>
+      static CONST auto f = [] { return T::template g<s>; };
+      // expected-note@-1 {{in instantiation of static data member 
'dependent_static_var_template::GH55872::t::g' requested here}}
+      // expected-note@-2 {{while substituting into a lambda expression here}}
+    };
+
+    struct t {
+      template<typename T>
+      static CONST auto g = [] { return T::template f<t>; };
+      // expected-error@-1 {{the type of variable template specialization 
'f<dependent_static_var_template::GH55872::t>' declared with deduced type 
'const auto' depends on itself}}
+      // expected-note@-2 {{while substituting into a lambda expression here}}
+    };
+
+    void test() { s::f<t>()(); } // expected-note {{in instantiation of static 
data member 'dependent_static_var_template::GH55872::s::f' requested here}}
+  }
+#endif
 }
 
 #ifndef PRECXX11

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to