mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-28 22:11:21 +08:00
re PR c++/68949 (Implicit initialization of array member silently miscompiling.)
PR c++/68949 * constexpr.c (register_constexpr_fundef): Keep the un-massaged body. (cxx_eval_call_expression): Don't look through clones. * optimize.c (maybe_clone_body): Clear DECL_SAVED_TREE of the alias. * semantics.c (expand_or_defer_fn_1): Keep DECL_SAVED_TREE of maybe-in-charge *tor. From-SVN: r232848
This commit is contained in:
parent
2d63bc398f
commit
ca30abcd13
@ -1,3 +1,12 @@
|
||||
2016-01-26 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/68949
|
||||
* constexpr.c (register_constexpr_fundef): Keep the un-massaged body.
|
||||
(cxx_eval_call_expression): Don't look through clones.
|
||||
* optimize.c (maybe_clone_body): Clear DECL_SAVED_TREE of the alias.
|
||||
* semantics.c (expand_or_defer_fn_1): Keep DECL_SAVED_TREE of
|
||||
maybe-in-charge *tor.
|
||||
|
||||
2016-01-26 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/68782
|
||||
|
@ -769,23 +769,23 @@ register_constexpr_fundef (tree fun, tree body)
|
||||
if (!is_valid_constexpr_fn (fun, !DECL_GENERATED_P (fun)))
|
||||
return NULL;
|
||||
|
||||
body = massage_constexpr_body (fun, body);
|
||||
if (body == NULL_TREE || body == error_mark_node)
|
||||
tree massaged = massage_constexpr_body (fun, body);
|
||||
if (massaged == NULL_TREE || massaged == error_mark_node)
|
||||
{
|
||||
if (!DECL_CONSTRUCTOR_P (fun))
|
||||
error ("body of constexpr function %qD not a return-statement", fun);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!potential_rvalue_constant_expression (body))
|
||||
if (!potential_rvalue_constant_expression (massaged))
|
||||
{
|
||||
if (!DECL_GENERATED_P (fun))
|
||||
require_potential_rvalue_constant_expression (body);
|
||||
require_potential_rvalue_constant_expression (massaged);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (DECL_CONSTRUCTOR_P (fun)
|
||||
&& cx_check_missing_mem_inits (fun, body, !DECL_GENERATED_P (fun)))
|
||||
&& cx_check_missing_mem_inits (fun, massaged, !DECL_GENERATED_P (fun)))
|
||||
return NULL;
|
||||
|
||||
/* Create the constexpr function table if necessary. */
|
||||
@ -1340,15 +1340,6 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
|
||||
{
|
||||
if (!result || result == error_mark_node)
|
||||
{
|
||||
if (DECL_SAVED_TREE (fun) == NULL_TREE
|
||||
&& (DECL_CONSTRUCTOR_P (fun) || DECL_DESTRUCTOR_P (fun)))
|
||||
/* The maybe-in-charge 'tor had its DECL_SAVED_TREE
|
||||
cleared, try a clone. */
|
||||
for (fun = DECL_CHAIN (fun);
|
||||
fun && DECL_CLONED_FUNCTION_P (fun);
|
||||
fun = DECL_CHAIN (fun))
|
||||
if (DECL_SAVED_TREE (fun))
|
||||
break;
|
||||
gcc_assert (DECL_SAVED_TREE (fun));
|
||||
tree parms, res;
|
||||
|
||||
|
@ -646,6 +646,8 @@ maybe_clone_body (tree fn)
|
||||
{
|
||||
if (expand_or_defer_fn_1 (clone))
|
||||
emit_associated_thunks (clone);
|
||||
/* We didn't generate a body, so remove the empty one. */
|
||||
DECL_SAVED_TREE (clone) = NULL_TREE;
|
||||
}
|
||||
else
|
||||
expand_or_defer_fn (clone);
|
||||
|
@ -4163,9 +4163,8 @@ expand_or_defer_fn_1 (tree fn)
|
||||
/* We don't want to process FN again, so pretend we've written
|
||||
it out, even though we haven't. */
|
||||
TREE_ASM_WRITTEN (fn) = 1;
|
||||
/* If this is an instantiation of a constexpr function, keep
|
||||
DECL_SAVED_TREE for explain_invalid_constexpr_fn. */
|
||||
if (!is_instantiation_of_constexpr (fn))
|
||||
/* If this is a constexpr function, keep DECL_SAVED_TREE. */
|
||||
if (!DECL_DECLARED_CONSTEXPR_P (fn))
|
||||
DECL_SAVED_TREE (fn) = NULL_TREE;
|
||||
return false;
|
||||
}
|
||||
|
29
gcc/testsuite/g++.dg/cpp0x/constexpr-array15.C
Normal file
29
gcc/testsuite/g++.dg/cpp0x/constexpr-array15.C
Normal file
@ -0,0 +1,29 @@
|
||||
// PR c++/68949
|
||||
// { dg-do run { target c++11 } }
|
||||
|
||||
struct Sub {
|
||||
int i;
|
||||
|
||||
constexpr Sub() : i(-1) {} // remove constexpr and it works as expected
|
||||
Sub(Sub&& rhs); // remove this constructor and it works as epxected.
|
||||
};
|
||||
|
||||
// v-- move this inline and it works as expected
|
||||
// v-- remove ': Sub()' and it works as expected
|
||||
Sub::Sub(Sub&& rhs) : Sub() { int tmp = i; i = rhs.i; rhs.i = tmp; }
|
||||
|
||||
struct Class {
|
||||
// v-- remove '[1]' and it works as expected
|
||||
// v-- add '= {}' and it works as expected
|
||||
Sub s[1];
|
||||
|
||||
// v-- add ': s{}' and it works as expected
|
||||
// v-- removing this constructor makes it work as expected
|
||||
Class() {}
|
||||
};
|
||||
|
||||
int main() {
|
||||
Class c;
|
||||
if (c.s[0].i != -1)
|
||||
__builtin_abort();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user