[clang] f4c886b - [clang] Properly print unnamed members in diagnostics

via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 24 07:38:15 PDT 2023


Author: Podchishchaeva, Mariya
Date: 2023-08-24T07:24:29-07:00
New Revision: f4c886b6aaeac0a48f3bdeda3103887599373842

URL: https://github.com/llvm/llvm-project/commit/f4c886b6aaeac0a48f3bdeda3103887599373842
DIFF: https://github.com/llvm/llvm-project/commit/f4c886b6aaeac0a48f3bdeda3103887599373842.diff

LOG: [clang] Properly print unnamed members in diagnostics

Use member's type when printing.
This also fixes a bug in warning diagnostic for out of order
initialization with designated initializers so it points to a valid
source location when an anonymous member is being initialized.

Fixes https://github.com/llvm/llvm-project/issues/63759

Reviewed By: aaron.ballman, shafik

Differential Revision: https://reviews.llvm.org/D158526

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/AST/Decl.h
    clang/lib/AST/Decl.cpp
    clang/lib/Sema/SemaInit.cpp
    clang/test/AST/ast-dump-APValue-anon-union.cpp
    clang/test/CXX/special/class.dtor/p5-0x.cpp
    clang/test/Sema/transparent-union.c
    clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
    clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp
    clang/test/SemaObjCXX/arc-0x.mm

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 0f6ad2e70c7d5f..8d9f4a5b86b54c 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 <https://github.com/llvm/llvm-project/issues/64945>`_ for details.
+- Clang now prints unnamed members in diagnostic messages instead of giving an
+  empty ''. Fixes
+  (`#63759 <https://github.com/llvm/llvm-project/issues/63759>`_)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index f6e38e5c57440d..a4390052890fff 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<FieldDecl> {
   // 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 7971a03153650c..60c80f2b075336 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 a21fdb771a4d66..d915d06ab2f1b8 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 1ed87e66561496..906bfe4857ed03 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:{{.*}}, col:{{.*}}> 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:{{.*}}, col:{{.*}}> 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:{{.*}}, col:{{.*}}> 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 ac8ce3466cb5c7..ae14dcdaf102ac 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 7967535db8c135..c134a7a9b1c4d0 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 4a4bf7180a47f4..c7cdf76d850dbe 100644
--- a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
+++ b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
@@ -136,7 +136,7 @@ namespace pr16061 {
 
   template<typename T> struct Test2 {
     union {
-      struct {  // expected-note {{default constructor of 'Test2<pr16061::X>' is implicitly deleted because variant field '' has a non-trivial default constructor}}
+      struct {  // expected-note-re {{default constructor of 'Test2<pr16061::X>' 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 60cd2547ee417a..510ace58c35a6a 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 at -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 at -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 743fabf667a1e4..2d5037bc72b272 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;
       };


        


More information about the cfe-commits mailing list