Skip to content

Commit

Permalink
Merging r367134:
Browse files Browse the repository at this point in the history
------------------------------------------------------------------------
r367134 | nathan-huckleberry | 2019-07-26 19:29:35 +0200 (Fri, 26 Jul 2019) | 16 lines

[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: 367150
  • Loading branch information
zmodem committed Jul 26, 2019
1 parent e202588 commit d1b122c
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 3 deletions.
9 changes: 6 additions & 3 deletions clang/lib/Sema/SemaDecl.cpp
Expand Up @@ -11527,9 +11527,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
Expand Down
56 changes: 56 additions & 0 deletions clang/test/Sema/warn-uninitialized-statement-expression.c
@@ -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;
});
}

0 comments on commit d1b122c

Please sign in to comment.