https://github.com/nehaGautam07 created
https://github.com/llvm/llvm-project/pull/220259
…#183473)
This came up in #183473. Clang was accepting things like:
[[ X1 ( ] ) ]] ;
That's not valid. The argument clause has to be a balanced-token-seq, and
there's a stray `]` in there. GCC errors; we only warned that `X1` is an
unknown attribute and carried on.
The reason is that for attributes we don't recognize, we don't try to parse
the arguments (they might not even be C++ expressions). We just skip to the
closing `)`. `SkipUntil` is too forgiving here: if the first token is an
unmatched `]` or `}`, it gets eaten and we never diagnose it.
I added a small helper that walks the argument tokens and checks that `()`,
`[]`, and `{}` actually nest. If they don't, we now error. We still skip
the contents instead of parsing them, so unknown vendor attributes with
well-formed arguments behave as before.
Test covers `[[X1(])]]` / `[[X1(})]]` (error) and `[[X1]]` / `[[X1()]]`
(warning only).
Fixes #183473
>From 6a3dd0b60437967fdff43af53a6019312c1c2e6d Mon Sep 17 00:00:00 2001
From: neharaj <[email protected]>
Date: Tue, 1 Sep 2026 14:14:18 +0000
Subject: [PATCH] [Clang][Parser] Reject unbalanced unknown attribute arguments
(Fixes #183473)
---
clang/include/clang/Parse/Parser.h | 2 +-
clang/lib/Parse/ParseDeclCXX.cpp | 40 ++++++++++++++++++-
.../Parser/cxx11-unbalanced-attr-args.cpp | 6 +++
3 files changed, 46 insertions(+), 2 deletions(-)
create mode 100644 clang/test/Parser/cxx11-unbalanced-attr-args.cpp
diff --git a/clang/include/clang/Parse/Parser.h
b/clang/include/clang/Parse/Parser.h
index ae91153e34e3a..c69cb71e9988e 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3078,7 +3078,7 @@ class Parser : public CodeCompletionHandler {
/// attribute-specifier-seq[opt] attribute-specifier
/// \endverbatim
void ParseCXX11Attributes(ParsedAttributes &attrs);
-
+ bool SkipBalancedAttributeArgs(tok::TokenKind Closer);
/// ParseCXX11AttributeArgs -- Parse a C++11 attribute-argument-clause.
/// Parses a C++11 (or C23)-style attribute argument list. Returns true
/// if this results in adding an attribute to the ParsedAttributes list.
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index d701cbaa43bdd..00bf283cffd7e 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -4534,7 +4534,43 @@ bool Parser::ParseCXXAssumeAttributeArg(
return false;
}
+bool Parser::SkipBalancedAttributeArgs(tok::TokenKind Closer) {
+ while (true) {
+ if (Tok.is(Closer))
+ return true;
+ if (Tok.is(tok::eof))
+ return false;
+ switch (Tok.getKind()) {
+ case tok::l_paren:
+ ConsumeParen();
+ if (!SkipBalancedAttributeArgs(tok::r_paren) ||
+ ExpectAndConsume(tok::r_paren))
+ return false;
+ break;
+ case tok::l_square:
+ ConsumeBracket();
+ if (!SkipBalancedAttributeArgs(tok::r_square) ||
+ ExpectAndConsume(tok::r_square))
+ return false;
+ break;
+ case tok::l_brace:
+ ConsumeBrace();
+ if (!SkipBalancedAttributeArgs(tok::r_brace) ||
+ ExpectAndConsume(tok::r_brace))
+ return false;
+ break;
+ case tok::r_paren:
+ case tok::r_square:
+ case tok::r_brace:
+ Diag(Tok, diag::err_expected) << Closer;
+ return false;
+ default:
+ ConsumeAnyToken();
+ break;
+ }
+ }
+}
bool Parser::ParseCXX11AttributeArgs(
IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
@@ -4581,7 +4617,9 @@ bool Parser::ParseCXX11AttributeArgs(
ScopeName, AttrName, getTargetInfo(), getLangOpts())) {
// Eat the left paren, then skip to the ending right paren.
ConsumeParen();
- SkipUntil(tok::r_paren);
+ if (!SkipBalancedAttributeArgs(tok::r_paren) ||
+ ExpectAndConsume(tok::r_paren))
+ SkipUntil(tok::r_paren, StopAtSemi);
return false;
}
diff --git a/clang/test/Parser/cxx11-unbalanced-attr-args.cpp
b/clang/test/Parser/cxx11-unbalanced-attr-args.cpp
new file mode 100644
index 0000000000000..ca5cbb76eba7d
--- /dev/null
+++ b/clang/test/Parser/cxx11-unbalanced-attr-args.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+[[X1(])]]; // expected-error {{expected ')'}} expected-warning {{unknown
attribute 'X1' ignored}}
+[[X1(})]]; // expected-error {{expected ')'}} expected-warning {{unknown
attribute 'X1' ignored}}
+[[X1]]; // expected-warning {{unknown attribute 'X1' ignored}}
+[[X1()]]; // expected-warning {{unknown attribute 'X1' ignored}}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits