From 7a5e159aceef541c054a53f6508cdb7fdd9af04d Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Thu, 9 Oct 2025 10:12:55 -0400 Subject: [PATCH 1/7] [C2y] Support WG14 N3457, the __COUNTER__ macro This implements the parts of https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3457.htm which were adopted at the recent meeting in Brno. Clang already implemented __COUNTER__, but needed some changes for conformance. Specifically, we now diagnose when the macro is expanded more than 2147483647 times. Additionally, we now give the expected extension and pre-compat warnings for the feature. To support testing the limits, this also adds a -cc1-only option, -finitial-counter-value=, which lets you specify the initial value the __COUNTER__ macro should expand to. --- clang/docs/LanguageExtensions.rst | 4 +- clang/docs/ReleaseNotes.rst | 5 +++ .../include/clang/Basic/DiagnosticLexKinds.td | 8 ++++ clang/include/clang/Driver/Options.td | 4 ++ clang/include/clang/Lex/Preprocessor.h | 6 +-- clang/include/clang/Lex/PreprocessorOptions.h | 4 ++ clang/include/clang/Serialization/ASTReader.h | 8 ++-- clang/lib/Frontend/ASTUnit.cpp | 9 +++-- clang/lib/Frontend/InitPreprocessor.cpp | 3 ++ clang/lib/Lex/PPMacroExpansion.cpp | 13 ++++++- clang/lib/Serialization/ASTReader.cpp | 4 +- clang/test/C/C2y/n3457.c | 37 +++++++++++++++++++ clang/test/C/C2y/n3457_1.c | 20 ++++++++++ clang/test/C/C2y/n3457_2.c | 10 +++++ clang/www/c_status.html | 2 +- 15 files changed, 122 insertions(+), 15 deletions(-) create mode 100644 clang/test/C/C2y/n3457.c create mode 100644 clang/test/C/C2y/n3457_1.c create mode 100644 clang/test/C/C2y/n3457_2.c diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 6bb99c757cd19..54c215e9ccfaa 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -385,7 +385,9 @@ Builtin Macros ``__COUNTER__`` Defined to an integer value that starts at zero and is incremented each time - the ``__COUNTER__`` macro is expanded. + the ``__COUNTER__`` macro is expanded. This is a standard feature in C2y but + is an extension in earlier language modes and in C++. This macro can only be + expanded 2147483647 times at most. ``__INCLUDE_LEVEL__`` Defined to an integral value that is the include depth of the file currently diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 5e9a71e1e74d6..37e02e9638296 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -181,6 +181,11 @@ C Language Changes C2y Feature Support ^^^^^^^^^^^^^^^^^^^ - Clang now supports `N3355 `_ Named Loops. +- Clang's implementation of ``__COUNTER__`` was updated to conform to + `WG14 N3457 `_. + This includes adding pedantic warnings for the feature being an extension in + other language modes as well as an error when the counter is expanded more + than 2147483647 times. C23 Feature Support ^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td index c7fe6e1db6d1f..46a7a88f7a50b 100644 --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -90,6 +90,14 @@ def err_unterminated___pragma : Error<"missing terminating ')' character">; def err_conflict_marker : Error<"version control conflict marker in file">; +def err_counter_overflow : Error< + "'__COUNTER__' value cannot exceed 2147483647">; +def ext_counter : Extension< + "'__COUNTER__' is a C2y extension">, InGroup; +def warn_counter : Warning< + "'__COUNTER__' is incompatible with standards before C2y">, + InGroup, DefaultIgnore; + def err_raw_delim_too_long : Error< "raw string delimiter longer than 16 characters" "; use PREFIX( )PREFIX to delimit raw string">; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index c8e96e125733c..2511f88f4e53c 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -8417,6 +8417,10 @@ def aligned_alloc_unavailable : Flag<["-"], "faligned-alloc-unavailable">, MarshallingInfoFlag>, ShouldParseIf; +def finitial_counter_value_EQ : Joined<["-"], "finitial-counter-value=">, + HelpText<"Sets the initial value for __COUNTER__, defaults to 0.">, + MarshallingInfoInt, "0">; + } // let Visibility = [CC1Option] //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 39754847a93e4..b79e6072cff15 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -226,7 +226,7 @@ class Preprocessor { LangOptions::FPEvalMethodKind::FEM_UnsetOnCommandLine; // Next __COUNTER__ value, starts at 0. - unsigned CounterValue = 0; + unsigned long CounterValue = 0; enum { /// Maximum depth of \#includes. @@ -2421,8 +2421,8 @@ class Preprocessor { bool SawDateOrTime() const { return DATELoc != SourceLocation() || TIMELoc != SourceLocation(); } - unsigned getCounterValue() const { return CounterValue; } - void setCounterValue(unsigned V) { CounterValue = V; } + unsigned long getCounterValue() const { return CounterValue; } + void setCounterValue(unsigned long V) { CounterValue = V; } LangOptions::FPEvalMethodKind getCurrentFPEvalMethod() const { assert(CurrentFPEvalMethod != LangOptions::FEM_UnsetOnCommandLine && diff --git a/clang/include/clang/Lex/PreprocessorOptions.h b/clang/include/clang/Lex/PreprocessorOptions.h index d4c4e1ccbf2c4..2b65e9422a5e5 100644 --- a/clang/include/clang/Lex/PreprocessorOptions.h +++ b/clang/include/clang/Lex/PreprocessorOptions.h @@ -198,6 +198,10 @@ class PreprocessorOptions { /// If set, the UNIX timestamp specified by SOURCE_DATE_EPOCH. std::optional SourceDateEpoch; + /// The initial value for __COUNTER__; typically is zero but can be set via a + /// -cc1 flag for testing purposes. + unsigned long InitialCounterValue = 0; + public: PreprocessorOptions() : PrecompiledPreambleBytes(0, false) {} diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index af856a8097ab1..485bfad8c9e1a 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -221,7 +221,7 @@ class ASTReaderListener { /// Receives __COUNTER__ value. virtual void ReadCounter(const serialization::ModuleFile &M, - unsigned Value) {} + unsigned long Value) {} /// This is called for each AST file loaded. virtual void visitModuleFile(StringRef Filename, @@ -312,7 +312,8 @@ class ChainedASTReaderListener : public ASTReaderListener { bool Complain, std::string &SuggestedPredefines) override; - void ReadCounter(const serialization::ModuleFile &M, unsigned Value) override; + void ReadCounter(const serialization::ModuleFile &M, + unsigned long Value) override; bool needsInputFileVisitation() override; bool needsSystemInputFileVisitation() override; void visitModuleFile(StringRef Filename, @@ -352,7 +353,8 @@ class PCHValidator : public ASTReaderListener { StringRef ModuleFilename, StringRef SpecificModuleCachePath, bool Complain) override; - void ReadCounter(const serialization::ModuleFile &M, unsigned Value) override; + void ReadCounter(const serialization::ModuleFile &M, + unsigned long Value) override; }; /// ASTReaderListenter implementation to set SuggestedPredefines of diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index cb445682ac48b..ff48faa02f593 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -520,7 +520,7 @@ class ASTInfoCollector : public ASTReaderListener { CodeGenOptions &CodeGenOpts; std::shared_ptr &TargetOpts; IntrusiveRefCntPtr &Target; - unsigned &Counter; + unsigned long &Counter; bool InitializedLanguage = false; bool InitializedHeaderSearchPaths = false; @@ -529,7 +529,8 @@ class ASTInfoCollector : public ASTReaderListener { HeaderSearchOptions &HSOpts, PreprocessorOptions &PPOpts, LangOptions &LangOpt, CodeGenOptions &CodeGenOpts, std::shared_ptr &TargetOpts, - IntrusiveRefCntPtr &Target, unsigned &Counter) + IntrusiveRefCntPtr &Target, + unsigned long &Counter) : PP(PP), Context(Context), HSOpts(HSOpts), PPOpts(PPOpts), LangOpt(LangOpt), CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), Target(Target), Counter(Counter) {} @@ -627,7 +628,7 @@ class ASTInfoCollector : public ASTReaderListener { } void ReadCounter(const serialization::ModuleFile &M, - unsigned Value) override { + unsigned long Value) override { Counter = Value; } @@ -873,7 +874,7 @@ std::unique_ptr ASTUnit::LoadFromASTFile( /*isysroot=*/"", /*DisableValidationKind=*/disableValid, AllowASTWithCompilerErrors); - unsigned Counter = 0; + unsigned long Counter = 0; AST->Reader->setListener(std::make_unique( *AST->PP, AST->Ctx.get(), *AST->HSOpts, *AST->PPOpts, *AST->LangOpts, *AST->CodeGenOpts, AST->TargetOpts, AST->Target, Counter)); diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 877ab02850667..aaf01705caa5e 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -1569,6 +1569,9 @@ void clang::InitializePreprocessor(Preprocessor &PP, llvm::raw_string_ostream Predefines(PredefineBuffer); MacroBuilder Builder(Predefines); + // Ensure that the initial value of __COUNTER__ is hooked up. + PP.setCounterValue(InitOpts.InitialCounterValue); + // Emit line markers for various builtin sections of the file. The 3 here // marks as being a system header, which suppresses warnings when // the same macro is defined multiple times. diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index dec1956ea0f9a..37eef9060d4b5 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -1737,7 +1737,18 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { Diag(getLastFPEvalPragmaLocation(), diag::note_pragma_entered_here); } } else if (II == Ident__COUNTER__) { - // __COUNTER__ expands to a simple numeric value. + Diag(Tok.getLocation(), + getLangOpts().C2y ? diag::warn_counter : diag::ext_counter); + // __COUNTER__ expands to a simple numeric value that must be less than + // 2147483647. + if (CounterValue > 2147483647) { + Diag(Tok.getLocation(), diag::err_counter_overflow); + // Retain the maximal value so we don't issue conversion-related + // diagnostics by overflowing into a long long. While this does produce + // a duplicate value, there's no way to ignore this error so there's no + // translation anyway. + CounterValue = 2147483647; + } OS << CounterValue++; Tok.setKind(tok::numeric_constant); } else if (II == Ident__has_feature) { diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 6acf79acea111..32d0f36d17459 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -225,7 +225,7 @@ bool ChainedASTReaderListener::ReadPreprocessorOptions( } void ChainedASTReaderListener::ReadCounter(const serialization::ModuleFile &M, - unsigned Value) { + unsigned long Value) { First->ReadCounter(M, Value); Second->ReadCounter(M, Value); } @@ -973,7 +973,7 @@ bool PCHValidator::ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, PP.getPreprocessorOpts()); } -void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) { +void PCHValidator::ReadCounter(const ModuleFile &M, unsigned long Value) { PP.setCounterValue(Value); } diff --git a/clang/test/C/C2y/n3457.c b/clang/test/C/C2y/n3457.c new file mode 100644 index 0000000000000..77e7b7ed5ecfe --- /dev/null +++ b/clang/test/C/C2y/n3457.c @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -verify=ext -std=c23 -pedantic %s +// RUN: %clang_cc1 -verify=pre -std=c2y -pedantic -Wpre-c2y-compat %s + +/* WG14 N3457: Clang 22 + * The __COUNTER__ predefined macro + * + * This predefined macro was supported as an extension in earlier versions of + * Clang, but the required diagnostics for the limits were not added until 22. + */ + +// Ensure that __COUNTER__ starts from 0. +static_assert(__COUNTER__ == 0); /* ext-warning {{'__COUNTER__' is a C2y extension}} + pre-warning {{'__COUNTER__' is incompatible with standards before C2y}} + */ + +// Ensure that the produced value can be used with token concatenation. +#define CAT_IMPL(a, b) a ## b +#define CAT(a, b) CAT_IMPL(a, b) +#define NAME_WITH_COUNTER(a) CAT(a, __COUNTER__) +void test() { + // Because this is the 2nd expansion, this defines test1. + int NAME_WITH_COUNTER(test); /* ext-warning {{'__COUNTER__' is a C2y extension}} + pre-warning {{'__COUNTER__' is incompatible with standards before C2y}} + */ + int other_test = test1; // Ok +} + +// Ensure that __COUNTER__ increments each time you mention it. +static_assert(__COUNTER__ == 2); /* ext-warning {{'__COUNTER__' is a C2y extension}} + pre-warning {{'__COUNTER__' is incompatible with standards before C2y}} + */ +static_assert(__COUNTER__ == 3); /* ext-warning {{'__COUNTER__' is a C2y extension}} + pre-warning {{'__COUNTER__' is incompatible with standards before C2y}} + */ +static_assert(__COUNTER__ == 4); /* ext-warning {{'__COUNTER__' is a C2y extension}} + pre-warning {{'__COUNTER__' is incompatible with standards before C2y}} + */ diff --git a/clang/test/C/C2y/n3457_1.c b/clang/test/C/C2y/n3457_1.c new file mode 100644 index 0000000000000..2612d096e23fc --- /dev/null +++ b/clang/test/C/C2y/n3457_1.c @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -verify -std=c2y -finitial-counter-value=2147483646 %s + +// The value produced needs to be a type that's representable with a signed +// long. However, the actual type it expands to does *not* need to be forced to +// be signed long because that would generally mean suffixing the value with L, +// which would be very surprising for folks using this to generate unique ids. +// We'll test this by ensuring the largest value can be expanded properly and +// an assertion that signed long is always at least four bytes wide (which is +// what's required to represent that maximal value). +// +// So we set the initial counter value to 2147483646, we'll validate that, +// increment it once to get to the maximal value and ensure there's no +// diagnostic, then increment again to ensure we get the constraint violation. + +static_assert(__COUNTER__ == 2147483646); // Test and increment +static_assert(__COUNTER__ == 2147483647); // Test and increment + +// This one should fail. +signed long i = __COUNTER__; // expected-error {{'__COUNTER__' value cannot exceed 2147483647}} + diff --git a/clang/test/C/C2y/n3457_2.c b/clang/test/C/C2y/n3457_2.c new file mode 100644 index 0000000000000..cf268283e11c6 --- /dev/null +++ b/clang/test/C/C2y/n3457_2.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -verify=good -std=c2y -finitial-counter-value=2147483648 %s +// RUN: %clang_cc1 -verify -std=c2y -finitial-counter-value=2147483648 -DEXPAND_IT %s +// good-no-diagnostics + +// This sets the intial __COUNTER__ value to something that's too big. Setting +// the value too large is fine. Expanding to a too-large value is not. +#ifdef EXPAND_IT + // This one should fail. + signed long i = __COUNTER__; // expected-error {{'__COUNTER__' value cannot exceed 2147483647}} +#endif diff --git a/clang/www/c_status.html b/clang/www/c_status.html index 380f66495a367..96dcaf14aae02 100644 --- a/clang/www/c_status.html +++ b/clang/www/c_status.html @@ -329,7 +329,7 @@

