forked from OSchip/llvm-project
[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:
parent
9df6177d38
commit
2e040398f8
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue