[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
This commit is contained in:
Yanzuo Liu 2025-05-14 16:25:01 +08:00 committed by GitHub
parent 3a81979a31
commit 86ba681e28
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 51 additions and 0 deletions

View File

@ -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),

View File

@ -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>
);
}