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

Reply via email to