Skip to content

Commit

Permalink
[clang] Properly print unnamed members in diagnostics
Browse files Browse the repository at this point in the history
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 #63759

Reviewed By: aaron.ballman, shafik

Differential Revision: https://reviews.llvm.org/D158526
  • Loading branch information
Fznamznon committed Aug 24, 2023
1 parent 434bf16 commit f4c886b
Show file tree
Hide file tree
Showing 10 changed files with 48 additions and 13 deletions.
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
//===----------------------------------------------------------------------===//
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions clang/test/AST/ast-dump-APValue-anon-union.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
5 changes: 2 additions & 3 deletions clang/test/CXX/special/class.dtor/p5-0x.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
};
};
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Sema/transparent-union.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
2 changes: 1 addition & 1 deletion clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
};
Expand Down
20 changes: 20 additions & 0 deletions clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
//
}
}
8 changes: 4 additions & 4 deletions clang/test/SemaObjCXX/arc-0x.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand All @@ -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;
};
Expand All @@ -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;
};
Expand Down

0 comments on commit f4c886b

Please sign in to comment.