llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Chen Miao (ChenMiaoi)
<details>
<summary>Changes</summary>
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
---
Full diff: https://github.com/llvm/llvm-project/pull/228990.diff
2 Files Affected:
- (modified) clang/lib/Parse/ParsePragma.cpp (+7-1)
- (modified) clang/test/Parser/pragma-attribute.cpp (+7)
``````````diff
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'}}
``````````
</details>
https://github.com/llvm/llvm-project/pull/228990
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits