Expand PTRMEM_CST only when necessary.
* constexpr.c (cxx_eval_constant_expression): Expand PTRMEM_CST only when necessary. (cxx_eval_component_reference): Like here. * decl2.c (lower_var_init): And here. (c_parse_final_cleanups): Call it. * typeck2.c (digest_init_r): Not here. * decl.c (complete_vars): Or here. (cp_finish_decl): Add local statics to symbol table. From-SVN: r229018
This commit is contained in:
parent
13b380a325
commit
dcdbc004d5
|
@ -1,3 +1,14 @@
|
|||
2015-10-19 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* constexpr.c (cxx_eval_constant_expression): Expand PTRMEM_CST
|
||||
only when necessary.
|
||||
(cxx_eval_component_reference): Like here.
|
||||
* decl2.c (lower_var_init): And here.
|
||||
(c_parse_final_cleanups): Call it.
|
||||
* typeck2.c (digest_init_r): Not here.
|
||||
* decl.c (complete_vars): Or here.
|
||||
(cp_finish_decl): Add local statics to symbol table.
|
||||
|
||||
2015-10-17 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/68006
|
||||
|
|
|
@ -1863,6 +1863,8 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t,
|
|||
tree whole = cxx_eval_constant_expression (ctx, orig_whole,
|
||||
lval,
|
||||
non_constant_p, overflow_p);
|
||||
if (TREE_CODE (whole) == PTRMEM_CST)
|
||||
whole = cplus_expand_constant (whole);
|
||||
if (whole == orig_whole)
|
||||
return t;
|
||||
if (lval)
|
||||
|
@ -3129,9 +3131,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
|||
}
|
||||
if (CONSTANT_CLASS_P (t))
|
||||
{
|
||||
if (TREE_CODE (t) == PTRMEM_CST)
|
||||
t = cplus_expand_constant (t);
|
||||
else if (TREE_OVERFLOW (t) && (!flag_permissive || ctx->quiet))
|
||||
if (TREE_OVERFLOW (t) && (!flag_permissive || ctx->quiet))
|
||||
*overflow_p = true;
|
||||
return t;
|
||||
}
|
||||
|
@ -3545,7 +3545,11 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
|||
non_constant_p, overflow_p);
|
||||
if (*non_constant_p)
|
||||
return t;
|
||||
if (POINTER_TYPE_P (TREE_TYPE (t))
|
||||
tree type = TREE_TYPE (t);
|
||||
if (TREE_CODE (op) == PTRMEM_CST
|
||||
&& !TYPE_PTRMEM_P (type))
|
||||
op = cplus_expand_constant (op);
|
||||
if (POINTER_TYPE_P (type)
|
||||
&& TREE_CODE (op) == INTEGER_CST
|
||||
&& !integer_zerop (op))
|
||||
{
|
||||
|
@ -3559,7 +3563,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
|||
/* We didn't fold at the top so we could check for ptr-int
|
||||
conversion. */
|
||||
return fold (t);
|
||||
r = fold_build1 (TREE_CODE (t), TREE_TYPE (t), op);
|
||||
r = fold_build1 (TREE_CODE (t), type, op);
|
||||
/* Conversion of an out-of-range value has implementation-defined
|
||||
behavior; the language considers it different from arithmetic
|
||||
overflow, which is undefined. */
|
||||
|
|
|
@ -6714,6 +6714,9 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
|
|||
to put statics on the list so we can deal with the label
|
||||
address extension. FIXME. */
|
||||
add_local_decl (cfun, decl);
|
||||
/* And make sure it's in the symbol table for
|
||||
c_parse_final_cleanups to find. */
|
||||
varpool_node::get_create (decl);
|
||||
}
|
||||
|
||||
/* Convert the initializer to the type of DECL, if we have not
|
||||
|
@ -14887,10 +14890,6 @@ complete_vars (tree type)
|
|||
cp_apply_type_quals_to_decl (cp_type_quals (type), var);
|
||||
}
|
||||
|
||||
if (DECL_INITIAL (var)
|
||||
&& decl_constant_var_p (var))
|
||||
DECL_INITIAL (var) = cplus_expand_constant (DECL_INITIAL (var));
|
||||
|
||||
/* Remove this entry from the list. */
|
||||
incomplete_vars->unordered_remove (ix);
|
||||
}
|
||||
|
|
|
@ -4484,6 +4484,22 @@ maybe_warn_sized_delete ()
|
|||
maybe_warn_sized_delete (VEC_DELETE_EXPR);
|
||||
}
|
||||
|
||||
/* Earlier we left PTRMEM_CST in variable initializers alone so that we could
|
||||
look them up when evaluating non-type template parameters. Now we need to
|
||||
lower them to something the back end can understand. */
|
||||
|
||||
static void
|
||||
lower_var_init ()
|
||||
{
|
||||
varpool_node *node;
|
||||
FOR_EACH_VARIABLE (node)
|
||||
{
|
||||
tree d = node->decl;
|
||||
if (tree init = DECL_INITIAL (d))
|
||||
DECL_INITIAL (d) = cplus_expand_constant (init);
|
||||
}
|
||||
}
|
||||
|
||||
/* This routine is called at the end of compilation.
|
||||
Its job is to create all the code needed to initialize and
|
||||
destroy the global aggregates. We do the destruction
|
||||
|
@ -4793,6 +4809,8 @@ c_parse_final_cleanups (void)
|
|||
}
|
||||
while (reconsider);
|
||||
|
||||
lower_var_init ();
|
||||
|
||||
generate_mangling_aliases ();
|
||||
|
||||
/* All used inline functions must have a definition at this point. */
|
||||
|
|
|
@ -1059,22 +1059,11 @@ digest_init_r (tree type, tree init, bool nested, int flags,
|
|||
|| BRACE_ENCLOSED_INITIALIZER_P (init))
|
||||
&& (SCALAR_TYPE_P (type) || code == REFERENCE_TYPE))
|
||||
{
|
||||
tree *exp;
|
||||
|
||||
if (nested)
|
||||
flags |= LOOKUP_NO_NARROWING;
|
||||
init = convert_for_initialization (0, type, init, flags,
|
||||
ICR_INIT, NULL_TREE, 0,
|
||||
complain);
|
||||
exp = &init;
|
||||
|
||||
/* Skip any conversions since we'll be outputting the underlying
|
||||
constant. */
|
||||
while (CONVERT_EXPR_P (*exp)
|
||||
|| TREE_CODE (*exp) == NON_LVALUE_EXPR)
|
||||
exp = &TREE_OPERAND (*exp, 0);
|
||||
|
||||
*exp = cplus_expand_constant (*exp);
|
||||
|
||||
return init;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue