From 5eb63cfd035391ed4a1552e41fa613c341fd7465 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 12 Dec 2017 17:09:42 -0500 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 10 ++++++++++ gcc/cp/cp-tree.h | 12 +++++++++-- gcc/cp/decl.c | 17 ++++++++++++---- gcc/cp/pt.c | 30 +++++++++++----------------- gcc/testsuite/g++.dg/cpp0x/constexpr-self1.C | 5 +++++ 5 files changed, 50 insertions(+), 24 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4f1be5b..010f3f4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2017-12-12 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. + 2017-12-12 Alexandre Oliva * constexpr.c (check_constexpr_ctor_body_1): Skip begin stmt diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 708d172..05551df 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2449,7 +2449,8 @@ struct GTY(()) lang_decl_base { 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. */ @@ -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 \ = 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) \ @@ -6542,7 +6550,7 @@ extern bool type_dependent_object_expression_p (tree); extern bool any_type_dependent_arguments_p (const vec *); 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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 99b22dc..3601fa1 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2120,6 +2120,8 @@ next_arg:; 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)) @@ -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 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 @@ -6929,8 +6935,6 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, 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. */ @@ -6944,6 +6948,11 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, if (init) DECL_INITIAL (decl) = init; + if (dep_init) + { + retrofit_lang_decl (decl); + SET_DECL_DEPENDENT_INIT_P (decl, true); + } return; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 0cf6509..b5be980 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13135,6 +13135,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) 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. */ @@ -23922,7 +23925,7 @@ instantiation_dependent_scope_ref_p (tree t) 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; @@ -23956,28 +23959,19 @@ value_dependent_expression_p (tree expression, bool lval /* = 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; @@ -24013,7 +24007,7 @@ value_dependent_expression_p (tree expression, bool lval /* = 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: @@ -24047,7 +24041,7 @@ value_dependent_expression_p (tree expression, bool lval /* = false */) 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: @@ -24095,7 +24089,7 @@ value_dependent_expression_p (tree expression, bool lval /* = false */) 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)); } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-self1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-self1.C index 96f1d18..32a10af 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-self1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-self1.C @@ -12,3 +12,8 @@ struct B : A constexpr B b (&b.u); template < typename > void foo () { b; } + +template < typename T> void foo2 () { + constexpr B b2 = &b2.u; + b2; +} -- 2.7.4