Skip to content

Commit

Permalink
PR c++/68949
Browse files Browse the repository at this point in the history
	* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@232848 138bc75d-0d04-0410-961f-82ee72b054a4
  • Loading branch information
jason committed Jan 26, 2016
1 parent 58b0f9c commit 6a38515
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 17 deletions.
9 changes: 9 additions & 0 deletions gcc/cp/ChangeLog
Original file line number Diff line number Diff line change
@@ -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
Expand Down
19 changes: 5 additions & 14 deletions gcc/cp/constexpr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -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;

Expand Down
2 changes: 2 additions & 0 deletions gcc/cp/optimize.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 2 additions & 3 deletions gcc/cp/semantics.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
29 changes: 29 additions & 0 deletions gcc/testsuite/g++.dg/cpp0x/constexpr-array15.C
Original file line number Diff line number Diff line change
@@ -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();
}

0 comments on commit 6a38515

Please sign in to comment.