+2019-03-26 Jason Merrill <jason@redhat.com>
+
+ PR c++/86429 - constexpr variable in lambda.
+ PR c++/82643
+ PR c++/87327
+ * constexpr.c (cxx_eval_constant_expression): In a lambda function,
+ try evaluating the captured variable directly.
+
2019-03-26 Jakub Jelinek <jakub@redhat.com>
PR c++/89796
case VAR_DECL:
if (DECL_HAS_VALUE_EXPR_P (t))
- return cxx_eval_constant_expression (ctx, DECL_VALUE_EXPR (t),
- lval, non_constant_p, overflow_p);
+ {
+ if (is_normal_capture_proxy (t)
+ && current_function_decl == DECL_CONTEXT (t))
+ {
+ /* Function parms aren't constexpr within the function
+ definition, so don't try to look at the closure. But if the
+ captured variable is constant, try to evaluate it directly. */
+ r = DECL_CAPTURED_VARIABLE (t);
+ tree type = TREE_TYPE (t);
+ if (TYPE_REF_P (type) != TYPE_REF_P (TREE_TYPE (r)))
+ {
+ /* Adjust r to match the reference-ness of t. */
+ if (TYPE_REF_P (type))
+ r = build_address (r);
+ else
+ r = convert_from_reference (r);
+ }
+ }
+ else
+ r = DECL_VALUE_EXPR (t);
+ return cxx_eval_constant_expression (ctx, r, lval, non_constant_p,
+ overflow_p);
+ }
/* fall through */
case CONST_DECL:
/* We used to not check lval for CONST_DECL, but darwin.c uses
--- /dev/null
+// PR c++/82643
+// { dg-do compile { target c++14 } }
+
+int main()
+{
+ struct A {
+ constexpr int operator()() const { return 42; }
+ };
+
+ auto f = A();
+ constexpr auto x = f(); //ok, call constexpr const non-static method
+
+ [](auto const &f) {
+ constexpr auto x = f(); /*ok*/
+ }(f);
+
+ [&]() {
+ constexpr auto x = f(); //ko, __closure is not a constant expression
+ };
+
+ [=]() {
+ constexpr auto x = f(); //same ko, __closure is not a constant expression
+ };
+}
--- /dev/null
+// PR c++/86429
+// { dg-do compile { target c++14 } }
+
+struct A
+{
+ int i;
+ constexpr int f(const int&) const { return i; }
+};
+
+void g()
+{
+ constexpr A a = { 42 };
+ [&](auto x) {
+ constexpr auto y = a.f(x);
+ }(24);
+}
--- /dev/null
+// PR c++/87327
+// { dg-do compile { target c++17 } }
+
+template <int N>
+struct Foo {
+ constexpr auto size() const {
+ return N;
+ }
+};
+
+constexpr int foo() {
+ constexpr auto a = Foo<5>{};
+
+ [&] {
+ Foo<a.size()> it = {};
+
+ return it;
+ }();
+
+ return 42;
+}
+
+constexpr int i = foo();