Author: Yanzuo Liu
Date: 2025-05-14T10:25:01+02:00
New Revision: 86ba681e286d0a377830d2cbbc5e58bb5fad442c

URL: 
https://github.com/llvm/llvm-project/commit/86ba681e286d0a377830d2cbbc5e58bb5fad442c
DIFF: 
https://github.com/llvm/llvm-project/commit/86ba681e286d0a377830d2cbbc5e58bb5fad442c.diff

LOG: [Clang][Sema] Disable checking invalid template id in initializer of 
primary variable template `std::format_kind` with libstdc++ (#139560)

#134522 triggers compilation error with libstdc++, in which primary
variable template `std::format_kind` is defined like

```cpp
template <typename R>
constexpr auto format_kind =
__primary_template_not_defined(
  format_kind<R>
);
```

See #139067 or <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120190>.

This PR disables checking template id in initializer of primary variable
template `std::format_kind` in libstdc++ (by checking `__GLIBCXX__`).

Fixes #139067

Added: 
    clang/test/SemaCXX/libstdcxx_format_kind_hack.cpp

Modified: 
    clang/lib/Sema/SemaTemplate.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 486414ea84861..e306da357ca86 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4353,6 +4353,38 @@ struct PartialSpecMatchResult {
   VarTemplatePartialSpecializationDecl *Partial;
   TemplateArgumentList *Args;
 };
+
+// HACK 2025-05-13: workaround std::format_kind since libstdc++ 15.1 (2025-04)
+// See GH139067 / https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120190
+static bool IsLibstdcxxStdFormatKind(Preprocessor &PP, VarDecl *Var) {
+  if (Var->getName() != "format_kind" ||
+      !Var->getDeclContext()->isStdNamespace())
+    return false;
+
+  MacroInfo *MacroGLIBCXX =
+      PP.getMacroInfo(PP.getIdentifierInfo("__GLIBCXX__"));
+
+  if (!MacroGLIBCXX || MacroGLIBCXX->getNumTokens() != 1)
+    return false;
+
+  const Token &RevisionDateTok = MacroGLIBCXX->getReplacementToken(0);
+  bool Invalid = false;
+  std::string RevisionDate = PP.getSpelling(RevisionDateTok, &Invalid);
+  StringRef FixDate = "30251231";
+
+  if (Invalid)
+    return false;
+
+  // The format of the revision date is in compressed ISO date format.
+  // See https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_macros.html
+  // So we can use string comparison.
+  //
+  // Checking old versions of libstdc++ is not needed because 15.1 is the first
+  // release in which users can access std::format_kind.
+  //
+  // FIXME: Correct FixDate once the issue is fixed.
+  return RevisionDate.size() == 8 && RevisionDate <= FixDate;
+}
 } // end anonymous namespace
 
 DeclResult
@@ -4384,6 +4416,8 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, 
SourceLocation TemplateLoc,
 
     if (VarDecl *Var = Template->getTemplatedDecl();
         ParsingInitForAutoVars.count(Var) &&
+        // See comments on this function definition
+        !IsLibstdcxxStdFormatKind(PP, Var) &&
         llvm::equal(
             CTAI.CanonicalConverted,
             
Template->getTemplateParameters()->getInjectedTemplateArgs(Context),

diff  --git a/clang/test/SemaCXX/libstdcxx_format_kind_hack.cpp 
b/clang/test/SemaCXX/libstdcxx_format_kind_hack.cpp
new file mode 100644
index 0000000000000..35611c870b8d1
--- /dev/null
+++ b/clang/test/SemaCXX/libstdcxx_format_kind_hack.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++23 -verify %s
+
+// expected-no-diagnostics
+
+// Primary variable template std::format_kind is defined as followed since
+// libstdc++ 15.1, which triggers compilation error introduced by GH134522.
+// This file tests the workaround.
+
+#define __GLIBCXX__ 20250513
+
+namespace std {
+  template<typename _Rg>
+    constexpr auto format_kind =
+    __primary_template_not_defined(
+      format_kind<_Rg>
+    );
+}


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

Reply via email to