vsavchenko updated this revision to Diff 320092.
vsavchenko added a comment.
Add check for extension
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D93630/new/
https://reviews.llvm.org/D93630
Files:
clang/include/clang/Basic/Features.def
clang/lib/Parse/ParseStmt.cpp
clang/test/Parser/stmt-attributes.c
clang/test/Parser/stmt-attributes.cpp
clang/test/Parser/stmt-attributes.m
Index: clang/test/Parser/stmt-attributes.m
===================================================================
--- /dev/null
+++ clang/test/Parser/stmt-attributes.m
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 -verify %s \
+// RUN: -fblocks -fobjc-exceptions -fexceptions -fsyntax-only \
+// RUN: -Wno-unused-value -Wno-unused-getter-return-value
+
+#if !__has_extension(statement_attributes_with_gnu_syntax)
+#error "We should have statement attributes with GNU syntax support"
+#endif
+
+@interface Base
+@end
+
+@interface Test : Base
+@property(getter=hasFoobar) int foobar;
+- (void)foo;
+- (void)bar;
+@end
+
+Test *getTest();
+
+@implementation Test
+- (void)foo __attribute__((nomerge)) {
+ // expected-error@-1 {{'nomerge' attribute only applies to functions and statements}}
+}
+
+- (void)bar {
+ __attribute__(()) [self foo];
+ // expected-error@-1 {{missing '[' at start of message send expression}}
+ // expected-error@-2 {{expected ']'}}
+ // expected-error@-3 {{expected identifier or '('}}
+ // expected-note@-4 {{to match this '['}}
+ __attribute__((nomerge)) [self foo];
+ // expected-warning@-1 {{nomerge attribute is ignored because there exists no call expression inside the statement}}
+ __attribute__((nomerge)) [getTest() foo];
+
+ __attribute__(()) ^{};
+ // expected-error@-1 {{expected identifier or '('}}
+ __attribute__((nomerge)) ^{};
+ // expected-warning@-1 {{nomerge attribute is ignored because there exists no call expression inside the statement}}
+ __attribute__((nomerge)) ^{ [self foo]; }();
+
+ __attribute__(()) @try {
+ [self foo];
+ } @finally {
+ }
+
+ __attribute__((nomerge)) @try {
+ [getTest() foo];
+ } @finally {
+ }
+
+ __attribute__((nomerge)) (__bridge void *)self;
+ // expected-warning@-1 {{nomerge attribute is ignored because there exists no call expression inside the statement}}
+
+ __attribute__((nomerge)) self.hasFoobar;
+ // expected-warning@-1 {{nomerge attribute is ignored because there exists no call expression inside the statement}}
+}
+@end
Index: clang/test/Parser/stmt-attributes.cpp
===================================================================
--- /dev/null
+++ clang/test/Parser/stmt-attributes.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s
+
+#if !__has_extension(statement_attributes_with_gnu_syntax)
+#error "We should have statement attributes with GNU syntax support"
+#endif
+
+template <typename T = void>
+class __attribute__((nomerge)) A {
+ // expected-error@-1 {{'nomerge' attribute only applies to functions and statements}}
+};
+
+class B : public A<> {
+public:
+ void bar();
+};
+
+void bar();
+
+void foo(A<> *obj) {
+ __attribute__((nomerge)) static_cast<B *>(obj)->bar();
+ __attribute__((nomerge))[obj]() { static_cast<B *>(obj)->bar(); }
+ ();
+ __attribute__(()) try {
+ bar();
+ } catch (...) {
+ }
+}
Index: clang/test/Parser/stmt-attributes.c
===================================================================
--- /dev/null
+++ clang/test/Parser/stmt-attributes.c
@@ -0,0 +1,90 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#if !__has_extension(statement_attributes_with_gnu_syntax)
+#error "We should have statement attributes with GNU syntax support"
+#endif
+
+void foo(int i) {
+
+ __attribute__((unknown_attribute)); // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
+ __attribute__(()) {}
+ __attribute__(()) if (0) {}
+ __attribute__(()) for (;;);
+ __attribute__(()) do {
+ __attribute__(()) continue;
+ }
+ while (0)
+ ;
+ __attribute__(()) while (0);
+
+ __attribute__(()) switch (i) {
+ __attribute__(()) case 0 :
+ __attribute__(()) default :
+ __attribute__(()) break;
+ }
+
+ __attribute__(()) goto here;
+ __attribute__(()) here :
+
+ __attribute__(()) return;
+
+ __attribute__((noreturn)) {} // expected-error {{'noreturn' attribute cannot be applied to a statement}}
+ __attribute__((noreturn)) if (0) {} // expected-error {{'noreturn' attribute cannot be applied to a statement}}
+ __attribute__((noreturn)) for (;;); // expected-error {{'noreturn' attribute cannot be applied to a statement}}
+ __attribute__((noreturn)) do { // expected-error {{'noreturn' attribute cannot be applied to a statement}}
+ __attribute__((unavailable)) continue; // expected-error {{'unavailable' attribute cannot be applied to a statement}}
+ }
+ while (0)
+ ;
+ __attribute__((unknown_attribute)) while (0); // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
+
+ __attribute__((unused)) switch (i) { // expected-error {{'unused' attribute cannot be applied to a statement}}
+ __attribute__((uuid)) case 0: // expected-warning {{unknown attribute 'uuid' ignored}}
+ __attribute__((visibility)) default: // expected-error {{'visibility' attribute cannot be applied to a statement}}
+ __attribute__((carries_dependency)) break; // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+ }
+
+ __attribute__((fastcall)) goto there; // expected-error {{'fastcall' attribute cannot be applied to a statement}}
+ __attribute__((noinline)) there : // expected-warning {{'noinline' attribute only applies to functions}}
+
+ __attribute__((weakref)) return; // expected-error {{'weakref' attribute only applies to variables and functions}}
+
+ __attribute__((carries_dependency)); // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+ __attribute__((carries_dependency)) {} // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+ __attribute__((carries_dependency)) if (0) {} // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+ __attribute__((carries_dependency)) for (;;); // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+ __attribute__((carries_dependency)) do { // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+ __attribute__((carries_dependency)) continue; // expected-error {{'carries_dependency' attribute cannot be applied to a statement}} ignored}}
+ }
+ while (0)
+ ;
+ __attribute__((carries_dependency)) while (0); // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+
+ __attribute__((carries_dependency)) switch (i) { // expected-error {{'carries_dependency' attribute cannot be applied to a statement}} ignored}}
+ __attribute__((carries_dependency)) case 0: // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+ __attribute__((carries_dependency)) default: // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+ __attribute__((carries_dependency)) break; // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+ }
+
+ __attribute__((carries_dependency)) goto here; // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+
+ __attribute__((carries_dependency)) return; // expected-error {{'carries_dependency' attribute cannot be applied to a statement}}
+}
+
+void bar();
+
+void foobar() {
+ __attribute__((nomerge)) bar();
+ __attribute__(()) bar(); // expected-error {{expected identifier or '('}}
+ __attribute__((unused, nomerge)) bar(); // expected-error {{expected identifier or '('}}
+ __attribute__((nomerge, unused)) bar(); // expected-error {{expected identifier or '('}}
+ __attribute__((nomerge(1, 2))) bar(); // expected-error {{'nomerge' attribute takes no arguments}}
+ int x;
+ __attribute__((nomerge)) x = 10; // expected-warning {{nomerge attribute is ignored because there exists no call expression inside the statement}}
+
+ __attribute__((nomerge)) label : bar(); // expected-error {{'nomerge' attribute only applies to functions and statements}}
+}
+
+int f();
+
+__attribute__((nomerge)) static int i; // expected-error {{'nomerge' attribute only applies to functions and statements}}
Index: clang/lib/Parse/ParseStmt.cpp
===================================================================
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -20,6 +20,8 @@
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/TypoCorrection.h"
+#include "llvm/ADT/STLExtras.h"
+
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -210,7 +212,11 @@
if ((getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt ||
(StmtCtx & ParsedStmtContext::AllowDeclarationsInC) !=
ParsedStmtContext()) &&
- (GNUAttributeLoc.isValid() || isDeclarationStatement())) {
+ ((GNUAttributeLoc.isValid() &&
+ !(!Attrs.empty() &&
+ llvm::all_of(
+ Attrs, [](ParsedAttr &Attr) { return Attr.isStmtAttr(); }))) ||
+ isDeclarationStatement())) {
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
DeclGroupPtrTy Decl;
if (GNUAttributeLoc.isValid()) {
Index: clang/include/clang/Basic/Features.def
===================================================================
--- clang/include/clang/Basic/Features.def
+++ clang/include/clang/Basic/Features.def
@@ -253,6 +253,7 @@
EXTENSION(overloadable_unmarked, true)
EXTENSION(pragma_clang_attribute_namespaces, true)
EXTENSION(pragma_clang_attribute_external_declaration, true)
+EXTENSION(statement_attributes_with_gnu_syntax, true)
EXTENSION(gnu_asm, LangOpts.GNUAsm)
EXTENSION(gnu_asm_goto_with_outputs, LangOpts.GNUAsm)
EXTENSION(matrix_types, LangOpts.MatrixTypes)
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits