vsavchenko updated this revision to Diff 319516.
vsavchenko added a comment.
Herald added a subscriber: dexonsmith.

Add extension for backward compatibility checks


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,53 @@
+// RUN: %clang_cc1 -verify %s \
+// RUN:   -fblocks -fobjc-exceptions -fexceptions -fsyntax-only \
+// RUN:   -Wno-unused-value -Wno-unused-getter-return-value
+
+@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,23 @@
+// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s
+
+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,86 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+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
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to