* 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
+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>
* constexpr.c (check_constexpr_ctor_body_1): Skip begin stmt
unsigned u2sel : 1;
unsigned concept_p : 1; /* applies to vars and functions */
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. */
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.var_declared_inline_p \
= 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
declaration or one of VAR_DECLs for the user identifiers in it. */
#define DECL_DECOMPOSITION_P(NODE) \
extern bool any_type_dependent_arguments_p (const vec<tree, va_gc> *);
extern bool any_type_dependent_elements_p (const_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_uneval_expression_p (tree);
extern bool any_value_dependent_elements_p (const_tree);
DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
DECL_NONTRIVIALLY_INITIALIZED_P (newdecl)
|= 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 (olddecl);
if (DECL_CLASS_SCOPE_P (olddecl))
then it can be used in future constant expressions, so its value
must be available. */
+ bool dep_init = false;
+
if (!VAR_P (decl) || type_dependent_p)
/* 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
&& init_const_expr_p
&& TREE_CODE (type) != REFERENCE_TYPE
&& decl_maybe_constant_var_p (decl)
- && !type_dependent_init_p (init)
- && !value_dependent_init_p (init))
+ && !(dep_init = (type_dependent_init_p (init)
+ || value_dependent_init_p (init))))
{
/* This variable seems to be a non-dependent constant, so process
its initializer. If check_initializer returns non-null the
init = NULL_TREE;
release_tree_vector (cleanups);
}
- else if (!init && is_concept_var (decl))
- error ("variable concept has no initializer");
else if (!DECL_PRETTY_FUNCTION_P (decl))
{
/* Deduce array size even if the initializer is dependent. */
if (init)
DECL_INITIAL (decl) = init;
+ if (dep_init)
+ {
+ retrofit_lang_decl (decl);
+ SET_DECL_DEPENDENT_INIT_P (decl, true);
+ }
return;
}
DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0;
if (VAR_P (r))
{
+ if (DECL_LANG_SPECIFIC (r))
+ SET_DECL_DEPENDENT_INIT_P (r, false);
+
SET_DECL_MODE (r, VOIDmode);
/* Possibly limit visibility based on template args. */
can be tested for value dependence. */
bool
-value_dependent_expression_p (tree expression, bool lval /* = false */)
+value_dependent_expression_p (tree expression)
{
if (!processing_template_decl || expression == NULL_TREE)
return false;
/* A non-type template parm. */
if (DECL_TEMPLATE_PARM_P (expression))
return true;
- gcc_checking_assert (!lval);
return value_dependent_expression_p (DECL_INITIAL (expression));
case VAR_DECL:
/* A constant with literal type and is initialized
- with an expression that is value-dependent.
-
- Note that a non-dependent parenthesized initializer will have
- already been replaced with its constant value, so if we see
- 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))))
+ with an expression that is value-dependent. */
+ if (DECL_DEPENDENT_INIT_P (expression)
+ /* FIXME cp_finish_decl doesn't fold reference initializers. */
+ || TREE_CODE (TREE_TYPE (expression)) == REFERENCE_TYPE)
return true;
if (DECL_HAS_VALUE_EXPR_P (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 false;
if (TREE_CODE (expression) == TREE_LIST)
return any_value_dependent_elements_p (expression);
- return value_dependent_expression_p (expression, lval);
+ return value_dependent_expression_p (expression);
}
case SIZEOF_EXPR:
return instantiation_dependent_scope_ref_p (expression);
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)));
case NONTYPE_ARGUMENT_PACK:
case ADDR_EXPR:
{
tree op = TREE_OPERAND (expression, 0);
- return (value_dependent_expression_p (op, true)
+ return (value_dependent_expression_p (op)
|| has_value_dependent_address (op));
}
constexpr B b (&b.u);
template < typename > void foo () { b; }
+
+template < typename T> void foo2 () {
+ constexpr B b2 = &b2.u;
+ b2;
+}