vsavchenko created this revision.
Herald added a subscriber: jdoerfert.
vsavchenko requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Before this commit, expression statements could not be annotated
with statement attributes.  Whenever parser found attribute, it
unconditionally assumed that it was followed by a declaration.
This not only doesn't allow expression attributes to have attributes,
but also produces spurious error diagnostics.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D93630

Files:
  clang/lib/Parse/ParseStmt.cpp
  clang/test/Parser/stmt-attributes.c
  clang/test/Sema/address_spaces.c
  clang/test/Sema/block-literal.c
  clang/test/SemaTemplate/address_space-dependent.cpp

Index: clang/test/SemaTemplate/address_space-dependent.cpp
===================================================================
--- clang/test/SemaTemplate/address_space-dependent.cpp
+++ clang/test/SemaTemplate/address_space-dependent.cpp
@@ -9,7 +9,8 @@
   __attribute__((address_space(J))) int array[5];     // expected-error {{automatic variable qualified with an address space}}
   __attribute__((address_space(I))) int arrarr[5][5]; // expected-error {{automatic variable qualified with an address space}}
 
-  __attribute__((address_space(J))) * x; // expected-error {{C++ requires a type specifier for all declarations}}
+  __attribute__((address_space(J))) * x; // expected-error {{use of undeclared identifier 'x'}}
+  // expected-error@-1 {{'address_space' attribute cannot be applied to a statement}}
 
   __attribute__((address_space(I))) float *B;
 
Index: clang/test/Sema/block-literal.c
===================================================================
--- clang/test/Sema/block-literal.c
+++ clang/test/Sema/block-literal.c
@@ -41,8 +41,11 @@
 
   foo:
   takeblock(^{ x = 4; });  // expected-error {{variable is not assignable (missing __block type specifier)}}
-  __block y = 7;    // expected-warning {{type specifier missing, defaults to 'int'}}
-  takeblock(^{ y = 8; });
+  __block y = 7;           // expected-error {{use of undeclared identifier 'y'}}
+  __block int z = 7;
+  takeblock(^{
+    z = 8;
+  });
 }
 
 
Index: clang/test/Sema/address_spaces.c
===================================================================
--- clang/test/Sema/address_spaces.c
+++ clang/test/Sema/address_spaces.c
@@ -9,7 +9,8 @@
 void foo(_AS3 float *a,
          _AS1 float b) // expected-error {{parameter may not be qualified with an address space}}
 {
-  _AS2 *x;// expected-warning {{type specifier missing, defaults to 'int'}}
+  _AS2 *x; // expected-error {{'address_space' attribute cannot be applied to a statement}}
+  // expected-error@-1 {{use of undeclared identifier 'x'}}
   _AS1 float * _AS2 *B;
 
   int _AS1 _AS2 *Y;   // expected-error {{multiple address spaces specified for type}}
Index: clang/test/Parser/stmt-attributes.c
===================================================================
--- /dev/null
+++ clang/test/Parser/stmt-attributes.c
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+void foo(int i) {
+
+  __attribute__((unknown_attribute));            // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
+  __attribute__((unknown_attribute)) {}          // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
+  __attribute__((unknown_attribute)) if (0) {}   // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
+  __attribute__((unknown_attribute)) for (;;);   // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
+  __attribute__((unknown_attribute)) do {        // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
+    __attribute__((unknown_attribute)) continue; // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
+  }
+  while (0)
+    ;
+  __attribute__((unknown_attribute)) while (0); // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
+
+  __attribute__((unknown_attribute)) switch (i) {                                                                                      // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
+    __attribute__((unknown_attribute)) case 0 :                                                                                        // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
+                                                __attribute__((unknown_attribute)) default :                                           // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
+                                                                                             __attribute__((unknown_attribute)) break; // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
+  }
+
+  __attribute__((unknown_attribute)) goto here; // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
+  __attribute__((unknown_attribute)) here :     // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
+
+                                            __attribute__((unknown_attribute)) return; // expected-warning {{unknown attribute 'unknown_attribute' ignored}}
+
+  __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_attributqqq)) while (0); // expected-warning {{unknown attribute 'unknown_attributqqq' ignored}}
+                                                  // TODO: remove 'qqq' part and enjoy 'empty loop body' warning here (DiagnoseEmptyLoopBody)
+
+  __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}}
+}
Index: clang/lib/Parse/ParseStmt.cpp
===================================================================
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -210,7 +210,7 @@
     if ((getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt ||
          (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) !=
              ParsedStmtContext()) &&
-        (GNUAttributeLoc.isValid() || isDeclarationStatement())) {
+        isDeclarationStatement()) {
       SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
       DeclGroupPtrTy Decl;
       if (GNUAttributeLoc.isValid()) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to