From: Richard Smith Date: Wed, 24 Apr 2019 00:08:02 +0000 (+0000) Subject: Add missing diagnostic for anonymous struct/union definitions that don't X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=01f976def19d3a1f90fa7dc40d11f15b9f610d2c;p=clang Add missing diagnostic for anonymous struct/union definitions that don't introduce any names. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@359051 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index b6ddd86039..1d0881856e 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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); diff --git a/test/Analysis/unions.cpp b/test/Analysis/unions.cpp index 2aa4824791..6fd35d1a43 100644 --- a/test/Analysis/unions.cpp +++ b/test/Analysis/unions.cpp @@ -36,7 +36,7 @@ namespace PR14054_original { struct ParseNode { union { struct { - union {}; + union {}; // expected-warning {{does not declare anything}} Definition *lexdef; } name; class { diff --git a/test/CXX/class/class.union/class.union.anon/p4.cpp b/test/CXX/class/class.union/class.union.anon/p4.cpp index cc54ba4066..a12ec38503 100644 --- a/test/CXX/class/class.union/class.union.anon/p4.cpp +++ b/test/CXX/class/class.union/class.union.anon/p4.cpp @@ -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}} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp index 54aabe6ef3..e24e63178e 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp @@ -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; diff --git a/test/CXX/drs/dr13xx.cpp b/test/CXX/drs/dr13xx.cpp index 208ab8a03b..1d61e8687e 100644 --- a/test/CXX/drs/dr13xx.cpp +++ b/test/CXX/drs/dr13xx.cpp @@ -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(); diff --git a/test/CXX/drs/dr14xx.cpp b/test/CXX/drs/dr14xx.cpp index eb5ba3db44..eb086178fc 100644 --- a/test/CXX/drs/dr14xx.cpp +++ b/test/CXX/drs/dr14xx.cpp @@ -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; }; diff --git a/test/CXX/drs/dr19xx.cpp b/test/CXX/drs/dr19xx.cpp index e6cf337da0..a1e8c76435 100644 --- a/test/CXX/drs/dr19xx.cpp +++ b/test/CXX/drs/dr19xx.cpp @@ -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 } diff --git a/test/CXX/module/module.interface/p3.cpp b/test/CXX/module/module.interface/p3.cpp index 22a003550b..29d2cb43b4 100644 --- a/test/CXX/module/module.interface/p3.cpp +++ b/test/CXX/module/module.interface/p3.cpp @@ -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; diff --git a/test/SemaCXX/anonymous-struct.cpp b/test/SemaCXX/anonymous-struct.cpp index f89d19959b..42770030d2 100644 --- a/test/SemaCXX/anonymous-struct.cpp +++ b/test/SemaCXX/anonymous-struct.cpp @@ -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}} diff --git a/test/SemaCXX/anonymous-union.cpp b/test/SemaCXX/anonymous-union.cpp index 5538ea4703..9a88439994 100644 --- a/test/SemaCXX/anonymous-union.cpp +++ b/test/SemaCXX/anonymous-union.cpp @@ -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 { diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index a8076bc19f..03491f4a87 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -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 { diff --git a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp index 80efd810f0..feb483546c 100644 --- a/test/SemaCXX/cxx0x-deleted-default-ctor.cpp +++ b/test/SemaCXX/cxx0x-deleted-default-ctor.cpp @@ -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}} }