https://github.com/s-barannikov updated https://github.com/llvm/llvm-project/pull/171017
>From e8d8e8a2fcaf17ce95471012b2451eef78e22df5 Mon Sep 17 00:00:00 2001 From: Sergei Barannikov <[email protected]> Date: Sun, 7 Dec 2025 10:16:19 +0300 Subject: [PATCH 1/4] precommit test --- clang/test/Sema/attr-modular-format.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clang/test/Sema/attr-modular-format.c b/clang/test/Sema/attr-modular-format.c index fc5b28b0b88be..1a22de115a315 100644 --- a/clang/test/Sema/attr-modular-format.c +++ b/clang/test/Sema/attr-modular-format.c @@ -3,6 +3,10 @@ int printf(const char *fmt, ...) __attribute__((modular_format(__modular_printf, "__printf", "float"))); // no-error int myprintf(const char *fmt, ...) __attribute__((modular_format(__modular_printf, "__printf", "float"))); // expected-error {{'modular_format' attribute requires 'format' attribute}} +int lprintf(const char *fmt, ...) __attribute__((modular_format(__modular_printf, L"__printf", L"float"), format(printf, 1, 2))); +// expected-error@-1 {{'modular_format' attribute requires a string}} +// expected-warning@-2 {{encoding prefix 'L' on an unevaluated string literal has no effect}} + int dupe(const char *fmt, ...) __attribute__((modular_format(__modular_printf, "__printf", "float", "int", "float"), format(printf, 1, 2))); // expected-error {{duplicate aspect 'float' in 'modular_format' attribute}} int multi_dupe(const char *fmt, ...) __attribute__((modular_format(__modular_printf, "__printf", "float", "int", "float", "int"), format(printf, 1, 2))); // expected-error {{duplicate aspect 'float' in 'modular_format' attribute}} \ // expected-error {{duplicate aspect 'int' in 'modular_format' attribute}} >From 14aa9063d863ec895b9e34ffb98c9f474c8a6fee Mon Sep 17 00:00:00 2001 From: Sergei Barannikov <[email protected]> Date: Sun, 7 Dec 2025 10:49:17 +0300 Subject: [PATCH 2/4] [clang] Fix string literal parsing on some attributes At the time ParseAttributeArgumentList is called, the first argument of an attribute may have already been parsed. We need to take this into account when accessing ParsedAttributeArgumentsProperties mask, which specifies which of the attribute arguments are string literals. --- clang/include/clang/Parse/Parser.h | 7 +++---- clang/lib/Parse/ParseDecl.cpp | 8 ++++---- clang/test/Sema/attr-modular-format.c | 3 +-- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index e03d7994e2fa5..373d496f19cd1 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2117,10 +2117,9 @@ class Parser : public CodeCompletionHandler { ExprResult ParseUnevaluatedStringInAttribute(const IdentifierInfo &AttrName); - bool - ParseAttributeArgumentList(const clang::IdentifierInfo &AttrName, - SmallVectorImpl<Expr *> &Exprs, - ParsedAttributeArgumentsProperties ArgsProperties); + bool parseAttributeArgumentList( + const IdentifierInfo &AttrName, SmallVectorImpl<Expr *> &Exprs, + ParsedAttributeArgumentsProperties ArgsProperties, unsigned Arg); /// Parses syntax-generic attribute arguments for attributes which are /// known to the implementation, and adds them to the given ParsedAttributes diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 8688ccf41acb5..26a1f7c0a5b93 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -421,11 +421,10 @@ Parser::ParseUnevaluatedStringInAttribute(const IdentifierInfo &AttrName) { return ParseUnevaluatedStringLiteralExpression(); } -bool Parser::ParseAttributeArgumentList( +bool Parser::parseAttributeArgumentList( const IdentifierInfo &AttrName, SmallVectorImpl<Expr *> &Exprs, - ParsedAttributeArgumentsProperties ArgsProperties) { + ParsedAttributeArgumentsProperties ArgsProperties, unsigned Arg) { bool SawError = false; - unsigned Arg = 0; while (true) { ExprResult Expr; if (ArgsProperties.isStringLiteralArg(Arg)) { @@ -580,7 +579,8 @@ unsigned Parser::ParseAttributeArgsCommon( ParsedAttributeArgumentsProperties ArgProperties = attributeStringLiteralListArg(getTargetInfo().getTriple(), *AttrName, Form.getSyntax(), ScopeName); - if (ParseAttributeArgumentList(*AttrName, ParsedExprs, ArgProperties)) { + if (parseAttributeArgumentList(*AttrName, ParsedExprs, ArgProperties, + ArgExprs.size())) { SkipUntil(tok::r_paren, StopAtSemi); return 0; } diff --git a/clang/test/Sema/attr-modular-format.c b/clang/test/Sema/attr-modular-format.c index 1a22de115a315..b7ae519cedbeb 100644 --- a/clang/test/Sema/attr-modular-format.c +++ b/clang/test/Sema/attr-modular-format.c @@ -4,8 +4,7 @@ int printf(const char *fmt, ...) __attribute__((modular_format(__modular_printf int myprintf(const char *fmt, ...) __attribute__((modular_format(__modular_printf, "__printf", "float"))); // expected-error {{'modular_format' attribute requires 'format' attribute}} int lprintf(const char *fmt, ...) __attribute__((modular_format(__modular_printf, L"__printf", L"float"), format(printf, 1, 2))); -// expected-error@-1 {{'modular_format' attribute requires a string}} -// expected-warning@-2 {{encoding prefix 'L' on an unevaluated string literal has no effect}} +// expected-warning@-1 2{{encoding prefix 'L' on an unevaluated string literal has no effect}} int dupe(const char *fmt, ...) __attribute__((modular_format(__modular_printf, "__printf", "float", "int", "float"), format(printf, 1, 2))); // expected-error {{duplicate aspect 'float' in 'modular_format' attribute}} int multi_dupe(const char *fmt, ...) __attribute__((modular_format(__modular_printf, "__printf", "float", "int", "float", "int"), format(printf, 1, 2))); // expected-error {{duplicate aspect 'float' in 'modular_format' attribute}} \ >From b66e563a98a83ed18837f35c23608f9e5d045760 Mon Sep 17 00:00:00 2001 From: Sergei Barannikov <[email protected]> Date: Tue, 6 Jan 2026 22:42:55 +0300 Subject: [PATCH 3/4] Revert naming change --- clang/include/clang/Parse/Parser.h | 2 +- clang/lib/Parse/ParseDecl.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 373d496f19cd1..a660ea91d9236 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2117,7 +2117,7 @@ class Parser : public CodeCompletionHandler { ExprResult ParseUnevaluatedStringInAttribute(const IdentifierInfo &AttrName); - bool parseAttributeArgumentList( + bool ParseAttributeArgumentList( const IdentifierInfo &AttrName, SmallVectorImpl<Expr *> &Exprs, ParsedAttributeArgumentsProperties ArgsProperties, unsigned Arg); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 26a1f7c0a5b93..0421cad5f980e 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -421,7 +421,7 @@ Parser::ParseUnevaluatedStringInAttribute(const IdentifierInfo &AttrName) { return ParseUnevaluatedStringLiteralExpression(); } -bool Parser::parseAttributeArgumentList( +bool Parser::ParseAttributeArgumentList( const IdentifierInfo &AttrName, SmallVectorImpl<Expr *> &Exprs, ParsedAttributeArgumentsProperties ArgsProperties, unsigned Arg) { bool SawError = false; @@ -579,7 +579,7 @@ unsigned Parser::ParseAttributeArgsCommon( ParsedAttributeArgumentsProperties ArgProperties = attributeStringLiteralListArg(getTargetInfo().getTriple(), *AttrName, Form.getSyntax(), ScopeName); - if (parseAttributeArgumentList(*AttrName, ParsedExprs, ArgProperties, + if (ParseAttributeArgumentList(*AttrName, ParsedExprs, ArgProperties, ArgExprs.size())) { SkipUntil(tok::r_paren, StopAtSemi); return 0; >From c4aef57ed4b46a43c912b2d37d78883c44933a2c Mon Sep 17 00:00:00 2001 From: Sergei Barannikov <[email protected]> Date: Tue, 6 Jan 2026 22:54:33 +0300 Subject: [PATCH 4/4] Document the function --- clang/include/clang/Parse/Parser.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index a660ea91d9236..d59e496ac7064 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2117,6 +2117,11 @@ class Parser : public CodeCompletionHandler { ExprResult ParseUnevaluatedStringInAttribute(const IdentifierInfo &AttrName); + /// Parses a comma-delimited list of arguments of an attribute \p AttrName, + /// filling \p Exprs. \p ArgsProperties specifies which of the arguments + /// should be parsed as unevaluated string literals. \p Arg is the number + /// of arguments parsed before calling / this function (the index of the + /// argument to be parsed next). bool ParseAttributeArgumentList( const IdentifierInfo &AttrName, SmallVectorImpl<Expr *> &Exprs, ParsedAttributeArgumentsProperties ArgsProperties, unsigned Arg); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
