https://github.com/zwuis created 
https://github.com/llvm/llvm-project/pull/139539

#134522 triggers compilation error with libstdc++. See #139067 or 
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120190>.

This reverts commit 91f1830cb69cab96201adba6378d64095e251f95.

>From 4878337bb6b2d6152fc53160ba4e515d2dadc266 Mon Sep 17 00:00:00 2001
From: Yanzuo Liu <zw...@outlook.com>
Date: Mon, 12 May 2025 19:47:46 +0800
Subject: [PATCH] Revert "[Clang][Sema] Handle invalid variable template
 specialization whose type depends on itself (#134522)"

This reverts commit 91f1830cb69cab96201adba6378d64095e251f95.
---
 clang/docs/ReleaseNotes.rst                   |  2 -
 clang/include/clang/AST/ASTContext.h          |  5 --
 .../clang/Basic/DiagnosticSemaKinds.td        | 14 +---
 clang/lib/AST/ASTContext.cpp                  | 49 -----------
 clang/lib/Sema/SemaExpr.cpp                   |  3 +-
 clang/lib/Sema/SemaTemplate.cpp               | 51 +-----------
 clang/lib/Sema/SemaTemplateDeduction.cpp      | 83 ++++++++++++++++++-
 .../cxx1y-variable-templates_in_class.cpp     | 20 -----
 .../cxx1y-variable-templates_top_level.cpp    | 17 ----
 .../SemaTemplate/instantiate-var-template.cpp | 11 ---
 10 files changed, 85 insertions(+), 170 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index e362ec595a3bb..d0645f3cbc6a5 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -684,8 +684,6 @@ Bug Fixes to C++ Support
 - Fixed an assertion when trying to constant-fold various builtins when the 
argument
   referred to a reference to an incomplete type. (#GH129397)
 - Fixed a crash when a cast involved a parenthesized aggregate initialization 
in dependent context. (#GH72880)
-- No longer crashes when instantiating invalid variable template specialization
-  whose type depends on itself. (#GH51347), (#GH55872)
 - Improved parser recovery of invalid requirement expressions. In turn, this
   fixes crashes from follow-on processing of the invalid requirement. 
(#GH138820)
 - Fixed the handling of pack indexing types in the constraints of a member 
function redeclaration. (#GH138255)
diff --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index 1fdc488a76507..555afc315b704 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -2971,11 +2971,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
   TemplateTemplateParmDecl *insertCanonicalTemplateTemplateParmDeclInternal(
       TemplateTemplateParmDecl *CanonTTP) 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/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index ca47cf62324f3..4751acfbb0456 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2531,14 +2531,9 @@ 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<
-          "%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_auto_variable_cannot_appear_in_own_initializer : Error<
+  "variable %0 declared with deduced type %1 "
+  "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">;
@@ -5312,9 +5307,6 @@ 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/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index c58cd2c93fb60..6b8685ae99256 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -7666,55 +7666,6 @@ 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:
-    llvm_unreachable("Comparing NULL template argument");
-
-  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 llvm::APSInt::isSameValue(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/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 2c81f7c583eb6..4af9b6f0a1f56 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -251,8 +251,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, 
ArrayRef<SourceLocation> Locs,
         << D->getDeclName();
     } else {
       Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer)
-          << diag::ParsingInitFor::Var << D->getDeclName()
-          << cast<VarDecl>(D)->getType();
+        << D->getDeclName() << cast<VarDecl>(D)->getType();
     }
     return true;
   }
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 7940340064eda..8ccfdb80e1ce5 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4373,43 +4373,8 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, 
SourceLocation TemplateLoc,
   // Produce a placeholder value if the specialization is dependent.
   if (Template->getDeclContext()->isDependentContext() ||
       TemplateSpecializationType::anyDependentTemplateArguments(
-          TemplateArgs, CTAI.CanonicalConverted)) {
-    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),
-            IsSameTemplateArg)) {
-      Diag(TemplateNameLoc,
-           diag::err_auto_variable_cannot_appear_in_own_initializer)
-          << diag::ParsingInitFor::VarTemplate << Var << Var->getType();
-      return true;
-    }
-
-    SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs;
-    Template->getPartialSpecializations(PartialSpecs);
-    for (VarTemplatePartialSpecializationDecl *Partial : PartialSpecs)
-      if (ParsingInitForAutoVars.count(Partial) &&
-          llvm::equal(CTAI.CanonicalConverted,
-                      Partial->getTemplateArgs().asArray(),
-                      IsSameTemplateArg)) {
-        Diag(TemplateNameLoc,
-             diag::err_auto_variable_cannot_appear_in_own_initializer)
-            << diag::ParsingInitFor::VarTemplatePartialSpec << Partial
-            << Partial->getType();
-        return true;
-      }
-
+          TemplateArgs, CTAI.CanonicalConverted))
     return DeclResult();
-  }
 
   // Find the variable template specialization declaration that
   // corresponds to these arguments.
