]> granicus.if.org Git - clang/commitdiff
Add missing diagnostic for anonymous struct/union definitions that don't
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 24 Apr 2019 00:08:02 +0000 (00:08 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 24 Apr 2019 00:08:02 +0000 (00:08 +0000)
introduce any names.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@359051 91177308-0d34-0410-b5e6-96231b3b80d8

12 files changed:
lib/Sema/SemaDecl.cpp
test/Analysis/unions.cpp
test/CXX/class/class.union/class.union.anon/p4.cpp
test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp
test/CXX/drs/dr13xx.cpp
test/CXX/drs/dr14xx.cpp
test/CXX/drs/dr19xx.cpp
test/CXX/module/module.interface/p3.cpp
test/SemaCXX/anonymous-struct.cpp
test/SemaCXX/anonymous-union.cpp
test/SemaCXX/constant-expression-cxx11.cpp
test/SemaCXX/cxx0x-deleted-default-ctor.cpp

index b6ddd860399fceeed5fe48b07a716b536c751cf5..1d0881856e319ae50ddb9b2a82b4a0df44c774f7 100644 (file)
@@ -4817,6 +4817,18 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
     Invalid = true;
   }
 
+  // C++ [dcl.dcl]p3:
+  //   [If there are no declarators], and except for the declaration of an
+  //   unnamed bit-field, the decl-specifier-seq shall introduce one or more
+  //   names into the program
+  // C++ [class.mem]p2:
+  //   each such member-declaration shall either declare at least one member
+  //   name of the class or declare at least one unnamed bit-field
+  //
+  // For C this is an error even for a named struct, and is diagnosed elsewhere.
+  if (getLangOpts().CPlusPlus && Record->field_empty())
+    Diag(DS.getBeginLoc(), diag::ext_no_declarators) << DS.getSourceRange();
+
   // Mock up a declarator.
   Declarator Dc(DS, DeclaratorContext::MemberContext);
   TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S);
index 2aa482479131860aecb7477f29ab13d87d2978d4..6fd35d1a43f4a1c87934c7725576e908cec7b958 100644 (file)
@@ -36,7 +36,7 @@ namespace PR14054_original {
   struct ParseNode {
     union {
       struct {
-        union {};
+        union {}; // expected-warning {{does not declare anything}}
         Definition *lexdef;
       } name;
       class {
index cc54ba40661939d762fc4308e5a447503f1c27bb..a12ec38503fa80675d92c9d19a7f8d7ad9bf74c8 100644 (file)
@@ -2,7 +2,7 @@
 
 union U {
   int x = 0; // expected-note {{previous initialization is here}}
-  union {};
+  union {}; // expected-warning {{does not declare anything}}
   union {
     int z;
     int y = 1; // expected-error {{initializing multiple members of union}}
index 54aabe6ef376e3e5fc7c5678ca4cbe6a3b7711ba..e24e63178efb039dda12cbd17c34c0cb3361668a 100644 (file)
@@ -181,8 +181,8 @@ union Empty {
 } constexpr empty1;
 
 struct EmptyVariant {
-  union {};
-  struct {};
+  union {}; // expected-warning {{does not declare anything}}
+  struct {}; // expected-warning {{does not declare anything}}
   constexpr EmptyVariant() {} // ok
 } constexpr empty2;
 
index 208ab8a03b0a03f4a8abd29d61191fe7eef4cf4c..1d61e8687eef03561c9896e074af15ae05f1b29e 100644 (file)
@@ -272,7 +272,7 @@ namespace dr1359 { // dr1359: 3.5
   union A { constexpr A() = default; };
   union B { constexpr B() = default; int a; }; // expected-error {{not constexpr}} expected-note 2{{candidate}}
   union C { constexpr C() = default; int a, b; }; // expected-error {{not constexpr}} expected-note 2{{candidate}}
-  struct X { constexpr X() = default; union {}; };
+  struct X { constexpr X() = default; union {}; }; // expected-error {{does not declare anything}}
   struct Y { constexpr Y() = default; union { int a; }; }; // expected-error {{not constexpr}} expected-note 2{{candidate}}
 
   constexpr A a = A();
index eb5ba3db448e64aab2b5592cdc6ff8ce6123008b..eb086178fc06f5f16ee7f3168b3dad85854613d4 100644 (file)
@@ -13,22 +13,22 @@ namespace dr1460 { // dr1460: 3.5
 #if __cplusplus >= 201103L
   namespace DRExample {
     union A {
-      union {};
-      union {};
+      union {}; // expected-error {{does not declare anything}}
+      union {}; // expected-error {{does not declare anything}}
       constexpr A() {}
     };
     constexpr A a = A();
 
     union B {
-      union {};
-      union {};
+      union {}; // expected-error {{does not declare anything}}
+      union {}; // expected-error {{does not declare anything}}
       constexpr B() = default;
     };
     constexpr B b = B();
 
     union C {
-      union {};
-      union {};
+      union {}; // expected-error {{does not declare anything}}
+      union {}; // expected-error {{does not declare anything}}
     };
     constexpr C c = C();
 #if __cplusplus > 201103L
@@ -40,7 +40,7 @@ namespace dr1460 { // dr1460: 3.5
   union A {};
   union B { int n; }; // expected-note +{{here}}
   union C { int n = 0; };
-  struct D { union {}; };
+  struct D { union {}; }; // expected-error {{does not declare anything}}
   struct E { union { int n; }; }; // expected-note +{{here}}
   struct F { union { int n = 0; }; };
 
@@ -66,7 +66,7 @@ namespace dr1460 { // dr1460: 3.5
     union A { constexpr A() = default; };
     union B { int n; constexpr B() = default; }; // expected-error {{not constexpr}}
     union C { int n = 0; constexpr C() = default; };
-    struct D { union {}; constexpr D() = default; };
+    struct D { union {}; constexpr D() = default; }; // expected-error {{does not declare anything}}
     struct E { union { int n; }; constexpr E() = default; }; // expected-error {{not constexpr}}
     struct F { union { int n = 0; }; constexpr F() = default; };
 
index e6cf337da0ba36520266b797e262bc51605fd13e..a1e8c764354f6d3fe0069a762ab2e5e886031d46 100644 (file)
@@ -84,6 +84,7 @@ namespace dr1940 { // dr1940: yes
 static union {
   static_assert(true, "");  // ok
   static_assert(false, ""); // expected-error {{static_assert failed}}
+  int not_empty;
 };
 #endif
 }
index 22a003550bbe581ff98c3549ccb9bc782c24da02..29d2cb43b4d23f6f84418a991104f21cce1ac0b9 100644 (file)
@@ -15,15 +15,15 @@ export { // expected-note 3{{export block begins here}}
   using namespace A; // expected-error {{ISO C++20 does not permit using directive to be exported}}
 }
 
-export struct {}; // expected-error {{must be class member}} expected-error {{GNU extension}}
+export struct {}; // expected-error {{must be class member}} expected-error {{GNU extension}} expected-error {{does not declare anything}}
 export struct {} struct_;
-export union {}; // expected-error {{must be declared 'static'}}
+export union {}; // expected-error {{must be declared 'static'}} expected-error {{does not declare anything}}
 export union {} union_;
 export enum {}; // expected-error {{does not declare anything}}
 export enum {} enum_;
 export enum E : int;
 export typedef int; // expected-error {{typedef requires a name}}
-export static union {}; // FIXME: this declaration is ill-formed even without the 'export'
+export static union {}; // expected-error {{does not declare anything}}
 export asm(""); // expected-error {{asm declaration cannot be exported}}
 export namespace B = A;
 export using A::ns_mem;
index f89d19959b8f18ebdb3787f96ec145356c15d30b..42770030d2fa8d09134185e41ea3400b76caccfa 100644 (file)
@@ -9,7 +9,7 @@ struct S {
 #endif
 };
 
-struct { // expected-error {{anonymous structs and classes must be class members}}
+struct { // expected-error {{anonymous structs and classes must be class members}} expected-warning {{does not declare anything}}
 };
 
 struct E {
@@ -19,7 +19,7 @@ struct E {
     // expected-error@-2 {{anonymous struct member 'x' has a non-trivial default constructor}}
 #endif
   };
-  static struct {
+  static struct { // expected-warning {{does not declare anything}}
   };
   class {
     int anon_priv_field; // expected-error {{anonymous struct cannot contain a private data member}}
index 5538ea47033535d08e6274adab1cd135d8567b7f..9a88439994815e710d38427b4b52236ab94618a5 100644 (file)
@@ -81,7 +81,7 @@ union { // expected-error{{anonymous unions at namespace or global scope must be
 };
 
 extern "C++" {
-union { }; // expected-error{{anonymous unions at namespace or global scope must be declared 'static'}}
+union { int extern_cxx; }; // expected-error{{anonymous unions at namespace or global scope must be declared 'static'}}
 }
 
 static union {
index a8076bc19fe0d3f436d9066882f8a0f6dc025ba6..03491f4a8719cf8d1e874fbda36cec5bf5a42024 100644 (file)
@@ -2146,7 +2146,7 @@ namespace InheritedCtor {
   struct B : A { int n; using A::A; }; // expected-note {{here}}
   constexpr B b(0); // expected-error {{constant expression}} expected-note {{derived class}}
 
-  struct C : A { using A::A; struct { union { int n, m = 0; }; union { int a = 0; }; int k = 0; }; struct {}; union {}; }; // expected-warning 4{{extension}}
+  struct C : A { using A::A; struct { union { int n, m = 0; }; union { int a = 0; }; int k = 0; }; struct {}; union {}; }; // expected-warning 6{{}}
   constexpr C c(0);
 
   struct D : A {
index 80efd810f09842b17ea87a383576e8960604cab2..feb483546c3eb6d9226340f757b6d7a32d88e3e2 100644 (file)
@@ -121,11 +121,11 @@ late_delete::late_delete() = default; // expected-error {{would delete it}}
 
 // See also rdar://problem/8125400.
 namespace empty {
-  static union {};
-  static union { union {}; };
-  static union { struct {}; };
-  static union { union { union {}; }; };
-  static union { union { struct {}; }; };
-  static union { struct { union {}; }; };
-  static union { struct { struct {}; }; };
+  static union {}; // expected-warning {{does not declare anything}}
+  static union { union {}; }; // expected-warning {{does not declare anything}}
+  static union { struct {}; }; // expected-warning {{does not declare anything}}
+  static union { union { union {}; }; }; // expected-warning {{does not declare anything}}
+  static union { union { struct {}; }; }; // expected-warning {{does not declare anything}}
+  static union { struct { union {}; }; }; // expected-warning {{does not declare anything}}
+  static union { struct { struct {}; }; }; // expected-warning {{does not declare anything}}
 }