Commit 5eb63cfd by Jason Merrill Committed by Jason Merrill

PR c++/82115 - ICE with variable initialized with its own address.

	* cp-tree.h (struct lang_decl_base): Add dependent_init_p.
	(DECL_DEPENDENT_INIT_P, SET_DECL_DEPENDENT_INIT_P): New.
	* decl.c (cp_finish_decl): Set it.
	(duplicate_decls): Copy it.
	* pt.c (tsubst_decl): Clear it.
	(value_dependent_expression_p): Revert earlier change.  Check it.

From-SVN: r255590
parent 331e2db3
2017-12-12 Jason Merrill <jason@redhat.com>
PR c++/82115 - ICE with variable initialized with its own address.
* cp-tree.h (struct lang_decl_base): Add dependent_init_p.
(DECL_DEPENDENT_INIT_P, SET_DECL_DEPENDENT_INIT_P): New.
* decl.c (cp_finish_decl): Set it.
(duplicate_decls): Copy it.
* pt.c (tsubst_decl): Clear it.
(value_dependent_expression_p): Revert earlier change. Check it.
2017-12-12 Alexandre Oliva <aoliva@redhat.com> 2017-12-12 Alexandre Oliva <aoliva@redhat.com>
* constexpr.c (check_constexpr_ctor_body_1): Skip begin stmt * constexpr.c (check_constexpr_ctor_body_1): Skip begin stmt
......
...@@ -2449,7 +2449,8 @@ struct GTY(()) lang_decl_base { ...@@ -2449,7 +2449,8 @@ struct GTY(()) lang_decl_base {
unsigned u2sel : 1; unsigned u2sel : 1;
unsigned concept_p : 1; /* applies to vars and functions */ unsigned concept_p : 1; /* applies to vars and functions */
unsigned var_declared_inline_p : 1; /* var */ unsigned var_declared_inline_p : 1; /* var */
/* 2 spare bits */ unsigned dependent_init_p : 1; /* var */
/* 1 spare bit */
}; };
/* True for DECL codes which have template info and access. */ /* True for DECL codes which have template info and access. */
...@@ -3879,6 +3880,13 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) ...@@ -3879,6 +3880,13 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.var_declared_inline_p \ (DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.var_declared_inline_p \
= true) = true)
/* True if NODE is a constant variable with a value-dependent initializer. */
#define DECL_DEPENDENT_INIT_P(NODE) \
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE)) \
&& DECL_LANG_SPECIFIC (NODE)->u.base.dependent_init_p)
#define SET_DECL_DEPENDENT_INIT_P(NODE, X) \
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.dependent_init_p = (X))
/* Nonzero if NODE is an artificial VAR_DECL for a C++17 structured binding /* Nonzero if NODE is an artificial VAR_DECL for a C++17 structured binding
declaration or one of VAR_DECLs for the user identifiers in it. */ declaration or one of VAR_DECLs for the user identifiers in it. */
#define DECL_DECOMPOSITION_P(NODE) \ #define DECL_DECOMPOSITION_P(NODE) \
...@@ -6542,7 +6550,7 @@ extern bool type_dependent_object_expression_p (tree); ...@@ -6542,7 +6550,7 @@ extern bool type_dependent_object_expression_p (tree);
extern bool any_type_dependent_arguments_p (const vec<tree, va_gc> *); extern bool any_type_dependent_arguments_p (const vec<tree, va_gc> *);
extern bool any_type_dependent_elements_p (const_tree); extern bool any_type_dependent_elements_p (const_tree);
extern bool type_dependent_expression_p_push (tree); extern bool type_dependent_expression_p_push (tree);
extern bool value_dependent_expression_p (tree, bool = false); extern bool value_dependent_expression_p (tree);
extern bool instantiation_dependent_expression_p (tree); extern bool instantiation_dependent_expression_p (tree);
extern bool instantiation_dependent_uneval_expression_p (tree); extern bool instantiation_dependent_uneval_expression_p (tree);
extern bool any_value_dependent_elements_p (const_tree); extern bool any_value_dependent_elements_p (const_tree);
......
...@@ -2120,6 +2120,8 @@ next_arg:; ...@@ -2120,6 +2120,8 @@ next_arg:;
DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl); DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
DECL_NONTRIVIALLY_INITIALIZED_P (newdecl) DECL_NONTRIVIALLY_INITIALIZED_P (newdecl)
|= DECL_NONTRIVIALLY_INITIALIZED_P (olddecl); |= DECL_NONTRIVIALLY_INITIALIZED_P (olddecl);
if (DECL_DEPENDENT_INIT_P (olddecl))
SET_DECL_DEPENDENT_INIT_P (newdecl, true);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl) DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl)
|= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl); |= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl);
if (DECL_CLASS_SCOPE_P (olddecl)) if (DECL_CLASS_SCOPE_P (olddecl))
...@@ -6910,14 +6912,18 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, ...@@ -6910,14 +6912,18 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
then it can be used in future constant expressions, so its value then it can be used in future constant expressions, so its value
must be available. */ must be available. */
bool dep_init = false;
if (!VAR_P (decl) || type_dependent_p) if (!VAR_P (decl) || type_dependent_p)
/* We can't do anything if the decl has dependent type. */; /* We can't do anything if the decl has dependent type. */;
else if (!init && is_concept_var (decl))
error ("variable concept has no initializer");
else if (init else if (init
&& init_const_expr_p && init_const_expr_p
&& TREE_CODE (type) != REFERENCE_TYPE && TREE_CODE (type) != REFERENCE_TYPE
&& decl_maybe_constant_var_p (decl) && decl_maybe_constant_var_p (decl)
&& !type_dependent_init_p (init) && !(dep_init = (type_dependent_init_p (init)
&& !value_dependent_init_p (init)) || value_dependent_init_p (init))))
{ {
/* This variable seems to be a non-dependent constant, so process /* This variable seems to be a non-dependent constant, so process
its initializer. If check_initializer returns non-null the its initializer. If check_initializer returns non-null the
...@@ -6929,8 +6935,6 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, ...@@ -6929,8 +6935,6 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
init = NULL_TREE; init = NULL_TREE;
release_tree_vector (cleanups); release_tree_vector (cleanups);
} }
else if (!init && is_concept_var (decl))
error ("variable concept has no initializer");
else if (!DECL_PRETTY_FUNCTION_P (decl)) else if (!DECL_PRETTY_FUNCTION_P (decl))
{ {
/* Deduce array size even if the initializer is dependent. */ /* Deduce array size even if the initializer is dependent. */
...@@ -6944,6 +6948,11 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, ...@@ -6944,6 +6948,11 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
if (init) if (init)
DECL_INITIAL (decl) = init; DECL_INITIAL (decl) = init;
if (dep_init)
{
retrofit_lang_decl (decl);
SET_DECL_DEPENDENT_INIT_P (decl, true);
}
return; return;
} }
......
...@@ -13135,6 +13135,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -13135,6 +13135,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0; DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0;
if (VAR_P (r)) if (VAR_P (r))
{ {
if (DECL_LANG_SPECIFIC (r))
SET_DECL_DEPENDENT_INIT_P (r, false);
SET_DECL_MODE (r, VOIDmode); SET_DECL_MODE (r, VOIDmode);
/* Possibly limit visibility based on template args. */ /* Possibly limit visibility based on template args. */
...@@ -23922,7 +23925,7 @@ instantiation_dependent_scope_ref_p (tree t) ...@@ -23922,7 +23925,7 @@ instantiation_dependent_scope_ref_p (tree t)
can be tested for value dependence. */ can be tested for value dependence. */
bool bool
value_dependent_expression_p (tree expression, bool lval /* = false */) value_dependent_expression_p (tree expression)
{ {
if (!processing_template_decl || expression == NULL_TREE) if (!processing_template_decl || expression == NULL_TREE)
return false; return false;
...@@ -23956,28 +23959,19 @@ value_dependent_expression_p (tree expression, bool lval /* = false */) ...@@ -23956,28 +23959,19 @@ value_dependent_expression_p (tree expression, bool lval /* = false */)
/* A non-type template parm. */ /* A non-type template parm. */
if (DECL_TEMPLATE_PARM_P (expression)) if (DECL_TEMPLATE_PARM_P (expression))
return true; return true;
gcc_checking_assert (!lval);
return value_dependent_expression_p (DECL_INITIAL (expression)); return value_dependent_expression_p (DECL_INITIAL (expression));
case VAR_DECL: case VAR_DECL:
/* A constant with literal type and is initialized /* A constant with literal type and is initialized
with an expression that is value-dependent. with an expression that is value-dependent. */
if (DECL_DEPENDENT_INIT_P (expression)
Note that a non-dependent parenthesized initializer will have /* FIXME cp_finish_decl doesn't fold reference initializers. */
already been replaced with its constant value, so if we see || TREE_CODE (TREE_TYPE (expression)) == REFERENCE_TYPE)
a TREE_LIST it must be dependent. */
if (!lval
&& DECL_INITIAL (expression)
&& decl_constant_var_p (expression)
&& (TREE_CODE (DECL_INITIAL (expression)) == TREE_LIST
/* cp_finish_decl doesn't fold reference initializers. */
|| TREE_CODE (TREE_TYPE (expression)) == REFERENCE_TYPE
|| value_dependent_expression_p (DECL_INITIAL (expression))))
return true; return true;
if (DECL_HAS_VALUE_EXPR_P (expression)) if (DECL_HAS_VALUE_EXPR_P (expression))
{ {
tree value_expr = DECL_VALUE_EXPR (expression); tree value_expr = DECL_VALUE_EXPR (expression);
if (value_dependent_expression_p (value_expr, lval)) if (value_dependent_expression_p (value_expr))
return true; return true;
} }
return false; return false;
...@@ -24013,7 +24007,7 @@ value_dependent_expression_p (tree expression, bool lval /* = false */) ...@@ -24013,7 +24007,7 @@ value_dependent_expression_p (tree expression, bool lval /* = false */)
if (TREE_CODE (expression) == TREE_LIST) if (TREE_CODE (expression) == TREE_LIST)
return any_value_dependent_elements_p (expression); return any_value_dependent_elements_p (expression);
return value_dependent_expression_p (expression, lval); return value_dependent_expression_p (expression);
} }
case SIZEOF_EXPR: case SIZEOF_EXPR:
...@@ -24047,7 +24041,7 @@ value_dependent_expression_p (tree expression, bool lval /* = false */) ...@@ -24047,7 +24041,7 @@ value_dependent_expression_p (tree expression, bool lval /* = false */)
return instantiation_dependent_scope_ref_p (expression); return instantiation_dependent_scope_ref_p (expression);
case COMPONENT_REF: case COMPONENT_REF:
return (value_dependent_expression_p (TREE_OPERAND (expression, 0), lval) return (value_dependent_expression_p (TREE_OPERAND (expression, 0))
|| value_dependent_expression_p (TREE_OPERAND (expression, 1))); || value_dependent_expression_p (TREE_OPERAND (expression, 1)));
case NONTYPE_ARGUMENT_PACK: case NONTYPE_ARGUMENT_PACK:
...@@ -24095,7 +24089,7 @@ value_dependent_expression_p (tree expression, bool lval /* = false */) ...@@ -24095,7 +24089,7 @@ value_dependent_expression_p (tree expression, bool lval /* = false */)
case ADDR_EXPR: case ADDR_EXPR:
{ {
tree op = TREE_OPERAND (expression, 0); tree op = TREE_OPERAND (expression, 0);
return (value_dependent_expression_p (op, true) return (value_dependent_expression_p (op)
|| has_value_dependent_address (op)); || has_value_dependent_address (op));
} }
......
...@@ -12,3 +12,8 @@ struct B : A ...@@ -12,3 +12,8 @@ struct B : A
constexpr B b (&b.u); constexpr B b (&b.u);
template < typename > void foo () { b; } template < typename > void foo () { b; }
template < typename T> void foo2 () {
constexpr B b2 = &b2.u;
b2;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment