}
if (TREE_CODE (t) == CONVERT_EXPR)
t = TREE_OPERAND (t, 0);
- if (TREE_CODE (t) == INIT_EXPR
- /* vptr initialization shows up as a MODIFY_EXPR. In C++14 we only
- use what this function builds for cx_check_missing_mem_inits, and
- assignment in the ctor body doesn't count. */
- || (cxx_dialect < cxx14 && TREE_CODE (t) == MODIFY_EXPR))
+ if (TREE_CODE (t) == INIT_EXPR)
{
member = TREE_OPERAND (t, 0);
init = break_out_target_exprs (TREE_OPERAND (t, 1));
else if (list != last
&& !check_constexpr_ctor_body_1 (last, list))
ok = false;
- if (!ok)
+ if (!ok && complain)
{
- if (complain)
- error ("%<constexpr%> constructor does not have empty body");
- DECL_DECLARED_CONSTEXPR_P (current_function_decl) = false;
+ pedwarn (input_location, OPT_Wc__14_extensions,
+ "%<constexpr%> constructor does not have empty body");
+ ok = true;
}
return ok;
}
--- /dev/null
+// Verify we diagnose and accept, as an extension, a non-empty constexpr
+// constructor body in C++11 mode.
+// PR c++/123845
+// { dg-do compile { target c++11_only } }
+// { dg-options "" }
+
+constexpr int negate(int n) { return -n; }
+
+struct A {
+ int m;
+ constexpr A() : m(42) {
+ ++m;
+ m = negate(m);
+ } // { dg-warning "does not have empty body \[-Wc++14-extensions\]" }
+};
+static_assert(A().m == -43, "");
+
+template<class T>
+struct B {
+ int m;
+ constexpr B() : m(42) {
+ ++m;
+ m = negate(m);
+ } // { dg-warning "does not have empty body \[-Wc++14-extensions\]" }
+};
+static_assert(B<int>().m == -43, "");
struct A
{
int i;
- constexpr A(int _i) { i = _i; } // { dg-error "empty body|A::i" "" { target c++17_down } }
+ constexpr A(int _i) { i = _i; } // { dg-warning "empty body" "" { target c++11_only } }
+ // { dg-error "'A::i' must be init" "" { target c++17_down } .-1 }
};
template <class T>
} catch (int) { // { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } }
} // { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } .-2 }
} catch (...) { // { dg-error "'constexpr' constructor does not have empty body" "" { target c++11_only } }
+ // { dg-error "compound-statement in 'constexpr' function" "" { target c++11_only } .-1 }
}
int m;
};
try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
} catch (int) { // { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } }
} // { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } .-2 }
- } catch (...) { // { dg-error "'constexpr' constructor does not have empty body" "" { target c++11_only } }
+ } catch (...) { // { dg-warning "'constexpr' constructor does not have empty body" "" { target c++11_only } }
+ // { dg-warning "compound-statement in 'constexpr' function" "" { target c++11_only } .-1 }
}
int m;
};
try { // { dg-warning "'try' in 'constexpr' function only available with" "" { target c++17_down } }
} catch (int) {
}
- } catch (...) { // { dg-error "'constexpr' constructor does not have empty body" "" { target c++11_only } }
+ } catch (...) { // { dg-warning "'constexpr' constructor does not have empty body" "" { target c++11_only } }
}
int m;
};