[Sema] Fix -Wuninitialized for struct assignment from GNU C statement expression

Summary:
Do not automatically report self references of structs in statement expression
as warnings. Instead wait for uninitialized cfg analysis.
https://bugs.llvm.org/show_bug.cgi?id=42604

Reviewers: aaron.ballman, rsmith, nickdesaulniers

Reviewed By: aaron.ballman, nickdesaulniers

Subscribers: nathanchance, cfe-commits

Tags: #clang

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

llvm-svn: 367134
This commit is contained in:
Nathan Huckleberry 2019-07-26 17:29:35 +00:00
parent 9df6177d38
commit 2e040398f8
2 changed files with 62 additions and 3 deletions

View File

@ -11257,9 +11257,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
// Check for self-references within variable initializers.
// Variables declared within a function/method body (except for references)
// are handled by a dataflow analysis.
if (!VDecl->hasLocalStorage() || VDecl->getType()->isRecordType() ||
VDecl->getType()->isReferenceType()) {
CheckSelfReference(*this, RealDecl, Init, DirectInit);
// This is undefined behavior in C++, but valid in C.
if (getLangOpts().CPlusPlus) {
if (!VDecl->hasLocalStorage() || VDecl->getType()->isRecordType() ||
VDecl->getType()->isReferenceType()) {
CheckSelfReference(*this, RealDecl, Init, DirectInit);
}
}
// If the type changed, it means we had an incomplete type that was

View File

@ -0,0 +1,56 @@
// RUN: %clang_cc1 -fsyntax-only -Wuninitialized -verify %s
void init(int *);
void foo(void) {
int i = ({
init(&i);
i;
});
}
void foo_bad(void) {
int i = ({
int z = i; // expected-warning{{variable 'i' is uninitialized when used within its own initialization}}
init(&i);
i;
});
}
struct widget {
int x, y;
};
void init2(struct widget *);
void bar(void) {
struct widget my_widget = ({
init2(&my_widget);
my_widget;
});
struct widget a = (init2(&a), a);
}
void bar_bad(void) {
struct widget my_widget = ({
struct widget z = my_widget; // expected-warning{{variable 'my_widget' is uninitialized when used within its own initialization}}
int x = my_widget.x; //FIXME: There should be an uninitialized warning here
init2(&my_widget);
my_widget;
});
}
void baz(void) {
struct widget a = ({
struct widget b = ({
b = a; // expected-warning{{variable 'a' is uninitialized when used within its own initialization}}
});
a;
});
}
void f(void) {
struct widget *a = ({
init2(a); // expected-warning{{variable 'a' is uninitialized when used within its own initialization}}
a;
});
}