Skip to content

Commit f4c886b

Browse files
committed
[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 llvm#63759 Reviewed By: aaron.ballman, shafik Differential Revision: https://reviews.llvm.org/D158526
1 parent 434bf16 commit f4c886b

File tree

10 files changed

+48
-13
lines changed

10 files changed

+48
-13
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ Bug Fixes in This Version
166166
The current solution may bring performance regressions if the awaiters have
167167
non-static data members. See
168168
`#64945 <https://github.com/llvm/llvm-project/issues/64945>`_ for details.
169+
- Clang now prints unnamed members in diagnostic messages instead of giving an
170+
empty ''. Fixes
171+
(`#63759 <https://github.com/llvm/llvm-project/issues/63759>`_)
169172

170173
Bug Fixes to Compiler Builtins
171174
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/AST/Decl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3182,6 +3182,8 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
31823182
// Implement isa/cast/dyncast/etc.
31833183
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
31843184
static bool classofKind(Kind K) { return K >= firstField && K <= lastField; }
3185+
3186+
void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override;
31853187
};
31863188

31873189
/// An instance of this object exists for each enum constant

clang/lib/AST/Decl.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4557,6 +4557,16 @@ void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) {
45574557
CapturedVLAType = VLAType;
45584558
}
45594559

4560+
void FieldDecl::printName(raw_ostream &OS, const PrintingPolicy &Policy) const {
4561+
// Print unnamed members using name of their type.
4562+
if (isAnonymousStructOrUnion()) {
4563+
this->getType().print(OS, Policy);
4564+
return;
4565+
}
4566+
// Otherwise, do the normal printing.
4567+
DeclaratorDecl::printName(OS, Policy);
4568+
}
4569+
45604570
//===----------------------------------------------------------------------===//
45614571
// TagDecl Implementation
45624572
//===----------------------------------------------------------------------===//

clang/lib/Sema/SemaInit.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2858,7 +2858,8 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
28582858

28592859
if (PrevField &&
28602860
PrevField->getFieldIndex() > KnownField->getFieldIndex()) {
2861-
SemaRef.Diag(DIE->getBeginLoc(), diag::ext_designated_init_reordered)
2861+
SemaRef.Diag(DIE->getInit()->getBeginLoc(),
2862+
diag::ext_designated_init_reordered)
28622863
<< KnownField << PrevField << DIE->getSourceRange();
28632864

28642865
unsigned OldIndex = StructuredIndex - 1;

clang/test/AST/ast-dump-APValue-anon-union.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,13 @@ void Test() {
4040

4141
constexpr U0 u0b{3.1415f};
4242
// CHECK: | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u0b 'const U0':'const U0' constexpr listinit
43-
// CHECK-NEXT: | |-value: Union . Union .f Float 3.141500e+00
43+
// CHECK-NEXT: | |-value: Union .U0::(anonymous union at {{.*}}) Union .f Float 3.141500e+00
4444

4545
constexpr U1 u1a{};
4646
// CHECK: | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u1a 'const U1':'const U1' constexpr listinit
47-
// CHECK-NEXT: | |-value: Union . Union .f Float 0.000000e+00
47+
// CHECK-NEXT: | |-value: Union .U1::(anonymous union at {{.*}}) Union .f Float 0.000000e+00
4848

4949
constexpr U1 u1b{3.1415f};
5050
// CHECK: `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} u1b 'const U1':'const U1' constexpr listinit
51-
// CHECK-NEXT: |-value: Union . Union .f Float 3.141500e+00
51+
// CHECK-NEXT: |-value: Union .U1::(anonymous union at {{.*}}) Union .f Float 3.141500e+00
5252
}

clang/test/CXX/special/class.dtor/p5-0x.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,14 @@ struct B4 {
6363
B4 b4; // expected-error {{deleted function}}
6464
union B5 {
6565
B5();
66-
// FIXME: Describe the anonymous union member better than ''.
67-
union { // expected-note {{because field '' has a deleted destructor}}
66+
union { // expected-note-re {{because field 'B5::(anonymous union at {{.+}})' has a deleted destructor}}
6867
DeletedDtor a; // expected-note {{because field 'a' has a deleted destructor}}
6968
};
7069
};
7170
B5 b5; // expected-error {{deleted function}}
7271
union B6 {
7372
B6();
74-
union { // expected-note {{because field '' has a deleted destructor}}
73+
union { // expected-note-re {{because field 'B6::(anonymous union at {{.+}})' has a deleted destructor}}
7574
InaccessibleDtor a; // expected-note {{because field 'a' has an inaccessible destructor}}
7675
};
7776
};

clang/test/Sema/transparent-union.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ union pr15134v2 {
124124
unsigned int u1;
125125
unsigned int u2;
126126
};
127-
struct { // expected-warning {{alignment of field '' (64 bits) does not match the alignment of the first field in transparent union; transparent_union attribute ignored}}
127+
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}}
128128
unsigned int u3;
129129
} __attribute__((aligned(8)));
130130
} __attribute__((transparent_union));

clang/test/SemaCXX/cxx0x-nontrivial-union.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ namespace pr16061 {
136136

137137
template<typename T> struct Test2 {
138138
union {
139-
struct { // expected-note {{default constructor of 'Test2<pr16061::X>' is implicitly deleted because variant field '' has a non-trivial default constructor}}
139+
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}}
140140
T x;
141141
};
142142
};

clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,23 @@ struct : public A, public B {
227227
.a = 1, // reorder-error {{field 'b' will be initialized after field 'a'}}
228228
};
229229
}
230+
231+
namespace GH63759 {
232+
struct C {
233+
int y = 1;
234+
union {
235+
int a;
236+
short b;
237+
};
238+
int x = 1;
239+
};
240+
241+
void foo() {
242+
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 {{.*}})'}}
243+
// reorder-note@-1 {{previous initialization for field 'x' is here}}
244+
245+
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'}}
246+
// reorder-note-re@-1 {{previous initialization for field 'GH63759::C::(anonymous union at {{.*}})' is here}}
247+
//
248+
}
249+
}

clang/test/SemaObjCXX/arc-0x.mm

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ void test() {
161161

162162
struct S1 {
163163
union {
164-
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}}
164+
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}}
165165
id f0; // expected-note-re 2 {{{{.*}} of '(anonymous union at {{.*}}' is implicitly deleted because variant field 'f0' is an ObjC pointer}}
166166
char f1;
167167
};
@@ -172,7 +172,7 @@ void test() {
172172
struct S2 {
173173
union {
174174
// FIXME: the note should say 'f0' is causing the special functions to be deleted.
175-
struct { // expected-note 6 {{'S2' is implicitly deleted because variant field '' has a non-trivial}}
175+
struct { // expected-note-re 6 {{'S2' is implicitly deleted because variant field 'test_union::S2::(anonymous struct at {{.*}})' has a non-trivial}}
176176
id f0;
177177
int f1;
178178
};
@@ -194,8 +194,8 @@ void test() {
194194
};
195195

196196
static union { // expected-error {{call to implicitly-deleted default constructor of}}
197-
union { // expected-note-re {{default constructor of '(unnamed union at {{.*}}' is implicitly deleted because field '' has a deleted default constructor}}
198-
union { // expected-note-re {{default constructor of '(anonymous union at {{.*}}' is implicitly deleted because field '' has a deleted default constructor}}
197+
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}}
198+
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}}
199199
__weak id g1; // expected-note-re {{default constructor of '(anonymous union at {{.*}}' is implicitly deleted because variant field 'g1' is an ObjC pointer}}
200200
int g2;
201201
};

0 commit comments

Comments
 (0)