@@ -4417,20 +4382,6 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, 
SourceLocation TemplateLoc,
   if (VarTemplateSpecializationDecl *Spec =
           Template->findSpecialization(CTAI.CanonicalConverted, InsertPos)) {
     checkSpecializationReachability(TemplateNameLoc, Spec);
-    if (Spec->getType()->isUndeducedType()) {
-      if (ParsingInitForAutoVars.count(Spec))
-        Diag(TemplateNameLoc,
-             diag::err_auto_variable_cannot_appear_in_own_initializer)
-            << diag::ParsingInitFor::VarTemplateExplicitSpec << Spec
-            << 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();
-
-      return true;
-    }
     // If we already have a variable template specialization, return it.
     return Spec;
   }
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 5dc06ebc2a235..b3505bad281f2 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -114,6 +114,27 @@ namespace clang {
 using namespace clang;
 using namespace sema;
 
+/// Compare two APSInts, extending and switching the sign as
+/// necessary to compare their values regardless of underlying type.
+static bool hasSameExtendedValue(llvm::APSInt X, llvm::APSInt Y) {
+  if (Y.getBitWidth() > X.getBitWidth())
+    X = X.extend(Y.getBitWidth());
+  else if (Y.getBitWidth() < X.getBitWidth())
+    Y = Y.extend(X.getBitWidth());
+
+  // If there is a signedness mismatch, correct it.
+  if (X.isSigned() != Y.isSigned()) {
+    // If the signed value is negative, then the values cannot be the same.
+    if ((Y.isSigned() && Y.isNegative()) || (X.isSigned() && X.isNegative()))
+      return false;
+
+    Y.setIsSigned(true);
+    X.setIsSigned(true);
+  }
+
+  return X == Y;
+}
+
 /// The kind of PartialOrdering we're performing template argument deduction
 /// for (C++11 [temp.deduct.partial]).
 enum class PartialOrderingKind { None, NonCall, Call };
@@ -252,7 +273,7 @@ checkDeducedTemplateArguments(ASTContext &Context,
     if (Y.getKind() == TemplateArgument::Expression ||
         Y.getKind() == TemplateArgument::Declaration ||
         (Y.getKind() == TemplateArgument::Integral &&
-         llvm::APSInt::isSameValue(X.getAsIntegral(), Y.getAsIntegral())))
+         hasSameExtendedValue(X.getAsIntegral(), Y.getAsIntegral())))
       return X.wasDeducedFromArrayBound() ? Y : X;
 
     // All other combinations are incompatible.
@@ -2553,7 +2574,7 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList 
*TemplateParams,
 
   case TemplateArgument::Integral:
     if (A.getKind() == TemplateArgument::Integral) {
-      if (llvm::APSInt::isSameValue(P.getAsIntegral(), A.getAsIntegral()))
+      if (hasSameExtendedValue(P.getAsIntegral(), A.getAsIntegral()))
         return TemplateDeductionResult::Success;
     }
     Info.FirstArg = P;
@@ -2807,6 +2828,62 @@ TemplateDeductionResult Sema::DeduceTemplateArguments(
       /*HasDeducedAnyParam=*/nullptr);
 }
 
+/// Determine whether two template arguments are the same.
+static bool isSameTemplateArg(ASTContext &Context, const TemplateArgument &X,
+                              const TemplateArgument &Y) {
+  if (X.getKind() != Y.getKind())
+    return false;
+
+  switch (X.getKind()) {
+    case TemplateArgument::Null:
+      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::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())
+        return false;
+      ArrayRef<TemplateArgument> XP = X.pack_elements();
+      ArrayRef<TemplateArgument> YP = Y.pack_elements();
+      for (unsigned i = 0; i < PackIterationSize; ++i)
+        if (!isSameTemplateArg(Context, XP[i], YP[i]))
+          return false;
+      return true;
+    }
+  }
+
+  llvm_unreachable("Invalid TemplateArgument Kind!");
+}
+
 TemplateArgumentLoc
 Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
                                     QualType NTTPType, SourceLocation Loc,
@@ -3272,7 +3349,7 @@ static TemplateDeductionResult 
FinishTemplateArgumentDeduction(
       break;
     TemplateArgument PP = P.isPackExpansion() ? P.getPackExpansionPattern() : 
P,
                      PA = A.isPackExpansion() ? A.getPackExpansionPattern() : 
A;
-    if (!S.Context.isSameTemplateArgument(PP, PA)) {
+    if (!isSameTemplateArg(S.Context, PP, PA)) {
       if (!P.isPackExpansion() && !A.isPackExpansion()) {
         Info.Param = makeTemplateParameter(TPL->getParam(
             (AsStack.empty() ? As.end() : AsStack.back().begin()) -
diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp 
b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
index 57a48fac56cd6..eafadb07b29e1 100644
--- a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
+++ b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
@@ -412,26 +412,6 @@ 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
diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp 
b/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
index 1fe0ce9aabf29..6fc2032ee7fb4 100644
--- a/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
+++ b/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
@@ -492,21 +492,4 @@ 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 50b7219af4bea..60d3bd3b59f53 100644
--- a/clang/test/SemaTemplate/instantiate-var-template.cpp
+++ b/clang/test/SemaTemplate/instantiate-var-template.cpp
@@ -47,14 +47,3 @@ namespace InvalidInsertPos {
   template<> int v<int, 0>;
   int k = v<int, 500>;
 }
-
-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'}}
-  }
-}

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

Reply via email to