Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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),
Expand Down
17 changes: 17 additions & 0 deletions clang/test/SemaCXX/libstdcxx_format_kind_hack.cpp
Original file line number Diff line number Diff line change
@@ -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>
);
}