Commit d1b122cb authored by Hans Wennborg's avatar Hans Wennborg
Browse files

Merging r367134:

------------------------------------------------------------------------
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
parent e2025880
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -11527,10 +11527,13 @@ 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.
  // 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
  // completed by the initializer. For example:
+56 −0
Original line number Diff line number Diff line
// 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;
  });
}