diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 0f6ad2e70c7d5..8d9f4a5b86b54 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -166,6 +166,9 @@ Bug Fixes in This Version The current solution may bring performance regressions if the awaiters have non-static data members. See `#64945 `_ for details. +- Clang now prints unnamed members in diagnostic messages instead of giving an + empty ''. Fixes + (`#63759 `_) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index f6e38e5c57440..a4390052890ff 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -3182,6 +3182,8 @@ class FieldDecl : public DeclaratorDecl, public Mergeable { // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstField && K <= lastField; } + + void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override; }; /// An instance of this object exists for each enum constant diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 7971a03153650..60c80f2b07533 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -4557,6 +4557,16 @@ void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) { CapturedVLAType = VLAType; } +void FieldDecl::printName(raw_ostream &OS, const PrintingPolicy &Policy) const { + // Print unnamed members using name of their type. + if (isAnonymousStructOrUnion()) { + this->getType().print(OS, Policy); + return; + } + // Otherwise, do the normal printing. + DeclaratorDecl::printName(OS, Policy); +} + //===----------------------------------------------------------------------===// // TagDecl Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index a21fdb771a4d6..d915d06ab2f1b 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2858,7 +2858,8 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, if (PrevField && PrevField->getFieldIndex() > KnownField->getFieldIndex()) { - SemaRef.Diag(DIE->getBeginLoc(), diag::ext_designated_init_reordered) + SemaRef.Diag(DIE->getInit()->getBeginLoc(), + diag::ext_designated_init_reordered) << KnownField << PrevField << DIE->getSourceRange(); unsigned OldIndex = StructuredIndex - 1; diff --git a/clang/test/AST/ast-dump-APValue-anon-union.cpp b/clang/test/AST/ast-dump-APValue-anon-union.cpp index 1ed87e6656149..906bfe4857ed0 100644 --- a/clang/test/AST/ast-dump-APValue-anon-union.cpp +++ b/clang/test/AST/ast-dump-APValue-anon-union.cpp @@ -40,13 +40,13 @@ void Test() { constexpr U0 u0b{3.1415f}; // CHECK: | `-VarDecl {{.*}} col:{{.*}} u0b 'const U0':'const U0' constexpr listinit - // CHECK-NEXT: | |-value: Union . Union .f Float 3.141500e+00 + // CHECK-NEXT: | |-value: Union .U0::(anonymous union at {{.*}}) Union .f Float 3.141500e+00 constexpr U1 u1a{}; // CHECK: | `-VarDecl {{.*}} col:{{.*}} u1a 'const U1':'const U1' constexpr listinit - // CHECK-NEXT: | |-value: Union . Union .f Float 0.000000e+00 + // CHECK-NEXT: | |-value: Union .U1::(anonymous union at {{.*}}) Union .f Float 0.000000e+00 constexpr U1 u1b{3.1415f}; // CHECK: `-VarDecl {{.*}} col:{{.*}} u1b 'const U1':'const U1' constexpr listinit - // CHECK-NEXT: |-value: Union . Union .f Float 3.141500e+00 + // CHECK-NEXT: |-value: Union .U1::(anonymous union at {{.*}}) Union .f Float 3.141500e+00 } diff --git a/clang/test/CXX/special/class.dtor/p5-0x.cpp b/clang/test/CXX/special/class.dtor/p5-0x.cpp index ac8ce3466cb5c..ae14dcdaf102a 100644 --- a/clang/test/CXX/special/class.dtor/p5-0x.cpp +++ b/clang/test/CXX/special/class.dtor/p5-0x.cpp @@ -63,15 +63,14 @@ struct B4 { B4 b4; // expected-error {{deleted function}} union B5 { B5(); - // FIXME: Describe the anonymous union member better than ''. - union { // expected-note {{because field '' has a deleted destructor}} + union { // expected-note-re {{because field 'B5::(anonymous union at {{.+}})' has a deleted destructor}} DeletedDtor a; // expected-note {{because field 'a' has a deleted destructor}} }; }; B5 b5; // expected-error {{deleted function}} union B6 { B6(); - union { // expected-note {{because field '' has a deleted destructor}} + union { // expected-note-re {{because field 'B6::(anonymous union at {{.+}})' has a deleted destructor}} InaccessibleDtor a; // expected-note {{because field 'a' has an inaccessible destructor}} }; }; diff --git a/clang/test/Sema/transparent-union.c b/clang/test/Sema/transparent-union.c index 7967535db8c13..c134a7a9b1c4d 100644 --- a/clang/test/Sema/transparent-union.c +++ b/clang/test/Sema/transparent-union.c @@ -124,7 +124,7 @@ union pr15134v2 { unsigned int u1; unsigned int u2; }; - struct { // expected-warning {{alignment of field '' (64 bits) does not match the alignment of the first field in transparent union; transparent_union attribute ignored}} + struct { // expected-warning-re {{alignment of field 'struct pr15134v2::(anonymous at {{.+}})' (64 bits) does not match the alignment of the first field in transparent union; transparent_union attribute ignored}} unsigned int u3; } __attribute__((aligned(8))); } __attribute__((transparent_union)); diff --git a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp index 4a4bf7180a47f..c7cdf76d850db 100644 --- a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp +++ b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp @@ -136,7 +136,7 @@ namespace pr16061 { template struct Test2 { union { - struct { // expected-note {{default constructor of 'Test2' is implicitly deleted because variant field '' has a non-trivial default constructor}} + struct { // expected-note-re {{default constructor of 'Test2' is implicitly deleted because variant field 'struct (anonymous struct at{{.+}})' has a non-trivial default constructor}} T x; }; }; diff --git a/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp b/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp index 60cd2547ee417..510ace58c35a6 100644 --- a/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp +++ b/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp @@ -227,3 +227,23 @@ struct : public A, public B { .a = 1, // reorder-error {{field 'b' will be initialized after field 'a'}} }; } + +namespace GH63759 { +struct C { + int y = 1; + union { + int a; + short b; + }; + int x = 1; +}; + +void foo() { + C c1 = {.x = 3, .a = 1}; // reorder-error-re {{ISO C++ requires field designators to be specified in declaration order; field 'x' will be initialized after field 'GH63759::C::(anonymous union at {{.*}})'}} + // reorder-note@-1 {{previous initialization for field 'x' is here}} + + C c2 = {.a = 3, .y = 1}; // reorder-error-re {{ISO C++ requires field designators to be specified in declaration order; field 'GH63759::C::(anonymous union at {{.*}})' will be initialized after field 'y'}} + // reorder-note-re@-1 {{previous initialization for field 'GH63759::C::(anonymous union at {{.*}})' is here}} + // +} +} diff --git a/clang/test/SemaObjCXX/arc-0x.mm b/clang/test/SemaObjCXX/arc-0x.mm index 743fabf667a1e..2d5037bc72b27 100644 --- a/clang/test/SemaObjCXX/arc-0x.mm +++ b/clang/test/SemaObjCXX/arc-0x.mm @@ -161,7 +161,7 @@ void test() { struct S1 { union { - union { // expected-note {{copy constructor of 'S1' is implicitly deleted because field '' has a deleted copy constructor}} expected-note {{copy assignment operator of 'S1' is implicitly deleted because field '' has a deleted copy assignment operator}} expected-note 4 {{'S1' is implicitly deleted because field '' has a deleted}} + union { // expected-note-re {{copy constructor of 'S1' is implicitly deleted because field 'test_union::S1::(anonymous union at {{.*}})' has a deleted copy constructor}} expected-note-re {{copy assignment operator of 'S1' is implicitly deleted because field 'test_union::S1::(anonymous union at {{.*}})' has a deleted copy assignment operator}} expected-note-re 4 {{'S1' is implicitly deleted because field 'test_union::S1::(anonymous union at {{.*}})' has a deleted}} id f0; // expected-note-re 2 {{{{.*}} of '(anonymous union at {{.*}}' is implicitly deleted because variant field 'f0' is an ObjC pointer}} char f1; }; @@ -172,7 +172,7 @@ void test() { struct S2 { union { // FIXME: the note should say 'f0' is causing the special functions to be deleted. - struct { // expected-note 6 {{'S2' is implicitly deleted because variant field '' has a non-trivial}} + struct { // expected-note-re 6 {{'S2' is implicitly deleted because variant field 'test_union::S2::(anonymous struct at {{.*}})' has a non-trivial}} id f0; int f1; }; @@ -194,8 +194,8 @@ void test() { }; static union { // expected-error {{call to implicitly-deleted default constructor of}} - union { // expected-note-re {{default constructor of '(unnamed union at {{.*}}' is implicitly deleted because field '' has a deleted default constructor}} - union { // expected-note-re {{default constructor of '(anonymous union at {{.*}}' is implicitly deleted because field '' has a deleted default constructor}} + union { // expected-note-re {{default constructor of '(unnamed union at {{.*}}' is implicitly deleted because field 'test_union::(anonymous union at {{.*}})' has a deleted default constructor}} + union { // expected-note-re {{default constructor of '(anonymous union at {{.*}}' is implicitly deleted because field 'test_union::(anonymous union at {{.*}})' has a deleted default constructor}} __weak id g1; // expected-note-re {{default constructor of '(anonymous union at {{.*}}' is implicitly deleted because variant field 'g1' is an ObjC pointer}} int g2; };