constexpr tidyups:
  * Fix bug when determining whether && / || are potential constant expressions
  * Try harder when determining whether ?: is a potential constant expression
  * Produce a diagnostic on sizeof(VLA) to provide a better source location

llvm-svn: 150657
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp
index 4e7608e..133d944 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp
@@ -51,7 +51,7 @@
   0;
 }
 
-int ng; // expected-note 5{{here}}
+int ng; // expected-note 6{{here}}
 constexpr int BinaryOp1(int n) { return n + ng; } // expected-error {{never produces}} expected-note {{read}}
 constexpr int BinaryOp2(int n) { return ng + n; } // expected-error {{never produces}} expected-note {{read}}
 
@@ -64,13 +64,18 @@
 
 struct S { int a; int b; int c[2]; };
 constexpr S InitList(int a) { return { a, ng }; }; // expected-error {{never produces}} expected-note {{read}}
+constexpr S InitList1a(int a) { return S{ a, ng }; }; // expected-error {{never produces}} expected-note {{read}}
 constexpr S InitList2(int a) { return { a, a, { ng } }; }; // expected-error {{never produces}} expected-note {{read}}
+constexpr S InitList3(int a) { return a ? S{ a, a } : S{ a, ng }; }; // ok
 
-constexpr S InitList3(int a) { return a ? (S){ a, a } : (S){ a, ng }; }; // ok
+constexpr int LogicalAnd1(int n) { return n && (throw, 0); } // ok
+constexpr int LogicalAnd2(int n) { return 1 && (throw, 0); } // expected-error {{never produces}} expected-note {{subexpression}}
 
-// FIXME: Check both arms of a ?: if the conditional is a potential constant
-// expression with an unknown value, and diagnose if neither is constant.
-constexpr S InitList4(int a) { return a ? (S){ a, ng } : (S){ a, ng }; };
+constexpr int LogicalOr1(int n) { return n || (throw, 0); } // ok
+constexpr int LogicalOr2(int n) { return 0 || (throw, 0); } // expected-error {{never produces}} expected-note {{subexpression}}
+
+constexpr int Conditional1(bool b, int n) { return b ? n : ng; } // ok
+constexpr int Conditional2(bool b, int n) { return b ? n * ng : n + ng; } // expected-error {{never produces}} expected-note {{both arms of conditional operator are unable to produce a constant expression}}
 
 // __builtin_constant_p ? : is magical, and is always a potential constant.
 constexpr bool BcpCall(int n) {
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index aa40311..f5cc1b3 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1169,3 +1169,26 @@
 constexpr const int j = i; // expected-error {{constant expression}} expected-note {{initializer of 'i' is not a constant expression}}
 
 }
+
+namespace RecursiveOpaqueExpr {
+  template<typename Iter>
+  constexpr auto LastNonzero(Iter p, Iter q) -> decltype(+*p) {
+    return p != q ? (LastNonzero(p+1, q) ?: *p) : 0; // expected-warning {{GNU}}
+  }
+
+  constexpr int arr1[] = { 1, 0, 0, 3, 0, 2, 0, 4, 0, 0 };
+  static_assert(LastNonzero(begin(arr1), end(arr1)) == 4, "");
+
+  constexpr int arr2[] = { 1, 0, 0, 3, 0, 2, 0, 4, 0, 5 };
+  static_assert(LastNonzero(begin(arr2), end(arr2)) == 5, "");
+}
+
+namespace VLASizeof {
+
+  void f(int k) {
+    int arr[k]; // expected-warning {{C99}}
+    constexpr int n = 1 +
+        sizeof(arr) // expected-error {{constant expression}}
+        * 3;
+  }
+}