https://github.com/ianayl updated https://github.com/llvm/llvm-project/pull/224769
>From fd0ec1d6dd50bdd02a1e32ba49c7146dcf8bad73 Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Fri, 18 Sep 2026 15:34:24 -0700 Subject: [PATCH 01/12] Implement CWG3013 in clang, but only for C++ --- clang/docs/ReleaseNotes.md | 18 ++++++ clang/include/clang/Basic/DiagnosticGroups.td | 4 +- .../include/clang/Basic/DiagnosticLexKinds.td | 8 +++ clang/include/clang/Lex/Preprocessor.h | 4 ++ clang/lib/Lex/PPDirectives.cpp | 4 ++ clang/lib/Lex/Preprocessor.cpp | 24 ++++++++ clang/test/CXX/drs/cwg3013.cpp | 58 +++++++++++++++++++ clang/test/CXX/drs/inputs/media/art.txt | 13 +++++ clang/test/CXX/drs/inputs/media/empty | 0 9 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 clang/test/CXX/drs/cwg3013.cpp create mode 100644 clang/test/CXX/drs/inputs/media/art.txt create mode 100644 clang/test/CXX/drs/inputs/media/empty diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index f4a34a37aff52e..da925b260ee1c1 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -54,6 +54,13 @@ in a future version of Clang. mode, as it was removed from the standard by [P3475R2](https://wg21.link/P3475R2). +- An error diagnostic is now issued if an `#embed` directive or a `__has_embed` + expression contains a parameter (i.e. `limit`, `prefix`, `suffix`, `if_empty`) + that has previously been defined as a macro, as per + [CWG3013](https://wg21.link/cwg3013). Previously macros that shared names with + `#embed` parameter names were expanded regardless, similar to its behavior in + C: Note that this expansion behavior is still present in C since there are no + rule analogue to CWG3013 in C. ### Objective-C Specific Potentially Breaking Changes @@ -194,6 +201,11 @@ features cannot lower the translation-unit ABI level; them to an enumeration type with a fixed `bool` underlying type. This resolves [CWG1094](https://wg21.link/cwg1094). +- Clang now diagnoses an error if an `#embed` directive or `__has_embed` + statement uses a parameter name (i.e. `limit`, `prefix`, `suffix`, `if_empty`) + that has previously been defined as a macro. This resolves + [CWG3013](https://wg21.link/cwg3013), which marks such code as ill-formed. + ### C Language Changes #### C2y Feature Support @@ -518,6 +530,12 @@ features cannot lower the translation-unit ABI level; - Improve Clang diagnoses when unary `__imag` operator with non-complex type operand is used as lvalue. (GH222383) +- Added `-Wembed-parameter-is-macro`, which warns in C if an `#embed` directive + or a `__has_embed` expression uses a parameter (i.e. `limit`, `prefix`, + `suffix`, `if_empty`) that has also been defined as a macro. C expands the + macro, but the same code is ill-formed in C++, so `-Wembed-parameter-is-macro` + is also part of `-Wc++-compat`; this warning is disabled by default otherwise. + ### Improvements to Clang's time-trace ### Improvements to Coverage Mapping diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 1da7698944b24b..b3c36c76d490bb 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -187,6 +187,7 @@ def C23Compat : DiagGroup<"c23-compat">; def : DiagGroup<"c2x-compat", [C23Compat]>; def CppKeywordInC : DiagGroup<"c++-keyword">; +def EmbedParameterIsMacro : DiagGroup<"embed-parameter-is-macro">; def DuplicateDeclSpecifier : DiagGroup<"duplicate-decl-specifier">; def InitStringTooLongMissingNonString : DiagGroup<"unterminated-string-initialization">; @@ -212,7 +213,8 @@ def CXXCompat: DiagGroup<"c++-compat", [ImplicitVoidPtrCast, DefaultConstInit, ImplicitIntToEnumCast, HiddenCppDecl, InitStringTooLongForCpp, CppKeywordInC, TentativeDefnCompat, JumpBypassesInit, - DuplicateDeclSpecifier]>; + DuplicateDeclSpecifier, + EmbedParameterIsMacro]>; def ExternCCompat : DiagGroup<"extern-c-compat">; def KeywordCompat : DiagGroup<"keyword-compat">; diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td index ff51485a1810bf..006da9a53e96a2 100644 --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -492,6 +492,14 @@ def warn_compat_pp_embed_directive : Warning< InGroup<CPre23Compat>, DefaultIgnore; def err_pp_embed_dup_params : Error< "cannot specify parameter '%0' twice in the same '#embed' directive">; +def err_pp_embed_parameter_is_macro : Error< + "cannot use %0 as %select{an '#embed'|a '__has_embed'}1 parameter if also" + " defined as a macro">; +def warn_c_pp_embed_parameter_is_macro : Warning< + "%0 is defined as a macro and gets expanded when used as a " + "%select{an '#embed'|a '__has_embed'}1 parameter in C; this is " + "ill-formed in C++">, + InGroup<EmbedParameterIsMacro>, DefaultIgnore; def err_pp_embed_device_file : Error< "device files are not yet supported by '#embed' directive">; diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 31b68a0fd0670e..4711728b1b7640 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -302,6 +302,10 @@ class Preprocessor { /// True if we are currently preprocessing a #if or #elif directive bool ParsingIfOrElifDirective; + /// True if we are preprocessing the parameters of an #embed directive or a + /// __has_embed expression. + bool ParsingEmbedParameters; + /// True if we are pre-expanding macro arguments. bool InMacroArgPreExpansion; diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index f1e9aaa72ff048..0b7c727d2ce890 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -3771,6 +3771,10 @@ void Preprocessor::HandleElifFamilyDirective(Token &ElifToken, std::optional<LexEmbedParametersResult> Preprocessor::LexEmbedParameters(Token &CurTok, bool ForHasEmbed) { LexEmbedParametersResult Result{}; + if (ForHasEmbed) + assert(isParsingIfOrElifDirective() && + "__has_embed outside of #if or #elif directive?"); + llvm::SaveAndRestore InEmbedParams(ParsingEmbedParameters, true); tok::TokenKind EndTokenKind = ForHasEmbed ? tok::r_paren : tok::eod; auto DiagMismatchedBracesAndSkipToEOD = diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index 84907adc5d744a..9bab63818007c7 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -119,6 +119,7 @@ Preprocessor::Preprocessor(const PreprocessorOptions &PPOpts, NumCachedTokenLexers = 0; PragmasEnabled = true; ParsingIfOrElifDirective = false; + ParsingEmbedParameters = false; PreprocessedOutput = false; // We haven't read anything from the external source. @@ -879,6 +880,11 @@ void Preprocessor::updateOutOfDateIdentifier(const IdentifierInfo &II) const { getExternalSource()->updateOutOfDateIdentifier(II); } +static bool isProtectedEmbedParameterName(const IdentifierInfo *II) { + return II->isStr("limit") || II->isStr("prefix") || II->isStr("suffix") || + II->isStr("if_empty"); +} + /// HandleIdentifier - This callback is invoked when the lexer reads an /// identifier. This callback looks up the identifier in the map and/or /// potentially macro expands it or turns it into a named token (like 'for'). @@ -922,6 +928,24 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) { if (const MacroDefinition MD = getMacroDefinition(&II)) { const auto *MI = MD.getMacroInfo(); assert(MI && "macro definition with no macro info?"); + // C++ [cpp.pre]/p4, [cpp.cond]/p9: if one of the pp-tokens of a #embed + // directive (or a has-embed-expression) is the identifier limit, prefix, + // suffix, or if_empty and that identifier is defined as a macro, the + // program is ill-formed. + // + // Thus, do not continue processing if compiling for C++. C doesn't have + // this restriction however, so only issue a warning for C if -Wc++-compat + // is enabled. + if (ParsingEmbedParameters && isProtectedEmbedParameterName(&II)) { + Diag(Identifier, getLangOpts().CPlusPlus + ? diag::err_pp_embed_parameter_is_macro + : diag::warn_c_pp_embed_parameter_is_macro) + << &II << isParsingIfOrElifDirective(); + Diag(MI->getDefinitionLoc(), diag::note_macro_here) << &II; + if (getLangOpts().CPlusPlus) + return true; + } + if (!DisableMacroExpansion) { if (!Identifier.isExpandDisabled() && MI->isEnabled()) { // C99 6.10.3p10: If the preprocessing token immediately after the diff --git a/clang/test/CXX/drs/cwg3013.cpp b/clang/test/CXX/drs/cwg3013.cpp new file mode 100644 index 00000000000000..95f4f6fc6f9e2a --- /dev/null +++ b/clang/test/CXX/drs/cwg3013.cpp @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 --embed-dir=%S/inputs -Wno-c23-extensions -fsyntax-only -verify=cxx,common -x c++ %s +// RUN: %clang_cc1 --embed-dir=%S/inputs -fsyntax-only -verify=c -std=c23 -x c %s +// RUN: %clang_cc1 --embed-dir=%S/inputs -fsyntax-only -verify=c-compat,common -std=c23 -Wc++-compat -x c %s +// +// Test -Wembed-parameter-is-macro: +// RUN: %clang_cc1 --embed-dir=%S/inputs -fsyntax-only -verify=c-compat,common -std=c23 -Wembed-parameter-is-macro -x c %s +// RUN: %clang_cc1 --embed-dir=%S/inputs -fsyntax-only -verify=c -std=c23 -Wc++-compat -Wno-embed-parameter-is-macro -x c %s + +// CWG3013: if one of the pp-tokens of a #embed directive (or a +// has-embed-expression) is the identifier limit, prefix, suffix, or if_empty +// and that identifier is defined as a macro, the program is ill-formed. +// (C++ [cpp.pre]/p4, [cpp.cond]/p9) +// +// However, C doesn't have this restriction, so we should only issue a warning +// for C if -Wc++-compat/-Wembed-parameter-is-macro is enabled. + +// c-no-diagnostics + +#define limit limit +// common-note@-1 2 {{macro 'limit' defined here}} +const int a[] = { +#embed <media/art.txt> limit(2) +// cxx-error@-1 {{cannot use 'limit' as an '#embed' parameter if also defined as a macro}} +// c-compat-warning@-2 {{'limit' is defined as a macro and gets expanded when used as an '#embed' parameter in C; this is ill-formed in C++}} +}; + +#define prefix prefix +// common-note@-1 {{macro 'prefix' defined here}} +const int b[] = { +#embed <media/art.txt> prefix(0,) +// cxx-error@-1 {{cannot use 'prefix' as an '#embed' parameter if also defined as a macro}} +// c-compat-warning@-2 {{'prefix' is defined as a macro and gets expanded when used as an '#embed' parameter in C; this is ill-formed in C++}} +}; + +#define suffix suffix +// common-note@-1 2 {{macro 'suffix' defined here}} +const int c[] = { +#embed <media/art.txt> suffix(,0) +// cxx-error@-1 {{cannot use 'suffix' as an '#embed' parameter if also defined as a macro}} +// c-compat-warning@-2 {{'suffix' is defined as a macro and gets expanded when used as an '#embed' parameter in C; this is ill-formed in C++}} +}; + +#define if_empty if_empty +// common-note@-1 {{macro 'if_empty' defined here}} +const int d[] = { +#embed <media/empty> if_empty(0) +// cxx-error@-1 {{cannot use 'if_empty' as an '#embed' parameter if also defined as a macro}} +// c-compat-warning@-2 {{'if_empty' is defined as a macro and gets expanded when used as an '#embed' parameter in C; this is ill-formed in C++}} +}; + +// The prohibition also covers the __has_embed argument. +#if __has_embed(<media/art.txt> limit(1) suffix(0)) +// cxx-error@-1 {{cannot use 'limit' as a '__has_embed' parameter if also defined as a macro}} +// cxx-error@-2 {{cannot use 'suffix' as a '__has_embed' parameter if also defined as a macro}} +// c-compat-warning@-3 {{'limit' is defined as a macro and gets expanded when used as a '__has_embed' parameter in C; this is ill-formed in C++}} +// c-compat-warning@-4 {{'suffix' is defined as a macro and gets expanded when used as a '__has_embed' parameter in C; this is ill-formed in C++}} +int e; +#endif diff --git a/clang/test/CXX/drs/inputs/media/art.txt b/clang/test/CXX/drs/inputs/media/art.txt new file mode 100644 index 00000000000000..f4536f39af349d --- /dev/null +++ b/clang/test/CXX/drs/inputs/media/art.txt @@ -0,0 +1,13 @@ + + ------------------------------------------- + . . + . _ . + . _ _ >(. ) _ . + . >(. )__ >(- )__ //___ >(. )__ . + . ~(____/ -~(_(=-/-~~(_(__/-~~(____/~ . + . ~. -~~~ . -~. ~~- . + . ~- . + . . + ------------------------------------------- + + O Pato \ No newline at end of file diff --git a/clang/test/CXX/drs/inputs/media/empty b/clang/test/CXX/drs/inputs/media/empty new file mode 100644 index 00000000000000..e69de29bb2d1d6 >From f3284b6d51d229603ef0ac32a22d02f495ed2b9d Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Fri, 18 Sep 2026 16:14:30 -0700 Subject: [PATCH 02/12] typo --- clang/include/clang/Basic/DiagnosticLexKinds.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td index 006da9a53e96a2..fbe9fc1461f09d 100644 --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -496,7 +496,7 @@ def err_pp_embed_parameter_is_macro : Error< "cannot use %0 as %select{an '#embed'|a '__has_embed'}1 parameter if also" " defined as a macro">; def warn_c_pp_embed_parameter_is_macro : Warning< - "%0 is defined as a macro and gets expanded when used as a " + "%0 is defined as a macro and gets expanded when used as " "%select{an '#embed'|a '__has_embed'}1 parameter in C; this is " "ill-formed in C++">, InGroup<EmbedParameterIsMacro>, DefaultIgnore; >From f32f333e7872597bbdfb8fbdaf16cff61ad6ad1c Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Mon, 21 Sep 2026 20:39:07 -0700 Subject: [PATCH 03/12] split c/c++ tests and make cwg test conform to other dr tests --- clang/test/CXX/drs/cwg3013.cpp | 75 +++++++++------------- clang/test/CXX/drs/cwg30xx.cpp | 2 + clang/test/Preprocessor/embed_cxx_compat.c | 51 +++++++++++++++ 3 files changed, 84 insertions(+), 44 deletions(-) create mode 100644 clang/test/Preprocessor/embed_cxx_compat.c diff --git a/clang/test/CXX/drs/cwg3013.cpp b/clang/test/CXX/drs/cwg3013.cpp index 95f4f6fc6f9e2a..965ac8d1803698 100644 --- a/clang/test/CXX/drs/cwg3013.cpp +++ b/clang/test/CXX/drs/cwg3013.cpp @@ -1,58 +1,45 @@ -// RUN: %clang_cc1 --embed-dir=%S/inputs -Wno-c23-extensions -fsyntax-only -verify=cxx,common -x c++ %s -// RUN: %clang_cc1 --embed-dir=%S/inputs -fsyntax-only -verify=c -std=c23 -x c %s -// RUN: %clang_cc1 --embed-dir=%S/inputs -fsyntax-only -verify=c-compat,common -std=c23 -Wc++-compat -x c %s -// -// Test -Wembed-parameter-is-macro: -// RUN: %clang_cc1 --embed-dir=%S/inputs -fsyntax-only -verify=c-compat,common -std=c23 -Wembed-parameter-is-macro -x c %s -// RUN: %clang_cc1 --embed-dir=%S/inputs -fsyntax-only -verify=c -std=c23 -Wc++-compat -Wno-embed-parameter-is-macro -x c %s - -// CWG3013: if one of the pp-tokens of a #embed directive (or a -// has-embed-expression) is the identifier limit, prefix, suffix, or if_empty -// and that identifier is defined as a macro, the program is ill-formed. -// (C++ [cpp.pre]/p4, [cpp.cond]/p9) -// -// However, C doesn't have this restriction, so we should only issue a warning -// for C if -Wc++-compat/-Wembed-parameter-is-macro is enabled. - -// c-no-diagnostics - -#define limit limit -// common-note@-1 2 {{macro 'limit' defined here}} +// RUN: %clang_cc1 -std=c++2c -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -Wno-c23-extensions -verify %s + +// C doesn't have an analogue to CWG3013: There is a corresponding C test at +// clang/test/Preprocessor/embed_cxx_compat.c testing an opt-in CXX-compat +// diagnostic. + +namespace cwg3013 { // cwg3013: 24 + +#define limit limit // #cwg3013-limit const int a[] = { -#embed <media/art.txt> limit(2) -// cxx-error@-1 {{cannot use 'limit' as an '#embed' parameter if also defined as a macro}} -// c-compat-warning@-2 {{'limit' is defined as a macro and gets expanded when used as an '#embed' parameter in C; this is ill-formed in C++}} +#embed __FILE__ limit(2) +// expected-error@-1 {{cannot use 'limit' as an '#embed' parameter if also defined as a macro}} +// expected-note@#cwg3013-limit {{macro 'limit' defined here}} }; -#define prefix prefix -// common-note@-1 {{macro 'prefix' defined here}} +#define prefix prefix // #cwg3013-prefix const int b[] = { -#embed <media/art.txt> prefix(0,) -// cxx-error@-1 {{cannot use 'prefix' as an '#embed' parameter if also defined as a macro}} -// c-compat-warning@-2 {{'prefix' is defined as a macro and gets expanded when used as an '#embed' parameter in C; this is ill-formed in C++}} +#embed __FILE__ prefix(0,) +// expected-error@-1 {{cannot use 'prefix' as an '#embed' parameter if also defined as a macro}} +// expected-note@#cwg3013-prefix {{macro 'prefix' defined here}} }; -#define suffix suffix -// common-note@-1 2 {{macro 'suffix' defined here}} +#define suffix suffix // #cwg3013-suffix const int c[] = { -#embed <media/art.txt> suffix(,0) -// cxx-error@-1 {{cannot use 'suffix' as an '#embed' parameter if also defined as a macro}} -// c-compat-warning@-2 {{'suffix' is defined as a macro and gets expanded when used as an '#embed' parameter in C; this is ill-formed in C++}} +#embed __FILE__ suffix(,0) +// expected-error@-1 {{cannot use 'suffix' as an '#embed' parameter if also defined as a macro}} +// expected-note@#cwg3013-suffix {{macro 'suffix' defined here}} }; -#define if_empty if_empty -// common-note@-1 {{macro 'if_empty' defined here}} +#define if_empty if_empty // #cwg3013-if_empty const int d[] = { -#embed <media/empty> if_empty(0) -// cxx-error@-1 {{cannot use 'if_empty' as an '#embed' parameter if also defined as a macro}} -// c-compat-warning@-2 {{'if_empty' is defined as a macro and gets expanded when used as an '#embed' parameter in C; this is ill-formed in C++}} +#embed __FILE__ if_empty(0) +// expected-error@-1 {{cannot use 'if_empty' as an '#embed' parameter if also defined as a macro}} +// expected-note@#cwg3013-if_empty {{macro 'if_empty' defined here}} }; -// The prohibition also covers the __has_embed argument. -#if __has_embed(<media/art.txt> limit(1) suffix(0)) -// cxx-error@-1 {{cannot use 'limit' as a '__has_embed' parameter if also defined as a macro}} -// cxx-error@-2 {{cannot use 'suffix' as a '__has_embed' parameter if also defined as a macro}} -// c-compat-warning@-3 {{'limit' is defined as a macro and gets expanded when used as a '__has_embed' parameter in C; this is ill-formed in C++}} -// c-compat-warning@-4 {{'suffix' is defined as a macro and gets expanded when used as a '__has_embed' parameter in C; this is ill-formed in C++}} +#if __has_embed(__FILE__ limit(1) suffix(0)) +// expected-error@-1 {{cannot use 'limit' as a '__has_embed' parameter if also defined as a macro}} +// expected-note@#cwg3013-limit {{macro 'limit' defined here}} +// expected-error@-3 {{cannot use 'suffix' as a '__has_embed' parameter if also defined as a macro}} +// expected-note@#cwg3013-suffix {{macro 'suffix' defined here}} int e; #endif + +} // namespace cwg3013 \ No newline at end of file diff --git a/clang/test/CXX/drs/cwg30xx.cpp b/clang/test/CXX/drs/cwg30xx.cpp index a664fe6b3f073e..a4053b55cd751d 100644 --- a/clang/test/CXX/drs/cwg30xx.cpp +++ b/clang/test/CXX/drs/cwg30xx.cpp @@ -22,6 +22,8 @@ void f( } // namespace cwg3005 +// cwg3013 is in cwg3013.cpp + namespace cwg3035 { // cwg3035: no #if __cplusplus >= 201103L static union { diff --git a/clang/test/Preprocessor/embed_cxx_compat.c b/clang/test/Preprocessor/embed_cxx_compat.c new file mode 100644 index 00000000000000..96c7c19682cfd7 --- /dev/null +++ b/clang/test/Preprocessor/embed_cxx_compat.c @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -std=c23 --embed-dir=%S/Inputs -fsyntax-only -verify=silent %s +// RUN: %clang_cc1 -std=c23 --embed-dir=%S/Inputs -fsyntax-only -verify=compat -Wc++-compat %s +// +// Test -Wembed-parameter-is-macro: +// RUN: %clang_cc1 -std=c23 --embed-dir=%S/Inputs -fsyntax-only -verify=compat -Wembed-parameter-is-macro %s +// RUN: %clang_cc1 -std=c23 --embed-dir=%S/Inputs -fsyntax-only -verify=silent -Wc++-compat -Wno-embed-parameter-is-macro %s + +// C++ has CWG3013: if one of the pp-tokens of a #embed directive (or a +// has-embed-expression) is the identifier limit, prefix, suffix, or if_empty +// and that identifier is defined as a macro, the program is ill-formed. +// (C++ [cpp.pre]/p4, [cpp.cond]/p9) +// +// ... But C doesn't seem to have this restriction, so we allow macro-expansion +// and only warn if -Wc++-compat or -Wembed-parameter-is-macro is enabled. C++ +// conformance with CWG3013 is tested in clang/test/CXX/drs/cwg3013.cpp. + +// silent-no-diagnostics + +#define limit limit +// compat-note@-1 2 {{macro 'limit' defined here}} +const int a[] = { +#embed __FILE__ limit(2) +// compat-warning@-1 {{'limit' is defined as a macro and gets expanded when used as an '#embed' parameter in C; this is ill-formed in C++}} +}; + +#define prefix prefix +// compat-note@-1 {{macro 'prefix' defined here}} +const int b[] = { +#embed __FILE__ prefix(0,) +// compat-warning@-1 {{'prefix' is defined as a macro and gets expanded when used as an '#embed' parameter in C; this is ill-formed in C++}} +}; + +#define suffix suffix +// compat-note@-1 2 {{macro 'suffix' defined here}} +const int c[] = { +#embed __FILE__ suffix(,0) +// compat-warning@-1 {{'suffix' is defined as a macro and gets expanded when used as an '#embed' parameter in C; this is ill-formed in C++}} +}; + +#define if_empty if_empty +// compat-note@-1 {{macro 'if_empty' defined here}} +const int d[] = { +#embed __FILE__ if_empty(0) +// compat-warning@-1 {{'if_empty' is defined as a macro and gets expanded when used as an '#embed' parameter in C; this is ill-formed in C++}} +}; + +#if __has_embed(__FILE__ limit(1) suffix(0)) +// compat-warning@-1 {{'limit' is defined as a macro and gets expanded when used as a '__has_embed' parameter in C; this is ill-formed in C++}} +// compat-warning@-2 {{'suffix' is defined as a macro and gets expanded when used as a '__has_embed' parameter in C; this is ill-formed in C++}} +int e; +#endif >From 667e78bf7a6e94576c8758b6f8b1c2e3b11b7474 Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Mon, 21 Sep 2026 20:39:50 -0700 Subject: [PATCH 04/12] rerun clang/www/make_cxx_dr_status --- clang/www/cxx_dr_status.html | 128 +++++++++++++++++++++++++++++------ 1 file changed, 106 insertions(+), 22 deletions(-) diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index e7679da30d5c29..b1e31e20b70780 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -1413,12 +1413,12 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td>Converting between function and object pointers</td> <td class="full" align="center">Clang 2.7</td> </tr> - <tr class="open" id="196"> + <tr id="196"> <td><a href="https://cplusplus.github.io/CWG/issues/196.html">196</a></td> <td>[<a href="https://wg21.link/expr.delete">expr.delete</a>]</td> - <td>open</td> + <td>C++17</td> <td>Arguments to deallocation functions</td> - <td align="center">Not resolved</td> + <td class="unknown" align="center">Unknown</td> </tr> <tr id="197"> <td><a href="https://cplusplus.github.io/CWG/issues/197.html">197</a></td> @@ -1910,12 +1910,12 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td>No grammar sentence symbol</td> <td class="na" align="center">N/A</td> </tr> - <tr class="open" id="267"> + <tr id="267"> <td><a href="https://cplusplus.github.io/CWG/issues/267.html">267</a></td> <td>[<a href="https://wg21.link/expr.new">expr.new</a>]</td> - <td>open</td> + <td>NAD</td> <td>Alignment requirement for <I>new-expression</I>s</td> - <td align="center">Not resolved</td> + <td class="unknown" align="center">Unknown</td> </tr> <tr class="open" id="268"> <td><a href="https://cplusplus.github.io/CWG/issues/268.html">268</a></td> @@ -10017,12 +10017,12 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td>Deduction failure vs “ill-formed, no diagnostic required”</td> <td class="unknown" align="center">Unknown</td> </tr> - <tr class="open" id="1463"> + <tr id="1463"> <td><a href="https://cplusplus.github.io/CWG/issues/1463.html">1463</a></td> <td>[<a href="https://wg21.link/temp.pre">temp.pre</a>]</td> - <td>drafting</td> + <td>DR</td> <td><TT>extern "C"</TT> alias templates</td> - <td align="center">Not resolved</td> + <td class="unknown" align="center">Unknown</td> </tr> <tr id="1464"> <td><a href="https://cplusplus.github.io/CWG/issues/1464.html">1464</a></td> @@ -11179,7 +11179,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <tr class="open" id="1628"> <td><a href="https://cplusplus.github.io/CWG/issues/1628.html">1628</a></td> <td>[<a href="https://wg21.link/expr.new">expr.new</a>]</td> - <td>open</td> + <td>review</td> <td>Deallocation function templates</td> <td align="center">Not resolved</td> </tr> @@ -13255,7 +13255,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <tr class="open" id="1924"> <td><a href="https://cplusplus.github.io/CWG/issues/1924.html">1924</a></td> <td>[<a href="https://wg21.link/lex.literal">lex.literal</a>]</td> - <td>review</td> + <td>open</td> <td>Definition of “literal” and kinds of literals</td> <td align="center">Not resolved</td> </tr> @@ -20908,7 +20908,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td>[<a href="https://wg21.link/cpp.embed.gen">cpp.embed.gen</a>]</td> <td>CD7</td> <td>Disallowing macros for <TT>#embed</TT> parameters</td> - <td class="unknown" align="center">Unknown</td> + <td class="unreleased" align="center">Clang 24</td> </tr> <tr id="3014"> <td><a href="https://cplusplus.github.io/CWG/issues/3014.html">3014</a></td> @@ -20969,7 +20969,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <tr class="open" id="3022"> <td><a href="https://cplusplus.github.io/CWG/issues/3022.html">3022</a></td> <td>[<a href="https://wg21.link/class.dtor">class.dtor</a>]</td> - <td>review</td> + <td>tentatively ready</td> <td>Redundant specification of explicit destructor calls</td> <td align="center">Not resolved</td> </tr> @@ -22194,7 +22194,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <tr class="open" id="3197"> <td><a href="https://cplusplus.github.io/CWG/issues/3197.html">3197</a></td> <td>[<a href="https://wg21.link/diff.basic">diff.basic</a>]</td> - <td>review</td> + <td>tentatively ready</td> <td>Relaxed requirements for integer representations</td> <td align="center">Not resolved</td> </tr> @@ -22271,7 +22271,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <tr class="open" id="3208"> <td><a href="https://cplusplus.github.io/CWG/issues/3208.html">3208</a></td> <td>[<a href="https://wg21.link/basic.life">basic.life</a>]</td> - <td>open</td> + <td>tentatively ready</td> <td>Base classes of virtual base classes</td> <td align="center">Not resolved</td> </tr> @@ -22285,42 +22285,42 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <tr class="open" id="3210"> <td><a href="https://cplusplus.github.io/CWG/issues/3210.html">3210</a></td> <td>[<a href="https://wg21.link/stmt.expand">stmt.expand</a>]</td> - <td>open</td> + <td>tentatively ready</td> <td>constexpr for empty destructuring expansion statements</td> <td align="center">Not resolved</td> </tr> <tr class="open" id="3211"> <td><a href="https://cplusplus.github.io/CWG/issues/3211.html">3211</a></td> <td>[<a href="https://wg21.link/basic.def.odr">basic.def.odr</a>]</td> - <td>open</td> + <td>tentatively ready</td> <td>Explicitly captured variable is not odr-usable in lambda contract</td> <td align="center">Not resolved</td> </tr> <tr class="open" id="3212"> <td><a href="https://cplusplus.github.io/CWG/issues/3212.html">3212</a></td> <td>[<a href="https://wg21.link/stmt.if">stmt.if</a>]</td> - <td>open</td> + <td>drafting</td> <td>Misleading disambiguation rule for nested <TT>if</TT></td> <td align="center">Not resolved</td> </tr> <tr class="open" id="3213"> <td><a href="https://cplusplus.github.io/CWG/issues/3213.html">3213</a></td> <td>[<a href="https://wg21.link/temp.param">temp.param</a>]</td> - <td>open</td> + <td>tentatively ready</td> <td>Restrictions on the <I>template-head</I> of a concept definition</td> <td align="center">Not resolved</td> </tr> <tr class="open" id="3214"> <td><a href="https://cplusplus.github.io/CWG/issues/3214.html">3214</a></td> <td>[<a href="https://wg21.link/basic.link">basic.link</a>]</td> - <td>open</td> + <td>tentatively ready</td> <td>Redeclaration of types and namespaces and their aliases</td> <td align="center">Not resolved</td> </tr> <tr class="open" id="3215"> <td><a href="https://cplusplus.github.io/CWG/issues/3215.html">3215</a></td> <td>[<a href="https://wg21.link/expr.const.core">expr.const.core</a>]</td> - <td>open</td> + <td>tentatively ready</td> <td><TT>this</TT> in a default member initializer during constant evaluation</td> <td align="center">Not resolved</td> </tr> @@ -22341,7 +22341,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <tr class="open" id="3218"> <td><a href="https://cplusplus.github.io/CWG/issues/3218.html">3218</a></td> <td>[<a href="https://wg21.link/temp.variadic">temp.variadic</a>]</td> - <td>open</td> + <td>tentatively ready</td> <td>Expanding packs created within a pack expansion</td> <td align="center">Not resolved</td> </tr> @@ -22351,6 +22351,90 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td>open</td> <td>Acquiring value representations and indeterminate or erroneous values</td> <td align="center">Not resolved</td> + </tr> + <tr class="open" id="3220"> + <td><a href="https://cplusplus.github.io/CWG/issues/3220.html">3220</a></td> + <td>[<a href="https://wg21.link/basic.link">basic.link</a>]</td> + <td>open</td> + <td>Regression in module attachment rules introduced by CWG3171</td> + <td align="center">Not resolved</td> + </tr> + <tr class="open" id="3221"> + <td><a href="https://cplusplus.github.io/CWG/issues/3221.html">3221</a></td> + <td>[<a href="https://wg21.link/basic.scope.block">basic.scope.block</a>]</td> + <td>tentatively ready</td> + <td>Missing Annex C entry for conflicting declarations in for-loops</td> + <td align="center">Not resolved</td> + </tr> + <tr class="open" id="3222"> + <td><a href="https://cplusplus.github.io/CWG/issues/3222.html">3222</a></td> + <td>[<a href="https://wg21.link/cpp.module">cpp.module</a>]</td> + <td>tentatively ready</td> + <td>Deleted module directives</td> + <td align="center">Not resolved</td> + </tr> + <tr class="open" id="3223"> + <td><a href="https://cplusplus.github.io/CWG/issues/3223.html">3223</a></td> + <td>[<a href="https://wg21.link/class.base.init">class.base.init</a>]</td> + <td>tentatively ready</td> + <td>Undefined behavior for constructor preconditions and destructor postconditions</td> + <td align="center">Not resolved</td> + </tr> + <tr class="open" id="3224"> + <td><a href="https://cplusplus.github.io/CWG/issues/3224.html">3224</a></td> + <td>[<a href="https://wg21.link/cpp.replace.general">cpp.replace.general</a>]</td> + <td>tentatively ready</td> + <td>Directives in multi-line macro arguments</td> + <td align="center">Not resolved</td> + </tr> + <tr class="open" id="3225"> + <td><a href="https://cplusplus.github.io/CWG/issues/3225.html">3225</a></td> + <td>[<a href="https://wg21.link/conv.integral">conv.integral</a>]</td> + <td>tentatively ready</td> + <td>Conversion of <TT>bool</TT> to signed integer of width 1</td> + <td align="center">Not resolved</td> + </tr> + <tr class="open" id="3226"> + <td><a href="https://cplusplus.github.io/CWG/issues/3226.html">3226</a></td> + <td>[<a href="https://wg21.link/temp.res.general">temp.res.general</a>]</td> + <td>tentatively ready</td> + <td>Conflict of templated entity vs. enclosing template</td> + <td align="center">Not resolved</td> + </tr> + <tr class="open" id="3227"> + <td><a href="https://cplusplus.github.io/CWG/issues/3227.html">3227</a></td> + <td>[<a href="https://wg21.link/temp.res.general">temp.res.general</a>]</td> + <td>tentatively ready</td> + <td>IFNDR for always-empty packs</td> + <td align="center">Not resolved</td> + </tr> + <tr class="open" id="3228"> + <td><a href="https://cplusplus.github.io/CWG/issues/3228.html">3228</a></td> + <td>[<a href="https://wg21.link/dcl.init">dcl.init</a>]</td> + <td>tentatively ready</td> + <td>Empty initializers vs. empty packs</td> + <td align="center">Not resolved</td> + </tr> + <tr class="open" id="3229"> + <td><a href="https://cplusplus.github.io/CWG/issues/3229.html">3229</a></td> + <td>[<a href="https://wg21.link/basic.def.odr">basic.def.odr</a>]</td> + <td>tentatively ready</td> + <td>Incomplete restrictions on same meaning for same tokens</td> + <td align="center">Not resolved</td> + </tr> + <tr class="open" id="3230"> + <td><a href="https://cplusplus.github.io/CWG/issues/3230.html">3230</a></td> + <td>[<a href="https://wg21.link/basic.pre">basic.pre</a>]</td> + <td>open</td> + <td>Are non-static data members "variables"?</td> + <td align="center">Not resolved</td> + </tr> + <tr class="open" id="3231"> + <td><a href="https://cplusplus.github.io/CWG/issues/3231.html">3231</a></td> + <td>[<a href="https://wg21.link/temp.concept">temp.concept</a>]</td> + <td>open</td> + <td>Default template argument for the prototype parameter of a concept</td> + <td align="center">Not resolved</td> </tr></table> </div> >From 0fd92492049832121df4989c3095b1cab063cc3d Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Mon, 21 Sep 2026 20:46:01 -0700 Subject: [PATCH 05/12] delete duplicate point in release notes --- clang/docs/ReleaseNotes.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index da925b260ee1c1..dc5c765cb84186 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -201,11 +201,6 @@ features cannot lower the translation-unit ABI level; them to an enumeration type with a fixed `bool` underlying type. This resolves [CWG1094](https://wg21.link/cwg1094). -- Clang now diagnoses an error if an `#embed` directive or `__has_embed` - statement uses a parameter name (i.e. `limit`, `prefix`, `suffix`, `if_empty`) - that has previously been defined as a macro. This resolves - [CWG3013](https://wg21.link/cwg3013), which marks such code as ill-formed. - ### C Language Changes #### C2y Feature Support >From cf667c5993041b9d77ff557fb998588e16aedd3c Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Mon, 21 Sep 2026 22:02:30 -0700 Subject: [PATCH 06/12] ate logo o pato --- clang/test/CXX/drs/inputs/media/art.txt | 13 ------------- clang/test/CXX/drs/inputs/media/empty | 0 2 files changed, 13 deletions(-) delete mode 100644 clang/test/CXX/drs/inputs/media/art.txt delete mode 100644 clang/test/CXX/drs/inputs/media/empty diff --git a/clang/test/CXX/drs/inputs/media/art.txt b/clang/test/CXX/drs/inputs/media/art.txt deleted file mode 100644 index f4536f39af349d..00000000000000 --- a/clang/test/CXX/drs/inputs/media/art.txt +++ /dev/null @@ -1,13 +0,0 @@ - - ------------------------------------------- - . . - . _ . - . _ _ >(. ) _ . - . >(. )__ >(- )__ //___ >(. )__ . - . ~(____/ -~(_(=-/-~~(_(__/-~~(____/~ . - . ~. -~~~ . -~. ~~- . - . ~- . - . . - ------------------------------------------- - - O Pato \ No newline at end of file diff --git a/clang/test/CXX/drs/inputs/media/empty b/clang/test/CXX/drs/inputs/media/empty deleted file mode 100644 index e69de29bb2d1d6..00000000000000 >From b2986ddf69c821872eee12aac2301164686f7cc4 Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Mon, 21 Sep 2026 22:02:54 -0700 Subject: [PATCH 07/12] use ExtWarn for warn_c_pp_embed_parameter_is_macro --- clang/include/clang/Basic/DiagnosticLexKinds.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td index fbe9fc1461f09d..fdb9ffba01613b 100644 --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -495,7 +495,7 @@ def err_pp_embed_dup_params : Error< def err_pp_embed_parameter_is_macro : Error< "cannot use %0 as %select{an '#embed'|a '__has_embed'}1 parameter if also" " defined as a macro">; -def warn_c_pp_embed_parameter_is_macro : Warning< +def warn_c_pp_embed_parameter_is_macro : ExtWarn< "%0 is defined as a macro and gets expanded when used as " "%select{an '#embed'|a '__has_embed'}1 parameter in C; this is " "ill-formed in C++">, >From ea6b88cefbfc58af8e8797e33e59a048f59804eb Mon Sep 17 00:00:00 2001 From: Ian Li <[email protected]> Date: Tue, 22 Sep 2026 01:11:50 -0400 Subject: [PATCH 08/12] Apply suggestion from @Fznamznon Co-authored-by: Mariya Podchishchaeva <[email protected]> --- clang/lib/Lex/PPDirectives.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 0b7c727d2ce890..bcf6a554b77f61 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -3771,8 +3771,7 @@ void Preprocessor::HandleElifFamilyDirective(Token &ElifToken, std::optional<LexEmbedParametersResult> Preprocessor::LexEmbedParameters(Token &CurTok, bool ForHasEmbed) { LexEmbedParametersResult Result{}; - if (ForHasEmbed) - assert(isParsingIfOrElifDirective() && + assert(!ForHasEmbed || isParsingIfOrElifDirective() && "__has_embed outside of #if or #elif directive?"); llvm::SaveAndRestore InEmbedParams(ParsingEmbedParameters, true); tok::TokenKind EndTokenKind = ForHasEmbed ? tok::r_paren : tok::eod; >From d371eae8b8dc38cfa145cca04bf2930c2dd61bc8 Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Mon, 21 Sep 2026 22:18:39 -0700 Subject: [PATCH 09/12] clang-format --- clang/lib/Lex/PPDirectives.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index bcf6a554b77f61..35697284e682b7 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -3771,8 +3771,8 @@ void Preprocessor::HandleElifFamilyDirective(Token &ElifToken, std::optional<LexEmbedParametersResult> Preprocessor::LexEmbedParameters(Token &CurTok, bool ForHasEmbed) { LexEmbedParametersResult Result{}; - assert(!ForHasEmbed || isParsingIfOrElifDirective() && - "__has_embed outside of #if or #elif directive?"); + assert(!ForHasEmbed || isParsingIfOrElifDirective() && + "__has_embed outside of #if or #elif directive?"); llvm::SaveAndRestore InEmbedParams(ParsingEmbedParameters, true); tok::TokenKind EndTokenKind = ForHasEmbed ? tok::r_paren : tok::eod; >From b4890b385f909cbd0b8536ac5b119556597fd795 Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Tue, 22 Sep 2026 13:36:39 -0700 Subject: [PATCH 10/12] don't hardocde embed params in preprocessor.cpp --- clang/include/clang/Lex/PPEmbedParameters.h | 5 +++++ clang/lib/Lex/Preprocessor.cpp | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Lex/PPEmbedParameters.h b/clang/include/clang/Lex/PPEmbedParameters.h index 41a69664df3667..478780dea2eed2 100644 --- a/clang/include/clang/Lex/PPEmbedParameters.h +++ b/clang/include/clang/Lex/PPEmbedParameters.h @@ -19,6 +19,11 @@ namespace clang { +/// List of identifier names that match to embed parameters. +inline constexpr StringRef PPEmbedParameterIdentNames[] = { + "clang::offset", "limit", "prefix", "suffix", "if_empty" +}; + /// Preprocessor extension embed parameter "clang::offset" /// `clang::offset( constant-expression )` class PPEmbedParameterOffset : public PPDirectiveParameter { diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index 9bab63818007c7..c5f36c7c531d2e 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -881,8 +881,7 @@ void Preprocessor::updateOutOfDateIdentifier(const IdentifierInfo &II) const { } static bool isProtectedEmbedParameterName(const IdentifierInfo *II) { - return II->isStr("limit") || II->isStr("prefix") || II->isStr("suffix") || - II->isStr("if_empty"); + return llvm::is_contained(PPEmbedParameterIdentNames, II->getName()); } /// HandleIdentifier - This callback is invoked when the lexer reads an >From 51e846226b7a1199f59599f2839d5653e3656d12 Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Tue, 22 Sep 2026 16:36:31 -0700 Subject: [PATCH 11/12] add additional preprocessor macro tests to ensure prepreprocessor macros work as intended --- clang/test/Preprocessor/embed_weird.cpp | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/clang/test/Preprocessor/embed_weird.cpp b/clang/test/Preprocessor/embed_weird.cpp index e44aff55c59e22..163cc29d5e8285 100644 --- a/clang/test/Preprocessor/embed_weird.cpp +++ b/clang/test/Preprocessor/embed_weird.cpp @@ -93,16 +93,42 @@ const unsigned char *null_ptr_3 = { #embed <null_byte.bin> }; +// Test macro expansions: #define FILE_NAME <null_byte.bin> #define LIMIT 1 #define OFFSET 0 #define EMPTY_SUFFIX suffix() +#define VALUE 7 +#define SUFFIX_TOKENS ,VALUE constexpr unsigned char ch = #embed FILE_NAME limit(LIMIT) clang::offset(OFFSET) EMPTY_SUFFIX ; static_assert(ch == 0); +const int nums1[] = { +#embed "numbers.txt" limit(LIMIT) prefix(VALUE,) suffix(SUFFIX_TOKENS) +}; +static_assert(sizeof(nums1) / sizeof(int) == LIMIT + 2); + +constexpr int empty_val = +#embed "numbers.txt" limit(0) if_empty(VALUE) +; +static_assert(empty_val == VALUE); + +#define PARAM_LIST limit(VALUE) prefix(8,) suffix(,9) +#define PARAM_ALIAS if_empty + +const int nums2[] = { +#embed "numbers.txt" PARAM_LIST +}; +static_assert(sizeof(nums2) / sizeof(int) == VALUE + 2); + +constexpr int only_prefix = +#embed "numbers.txt" limit(0) PARAM_ALIAS(7) +; +static_assert(only_prefix == 7); + void foobar(float x, char y, char z); void g1() { foobar((float) #embed "numbers.txt" limit(3) >From 72d55925e5d72317c6b5ca7b54afda635dcb8171 Mon Sep 17 00:00:00 2001 From: "Li, Ian" <[email protected]> Date: Tue, 22 Sep 2026 16:43:43 -0700 Subject: [PATCH 12/12] clang-format --- clang/include/clang/Lex/PPEmbedParameters.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Lex/PPEmbedParameters.h b/clang/include/clang/Lex/PPEmbedParameters.h index 478780dea2eed2..3eaadf4cf147bc 100644 --- a/clang/include/clang/Lex/PPEmbedParameters.h +++ b/clang/include/clang/Lex/PPEmbedParameters.h @@ -19,10 +19,9 @@ namespace clang { -/// List of identifier names that match to embed parameters. +/// List of identifier names that match to embed parameters. inline constexpr StringRef PPEmbedParameterIdentNames[] = { - "clang::offset", "limit", "prefix", "suffix", "if_empty" -}; + "clang::offset", "limit", "prefix", "suffix", "if_empty"}; /// Preprocessor extension embed parameter "clang::offset" /// `clang::offset( constant-expression )` _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
