summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorRichard Smith <richard@metafoo.co.uk>2020-03-09 17:34:33 -0700
committerHans Wennborg <hans@chromium.org>2020-03-12 12:10:24 +0100
commitd9bd6e3c1943e03b783f11d9f2e224ff83f83a7b (patch)
tree16f09db3551e9ad0ed5a7f345d319442e6efd6ce /clang/test
parent5e062819d5adeb2526f1b8393edf5a265bef1591 (diff)
downloadbcm5719-llvm-d9bd6e3c1943e03b783f11d9f2e224ff83f83a7b.tar.gz
bcm5719-llvm-d9bd6e3c1943e03b783f11d9f2e224ff83f83a7b.zip
PR45083: Mark statement expressions as being dependent if they appear in
a dependent context. This matches the GCC behavior. We track the enclosing template depth when determining whether a statement expression is within a dependent context; there doesn't appear to be any other reliable way to determine this. We previously assumed they were neither value- nor instantiation-dependent under any circumstances, which would lead to crashes and other misbehavior. (cherry picked from commit 5c845c1c50ac89a6f12557d1571678f3d1432478)
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/SemaTemplate/dependent-expr.cpp69
1 files changed, 67 insertions, 2 deletions
diff --git a/clang/test/SemaTemplate/dependent-expr.cpp b/clang/test/SemaTemplate/dependent-expr.cpp
index bb1e239c349..0ce4cb39d34 100644
--- a/clang/test/SemaTemplate/dependent-expr.cpp
+++ b/clang/test/SemaTemplate/dependent-expr.cpp
@@ -1,5 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++2a %s
// PR5908
template <typename Iterator>
@@ -108,3 +107,69 @@ namespace PR18152 {
};
template struct A<0>;
}
+
+template<typename T> void stmt_expr_1() {
+ static_assert( ({ false; }), "" );
+}
+void stmt_expr_2() {
+ static_assert( ({ false; }), "" ); // expected-error {{failed}}
+}
+
+namespace PR45083 {
+ struct A { bool x; };
+
+ template<typename> struct B : A {
+ void f() {
+ const int n = ({ if (x) {} 0; });
+ }
+ };
+
+ template void B<int>::f();
+
+ template<typename> void f() {
+ decltype(({})) x; // expected-error {{incomplete type}}
+ }
+ template void f<int>(); // expected-note {{instantiation of}}
+
+ template<typename> auto g() {
+ auto c = [](auto, int) -> decltype(({})) {};
+ using T = decltype(c(0.0, 0));
+ using T = void;
+ return c(0, 0);
+ }
+ using U = decltype(g<int>()); // expected-note {{previous}}
+ using U = float; // expected-error {{different types ('float' vs 'decltype(g<int>())' (aka 'void'))}}
+
+ void h(auto a, decltype(g<char>())*) {} // expected-note {{previous}}
+ void h(auto a, void*) {} // expected-error {{redefinition}}
+
+ void i(auto a) {
+ [](auto a, int = ({decltype(a) i; i * 2;})){}(a); // expected-error {{no matching function}} expected-note {{substitution failure}}
+ }
+ void use_i() {
+ i(0);
+ i((void*)0); // expected-note {{instantiation of}}
+ }
+}
+
+namespace BindingInStmtExpr {
+ template<class ...Ts> struct overload : Ts... {
+ overload(Ts ...ts) : Ts(decltype(ts)(ts))... {}
+ using Ts::operator()...;
+ };
+
+ template<int> struct N {};
+
+ template<class T> auto num_bindings() {
+ auto f0 = [](auto t, unsigned) { return N<0>(); };
+ auto f1 = [](auto t, int) -> decltype(({ auto [_1] = t; N<1>(); })) { return {}; };
+ auto f2 = [](auto t, int) -> decltype(({ auto [_1, _2] = t; N<2>(); })) { return {}; };
+ auto f3 = [](auto t, int) -> decltype(({ auto [_1, _2, _3] = t; N<3>(); })) { return {}; };
+ return decltype(overload(f0, f1, f2, f3)(T(), 0))();
+ }
+
+ struct T { int a; int b; };
+ // Make sure we get a correct, non-dependent type back.
+ using U = decltype(num_bindings<T>()); // expected-note {{previous}}
+ using U = N<3>; // expected-error-re {{type alias redefinition with different types ('N<3>' vs {{.*}}N<2>}}
+}
OpenPOWER on IntegriCloud