C2y implementation status

The __COUNTER__ predefined macro N3457 - Unknown + Clang 22 Chasing Ghosts I: constant expressions v2 From 1d0a459b44489e6a1471464571bdfffe97158d1b Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Thu, 9 Oct 2025 12:11:52 -0400 Subject: [PATCH 2/7] Clang 22 isn't released yet --- clang/www/c_status.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/www/c_status.html b/clang/www/c_status.html index 96dcaf14aae02..eeff464313245 100644 --- a/clang/www/c_status.html +++ b/clang/www/c_status.html @@ -329,7 +329,7 @@

C2y implementation status

The __COUNTER__ predefined macro N3457 - Clang 22 + Clang 22 Chasing Ghosts I: constant expressions v2 From 7129a6ad493ca1a33b388eb4e6b6bde406cf9dd0 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Thu, 9 Oct 2025 12:13:15 -0400 Subject: [PATCH 3/7] Use a named constant; NFC --- clang/lib/Lex/PPMacroExpansion.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 37eef9060d4b5..8213e2bc2d769 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -1741,13 +1741,14 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { getLangOpts().C2y ? diag::warn_counter : diag::ext_counter); // __COUNTER__ expands to a simple numeric value that must be less than // 2147483647. - if (CounterValue > 2147483647) { + constexpr unsigned long MaxPosValue = std::numeric_limits::max(); + if (CounterValue > MaxPosValue) { Diag(Tok.getLocation(), diag::err_counter_overflow); // Retain the maximal value so we don't issue conversion-related // diagnostics by overflowing into a long long. While this does produce // a duplicate value, there's no way to ignore this error so there's no // translation anyway. - CounterValue = 2147483647; + CounterValue = MaxPosValue; } OS << CounterValue++; Tok.setKind(tok::numeric_constant); From 1c123deb64d25e7e7f0966f37b73165a92916ed2 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Thu, 9 Oct 2025 12:14:28 -0400 Subject: [PATCH 4/7] Add C++ pedantic test --- clang/test/C/C2y/n3457.c | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/test/C/C2y/n3457.c b/clang/test/C/C2y/n3457.c index 77e7b7ed5ecfe..d71a3f37e1343 100644 --- a/clang/test/C/C2y/n3457.c +++ b/clang/test/C/C2y/n3457.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -verify=ext -std=c23 -pedantic %s +// RUN: %clang_cc1 -verify=ext -pedantic -x c++ %s // RUN: %clang_cc1 -verify=pre -std=c2y -pedantic -Wpre-c2y-compat %s /* WG14 N3457: Clang 22 From 07207716fe0409e45d3383afef71867973974997 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Thu, 9 Oct 2025 12:15:37 -0400 Subject: [PATCH 5/7] Update Language Extensions docs for backporting --- clang/docs/LanguageExtensions.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 54c215e9ccfaa..7fdc991af3b60 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1823,6 +1823,7 @@ Octal literals prefixed with ``0o`` or ``0O`` C ``_Countof`` (N3369, N3469) C2y C89 ``_Generic`` with a type operand (N3260) C2y C89, C++ ``++``/``--`` on ``_Complex`` value (N3259) C2y C89, C++ +``__COUNTER__`` (N3457) C2y C89, C++ ============================================= ================================ ============= ============= Builtin type aliases From 19e851e0cd78ab377d54d82bff70a6250a1644ea Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Thu, 9 Oct 2025 12:40:24 -0400 Subject: [PATCH 6/7] unsigned long -> uint32_t; NFC --- clang/include/clang/Lex/Preprocessor.h | 6 +++--- clang/include/clang/Lex/PreprocessorOptions.h | 2 +- clang/include/clang/Serialization/ASTReader.h | 10 ++++------ clang/lib/Frontend/ASTUnit.cpp | 9 ++++----- clang/lib/Lex/PPMacroExpansion.cpp | 2 +- clang/lib/Serialization/ASTReader.cpp | 4 ++-- 6 files changed, 15 insertions(+), 18 deletions(-) diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index b79e6072cff15..412002259c054 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -226,7 +226,7 @@ class Preprocessor { LangOptions::FPEvalMethodKind::FEM_UnsetOnCommandLine; // Next __COUNTER__ value, starts at 0. - unsigned long CounterValue = 0; + uint32_t CounterValue = 0; enum { /// Maximum depth of \#includes. @@ -2421,8 +2421,8 @@ class Preprocessor { bool SawDateOrTime() const { return DATELoc != SourceLocation() || TIMELoc != SourceLocation(); } - unsigned long getCounterValue() const { return CounterValue; } - void setCounterValue(unsigned long V) { CounterValue = V; } + uint32_t getCounterValue() const { return CounterValue; } + void setCounterValue(uint32_t V) { CounterValue = V; } LangOptions::FPEvalMethodKind getCurrentFPEvalMethod() const { assert(CurrentFPEvalMethod != LangOptions::FEM_UnsetOnCommandLine && diff --git a/clang/include/clang/Lex/PreprocessorOptions.h b/clang/include/clang/Lex/PreprocessorOptions.h index 2b65e9422a5e5..1c2f6e72e1b93 100644 --- a/clang/include/clang/Lex/PreprocessorOptions.h +++ b/clang/include/clang/Lex/PreprocessorOptions.h @@ -200,7 +200,7 @@ class PreprocessorOptions { /// The initial value for __COUNTER__; typically is zero but can be set via a /// -cc1 flag for testing purposes. - unsigned long InitialCounterValue = 0; + uint32_t InitialCounterValue = 0; public: PreprocessorOptions() : PrecompiledPreambleBytes(0, false) {} diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 485bfad8c9e1a..4ca45a16408a6 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -220,8 +220,8 @@ class ASTReaderListener { } /// Receives __COUNTER__ value. - virtual void ReadCounter(const serialization::ModuleFile &M, - unsigned long Value) {} + virtual void ReadCounter(const serialization::ModuleFile &M, uint32_t Value) { + } /// This is called for each AST file loaded. virtual void visitModuleFile(StringRef Filename, @@ -312,8 +312,7 @@ class ChainedASTReaderListener : public ASTReaderListener { bool Complain, std::string &SuggestedPredefines) override; - void ReadCounter(const serialization::ModuleFile &M, - unsigned long Value) override; + void ReadCounter(const serialization::ModuleFile &M, uint32_t Value) override; bool needsInputFileVisitation() override; bool needsSystemInputFileVisitation() override; void visitModuleFile(StringRef Filename, @@ -353,8 +352,7 @@ class PCHValidator : public ASTReaderListener { StringRef ModuleFilename, StringRef SpecificModuleCachePath, bool Complain) override; - void ReadCounter(const serialization::ModuleFile &M, - unsigned long Value) override; + void ReadCounter(const serialization::ModuleFile &M, uint32_t Value) override; }; /// ASTReaderListenter implementation to set SuggestedPredefines of diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index ff48faa02f593..cf1cd751b8e8d 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -520,7 +520,7 @@ class ASTInfoCollector : public ASTReaderListener { CodeGenOptions &CodeGenOpts; std::shared_ptr &TargetOpts; IntrusiveRefCntPtr &Target; - unsigned long &Counter; + uint32_t &Counter; bool InitializedLanguage = false; bool InitializedHeaderSearchPaths = false; @@ -529,8 +529,7 @@ class ASTInfoCollector : public ASTReaderListener { HeaderSearchOptions &HSOpts, PreprocessorOptions &PPOpts, LangOptions &LangOpt, CodeGenOptions &CodeGenOpts, std::shared_ptr &TargetOpts, - IntrusiveRefCntPtr &Target, - unsigned long &Counter) + IntrusiveRefCntPtr &Target, uint32_t &Counter) : PP(PP), Context(Context), HSOpts(HSOpts), PPOpts(PPOpts), LangOpt(LangOpt), CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), Target(Target), Counter(Counter) {} @@ -628,7 +627,7 @@ class ASTInfoCollector : public ASTReaderListener { } void ReadCounter(const serialization::ModuleFile &M, - unsigned long Value) override { + uint32_t Value) override { Counter = Value; } @@ -874,7 +873,7 @@ std::unique_ptr ASTUnit::LoadFromASTFile( /*isysroot=*/"", /*DisableValidationKind=*/disableValid, AllowASTWithCompilerErrors); - unsigned long Counter = 0; + uint32_t Counter = 0; AST->Reader->setListener(std::make_unique( *AST->PP, AST->Ctx.get(), *AST->HSOpts, *AST->PPOpts, *AST->LangOpts, *AST->CodeGenOpts, AST->TargetOpts, AST->Target, Counter)); diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 8213e2bc2d769..ef49598243c5b 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -1741,7 +1741,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { getLangOpts().C2y ? diag::warn_counter : diag::ext_counter); // __COUNTER__ expands to a simple numeric value that must be less than // 2147483647. - constexpr unsigned long MaxPosValue = std::numeric_limits::max(); + constexpr uint32_t MaxPosValue = std::numeric_limits::max(); if (CounterValue > MaxPosValue) { Diag(Tok.getLocation(), diag::err_counter_overflow); // Retain the maximal value so we don't issue conversion-related diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 32d0f36d17459..73653f64b1543 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -225,7 +225,7 @@ bool ChainedASTReaderListener::ReadPreprocessorOptions( } void ChainedASTReaderListener::ReadCounter(const serialization::ModuleFile &M, - unsigned long Value) { + uint32_t Value) { First->ReadCounter(M, Value); Second->ReadCounter(M, Value); } @@ -973,7 +973,7 @@ bool PCHValidator::ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, PP.getPreprocessorOpts()); } -void PCHValidator::ReadCounter(const ModuleFile &M, unsigned long Value) { +void PCHValidator::ReadCounter(const ModuleFile &M, uint32_t Value) { PP.setCounterValue(Value); } From aabea7c7cecc2b9b55419a8c128521df9b241540 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Fri, 10 Oct 2025 08:01:35 -0400 Subject: [PATCH 7/7] Use digit separators in the diagnostic --- clang/include/clang/Basic/DiagnosticLexKinds.td | 2 +- clang/test/C/C2y/n3457_1.c | 2 +- clang/test/C/C2y/n3457_2.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td index 46a7a88f7a50b..417187222e448 100644 --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -91,7 +91,7 @@ def err_unterminated___pragma : Error<"missing terminating ')' character">; def err_conflict_marker : Error<"version control conflict marker in file">; def err_counter_overflow : Error< - "'__COUNTER__' value cannot exceed 2147483647">; + "'__COUNTER__' value cannot exceed 2'147'483'647">; def ext_counter : Extension< "'__COUNTER__' is a C2y extension">, InGroup; def warn_counter : Warning< diff --git a/clang/test/C/C2y/n3457_1.c b/clang/test/C/C2y/n3457_1.c index 2612d096e23fc..76c5a0b9a700f 100644 --- a/clang/test/C/C2y/n3457_1.c +++ b/clang/test/C/C2y/n3457_1.c @@ -16,5 +16,5 @@ static_assert(__COUNTER__ == 2147483646); // Test and increment static_assert(__COUNTER__ == 2147483647); // Test and increment // This one should fail. -signed long i = __COUNTER__; // expected-error {{'__COUNTER__' value cannot exceed 2147483647}} +signed long i = __COUNTER__; // expected-error {{'__COUNTER__' value cannot exceed 2'147'483'647}} diff --git a/clang/test/C/C2y/n3457_2.c b/clang/test/C/C2y/n3457_2.c index cf268283e11c6..018c8f4390767 100644 --- a/clang/test/C/C2y/n3457_2.c +++ b/clang/test/C/C2y/n3457_2.c @@ -6,5 +6,5 @@ // the value too large is fine. Expanding to a too-large value is not. #ifdef EXPAND_IT // This one should fail. - signed long i = __COUNTER__; // expected-error {{'__COUNTER__' value cannot exceed 2147483647}} + signed long i = __COUNTER__; // expected-error {{'__COUNTER__' value cannot exceed 2'147'483'647}} #endif