https://github.com/ChenMiaoi created
https://github.com/llvm/llvm-project/pull/228990
A nested `_Pragma` can produce an `annot_pragma_attribute` token during
preprocessing. After diagnosing invalid attribute syntax,
`HandlePragmaAttribute` calls `getIdentifierInfo()` to generate a fix-it
without checking whether the current token is an annotation.
`getAttributeSubjectRulesRecoveryPointForToken`, which handles recovery for
attribute subject rules, has the same problem.
For example, this input enters the attribute syntax error path:
```c
#pragma clang attribute (_Pragma("clang attribute push"))
```
In the following input, the attribute itself is valid, but a nested `_Pragma`
appears where `apply_to` is expected, entering the attribute subject rule
recovery path:
```c
#pragma clang attribute push(__attribute__((annotate("test"))), _Pragma("clang
attribute push"))
```
Before this change, both inputs fail in assertion-enabled builds with:
```text
Assertion `!isAnnotation() && "getIdentifierInfo() on an annotation token!"'
failed.
```
Check for annotation tokens before querying identifier information in
`HandlePragmaAttribute`. Return `None` for annotation tokens in
`getAttributeSubjectRulesRecoveryPointForToken` so that the existing error
recovery logic can handle them.
The two inputs now produce the following diagnostics, respectively:
```text
error: expected an attribute that is specified using the GNU, C++11 or
'__declspec' syntax
error: expected attribute subject set specifier 'apply_to'
```
Fixes #225035
>From 774f0176cad0716b4990f1c7290813e876735fa8 Mon Sep 17 00:00:00 2001
From: Chen Miao <[email protected]>
Date: Mon, 5 Oct 2026 15:12:50 +0800
Subject: [PATCH] [clang] Fix pragma attribute crashes caused by nested _Pragma
A nested `_Pragma` can produce an `annot_pragma_attribute` token during
preprocessing. After diagnosing invalid attribute syntax,
`HandlePragmaAttribute` calls `getIdentifierInfo()` to generate a fix-it
without checking whether the current token is an annotation.
`getAttributeSubjectRulesRecoveryPointForToken`, which handles recovery
for attribute subject rules, has the same problem.
For example, this input enters the attribute syntax error path:
```c
#pragma clang attribute (_Pragma("clang attribute push"))
```
In the following input, the attribute itself is valid, but a nested
`_Pragma` appears where `apply_to` is expected, entering the attribute
subject rule recovery path:
```c
#pragma clang attribute push(__attribute__((annotate("test"))), _Pragma("clang
attribute push"))
```
Before this change, both inputs fail in assertion-enabled builds with:
```text
Assertion `!isAnnotation() && "getIdentifierInfo() on an annotation token!"'
failed.
```
Check for annotation tokens before querying identifier information in
`HandlePragmaAttribute`. Return `None` for annotation tokens in
`getAttributeSubjectRulesRecoveryPointForToken` so that the existing
error recovery logic can handle them.
The two inputs now produce the following diagnostics, respectively:
```text
error: expected an attribute that is specified using the GNU, C++11 or
'__declspec' syntax
error: expected attribute subject set specifier 'apply_to'
```
Fixes #225035
---
clang/lib/Parse/ParsePragma.cpp | 8 +++++++-
clang/test/Parser/pragma-attribute.cpp | 7 +++++++
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index f58d2c70b7d98..34a9ed09fec8e 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -1870,6 +1870,10 @@ enum class MissingAttributeSubjectRulesRecoveryPoint {
MissingAttributeSubjectRulesRecoveryPoint
getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
+ // Nested `_Pragma` annotations cannot name attribute subject rules.
+ // https://github.com/llvm/llvm-project/issues/225035
+ if (Tok.isAnnotation())
+ return MissingAttributeSubjectRulesRecoveryPoint::None;
if (const auto *II = Tok.getIdentifierInfo()) {
if (II->isStr("apply_to"))
return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
@@ -2038,7 +2042,9 @@ void Parser::HandlePragmaAttribute() {
ParseMicrosoftDeclSpecs(Attrs);
} else {
Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
- if (Tok.getIdentifierInfo()) {
+ // A nested `_Pragma` can produce an annotation token here.
+ // https://github.com/llvm/llvm-project/issues/225035
+ if (!Tok.isAnnotation() && Tok.getIdentifierInfo()) {
// If we suspect that this is an attribute suggest the use of
// '__attribute__'.
if (ParsedAttr::getParsedKind(
diff --git a/clang/test/Parser/pragma-attribute.cpp
b/clang/test/Parser/pragma-attribute.cpp
index 1f90a8990bb96..78699c06262cd 100644
--- a/clang/test/Parser/pragma-attribute.cpp
+++ b/clang/test/Parser/pragma-attribute.cpp
@@ -180,6 +180,13 @@ _Pragma("clang attribute pop");
#pragma clang attribute push (annotate("test")) // expected-error {{expected
an attribute that is specified using the GNU, C++11 or '__declspec' syntax}}
// expected-note@-1 {{use the GNU '__attribute__' syntax}}
+// Nested pragmas must be diagnosed without crashing (GH225035).
+#pragma clang attribute (_Pragma("clang attribute push")) // expected-error
{{expected an attribute that is specified using the GNU, C++11 or '__declspec'
syntax}}
+#pragma clang attribute push (_Pragma("clang attribute push")) //
expected-error {{expected an attribute that is specified using the GNU, C++11
or '__declspec' syntax}}
+#pragma clang attribute push(__attribute__((annotate("test"))) _Pragma("clang
attribute push")) // expected-error {{expected ','}}
+#pragma clang attribute push(__attribute__((annotate("test"))), _Pragma("clang
attribute push")) // expected-error {{expected attribute subject set specifier
'apply_to'}}
+#pragma clang attribute push(__attribute__((annotate("test"))), apply_to
_Pragma("clang attribute push")) // expected-error {{expected '='}}
+
#pragma clang attribute push([[clang::uninitialized]], apply_to =
variable(is_local))
#pragma clang attribute pop
#pragma clang attribute push([[clang::uninitialized]], apply_to = function) //
expected-error {{attribute 'clang::uninitialized' cannot be applied to
'function'}}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits