Modify the uninitialized field visitor to detect uninitialized use across the
fields in the class.  This allows a better checking of member intiailizers and
in class initializers in regards to initialization ordering.

For instance, this code will now produce warnings:

class A {
  int x;
  int y;
  A() : x(y) {}  // y is initialized after x, warn here
  A(int): y(x) {} // default initialization of leaves x uninitialized, warn here
};

Several test cases were updated with -Wno-uninitialized to silence this warning.

llvm-svn: 191068
diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p7.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p7.cpp
index d1fbe76..22667ac 100644
--- a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p7.cpp
+++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p7.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++1y %s -verify
+// RUN: %clang_cc1 -Wno-uninitialized -std=c++1y %s -verify
 
 // expected-no-diagnostics
 
diff --git a/clang/test/Parser/cxx-ambig-init-templ.cpp b/clang/test/Parser/cxx-ambig-init-templ.cpp
index 88ab61c..ac79f77 100644
--- a/clang/test/Parser/cxx-ambig-init-templ.cpp
+++ b/clang/test/Parser/cxx-ambig-init-templ.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -verify %s
+// RUN: %clang_cc1 -Wno-uninitialized -std=c++11 -verify %s
 
 template<int> struct c { c(int) = delete; typedef void val; operator int() const; };
 
diff --git a/clang/test/SemaCXX/constexpr-value-init.cpp b/clang/test/SemaCXX/constexpr-value-init.cpp
index d137bd8..e5b7db5 100644
--- a/clang/test/SemaCXX/constexpr-value-init.cpp
+++ b/clang/test/SemaCXX/constexpr-value-init.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -std=c++11 -fsyntax-only -verify
+// RUN: %clang_cc1 %s -Wno-uninitialized -std=c++11 -fsyntax-only -verify
 
 struct A {
   constexpr A() : a(b + 1), b(a + 1) {} // expected-note {{outside its lifetime}}
diff --git a/clang/test/SemaCXX/cxx0x-class.cpp b/clang/test/SemaCXX/cxx0x-class.cpp
index 074591e..2b1338f 100644
--- a/clang/test/SemaCXX/cxx0x-class.cpp
+++ b/clang/test/SemaCXX/cxx0x-class.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wno-error=static-float-init %s 
+// RUN: %clang_cc1 -Wno-uninitialized -fsyntax-only -verify -std=c++11 -Wno-error=static-float-init %s 
 
 int vs = 0;
 
diff --git a/clang/test/SemaCXX/uninitialized.cpp b/clang/test/SemaCXX/uninitialized.cpp
index 31895c6..2fb0482 100644
--- a/clang/test/SemaCXX/uninitialized.cpp
+++ b/clang/test/SemaCXX/uninitialized.cpp
@@ -340,7 +340,10 @@
   };
 
   struct E {
-    int a, b, c;
+    int b = 1;
+    int c = 1;
+    int a;  // This field needs to be last to prevent the cross field
+            // uninitialized warning.
     E(char (*)[1]) : a(a ? b : c) {}  // expected-warning {{field 'a' is uninitialized when used here}}
     E(char (*)[2]) : a(b ? a : a) {} // expected-warning 2{{field 'a' is uninitialized when used here}}
     E(char (*)[3]) : a(b ? (a) : c) {} // expected-warning {{field 'a' is uninitialized when used here}}
@@ -459,7 +462,7 @@
   };
 
   struct U {
-    U() : a(b + 1), b(a + 1) {} // FIXME: Warn here.
+    U() : a(b + 1), b(a + 1) {} // expected-warning{{field 'b' is uninitialized when used here}}
     int a = 42; // Note: because a and b are in the member initializer list, these initializers are ignored.
     int b = 1;
   };
@@ -561,3 +564,107 @@
     A a9 = normal(a9);  // expected-warning {{uninitialized}}
   };
 }
+
+namespace cross_field_warnings {
+  struct A {
+    int a, b;
+    A() {}
+    A(char (*)[1]) : b(a) {}  // expected-warning{{field 'a' is uninitialized when used here}}
+    A(char (*)[2]) : a(b) {}  // expected-warning{{field 'b' is uninitialized when used here}}
+  };
+
+  struct B {
+    int a = b;  // expected-warning{{field 'b' is uninitialized when used here}}
+    int b;
+  };
+
+  struct C {
+    int a;
+    int b = a;  // expected-warning{{field 'a' is uninitialized when used here}}
+    C(char (*)[1]) : a(5) {}
+    C(char (*)[2]) {}
+  };
+
+  struct D {
+    int a;
+    int &b;
+    int &c = a;
+    int d = b;
+    D() : b(a) {}
+  };
+
+  struct E {
+    int a;
+    int get();
+    static int num();
+    E() {}
+    E(int) {}
+  };
+
+  struct F {
+    int a;
+    E e;
+    int b;
+    F(char (*)[1]) : a(e.get()) {}  // expected-warning{{field 'e' is uninitialized when used here}}
+    F(char (*)[2]) : a(e.num()) {}
+    F(char (*)[3]) : e(a) {}  // expected-warning{{field 'a' is uninitialized when used here}}
+    F(char (*)[4]) : a(4), e(a) {}
+    F(char (*)[5]) : e(b) {}  // expected-warning{{field 'b' is uninitialized when used here}}
+    F(char (*)[6]) : e(b), b(4) {}  // expected-warning{{field 'b' is uninitialized when used here}}
+  };
+
+  struct G {
+    G(const A&) {};
+  };
+
+  struct H {
+    A a1;
+    G g;
+    A a2;
+    H() : g(a1) {}
+    H(int) : g(a2) {}
+  };
+
+  struct I {
+    I(int*) {}
+  };
+
+  struct J : public I {
+    int *a;
+    int *b;
+    int c;
+    J() : I((a = new int(5))), b(a), c(*a) {}
+  };
+
+  struct K {
+    int a = (b = 5);
+    int b = b + 5;
+  };
+
+  struct L {
+    int a = (b = 5);
+    int b = b + 5;  // expected-warning{{field 'b' is uninitialized when used here}}
+    L() : a(5) {}  // expected-note{{during field initialization in this constructor}}
+  };
+
+  struct M { };
+
+  struct N : public M {
+    int a;
+    int b;
+    N() : b(a) { }  // expected-warning{{field 'a' is uninitialized when used here}}
+  };
+
+  struct O {
+    int x = 42;
+    int get() { return x; }
+  };
+
+  struct P {
+    O o;
+    int x = o.get();
+    P() : x(o.get()) { }
+  };
+
+}
+
diff --git a/clang/test/SemaCXX/warn-unused-private-field.cpp b/clang/test/SemaCXX/warn-unused-private-field.cpp
index 661442d..932a7dc 100644
--- a/clang/test/SemaCXX/warn-unused-private-field.cpp
+++ b/clang/test/SemaCXX/warn-unused-private-field.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -Wunused-private-field -Wused-but-marked-unused -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -Wunused-private-field -Wused-but-marked-unused -Wno-uninitialized -verify -std=c++11 %s
 
 class NotFullyDefined {
  public: