From d1a902a2d56e27596f092189adee184da69ad3ea Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 30 May 2014 11:09:40 -0400 Subject: [PATCH] re PR c++/60992 (ICE in tsubst_copy, at cp/pt.c:12637) PR c++/60992 * pt.c (tsubst_init): Split out from... (tsubst_expr) [DECL_EXPR]: Here. (tsubst_copy) [VAR_DECL]: Use it. * semantics.c (finish_id_expression): Return the decl for static/const. From-SVN: r211084 --- gcc/cp/ChangeLog | 8 +++++ gcc/cp/pt.c | 81 +++++++++++++++++++++++++++++++++------------- gcc/cp/semantics.c | 15 +++------ 3 files changed, 71 insertions(+), 33 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index dbcd3c6ddf8..b3138014f44 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2014-05-30 Jason Merrill + + PR c++/60992 + * pt.c (tsubst_init): Split out from... + (tsubst_expr) [DECL_EXPR]: Here. + (tsubst_copy) [VAR_DECL]: Use it. + * semantics.c (finish_id_expression): Return the decl for static/const. + 2014-05-28 Jason Merrill PR c++/47202 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 0b3cd7f4e51..a24e0443c9f 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -12513,6 +12513,37 @@ tsubst_qualified_id (tree qualified_id, tree args, return expr; } +/* tsubst the initializer for a VAR_DECL. INIT is the unsubstituted + initializer, DECL is the substituted VAR_DECL. Other arguments are as + for tsubst. */ + +static tree +tsubst_init (tree init, tree decl, tree args, + tsubst_flags_t complain, tree in_decl) +{ + if (!init) + return NULL_TREE; + + init = tsubst_expr (init, args, complain, in_decl, false); + + if (!init) + { + /* If we had an initializer but it + instantiated to nothing, + value-initialize the object. This will + only occur when the initializer was a + pack expansion where the parameter packs + used in that expansion were of length + zero. */ + init = build_value_init (TREE_TYPE (decl), + complain); + if (TREE_CODE (init) == AGGR_INIT_EXPR) + init = get_target_expr_sfinae (init, complain); + } + + return init; +} + /* Like tsubst, but deals with expressions. This function just replaces template parms; to finish processing the resultant expression, use tsubst_copy_and_build or tsubst_expr. */ @@ -12670,11 +12701,34 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) local static or constant. Building a new VAR_DECL should be OK in all those cases. */ r = tsubst_decl (t, args, complain); - if (decl_constant_var_p (r)) - /* A use of a local constant must decay to its value. */ - return integral_constant_value (r); + if (decl_maybe_constant_var_p (r)) + { + /* We can't call cp_finish_decl, so handle the + initializer by hand. */ + tree init = tsubst_init (DECL_INITIAL (t), r, args, + complain, in_decl); + if (!processing_template_decl) + init = maybe_constant_init (init); + if (processing_template_decl + ? potential_constant_expression (init) + : reduced_constant_expression_p (init)) + DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r) + = TREE_CONSTANT (r) = true; + DECL_INITIAL (r) = init; + } gcc_assert (cp_unevaluated_operand || TREE_STATIC (r) + || decl_constant_var_p (r) || errorcount || sorrycount); + if (!processing_template_decl) + { + if (TREE_STATIC (r)) + rest_of_decl_compilation (r, toplevel_bindings_p (), + at_eof); + else if (decl_constant_var_p (r)) + /* A use of a local constant decays to its value. + FIXME update for core DR 696. */ + return integral_constant_value (r); + } return r; } } @@ -13544,26 +13598,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, init = cp_fname_init (name, &TREE_TYPE (decl)); } else - { - tree t = RECUR (init); - - if (init && !t) - { - /* If we had an initializer but it - instantiated to nothing, - value-initialize the object. This will - only occur when the initializer was a - pack expansion where the parameter packs - used in that expansion were of length - zero. */ - init = build_value_init (TREE_TYPE (decl), - complain); - if (TREE_CODE (init) == AGGR_INIT_EXPR) - init = get_target_expr_sfinae (init, complain); - } - else - init = t; - } + init = tsubst_init (init, decl, args, complain, in_decl); if (VAR_P (decl)) const_init = (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index edab3309b36..396a893bd57 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3166,12 +3166,7 @@ finish_id_expression (tree id_expression, else if (TREE_STATIC (decl) /* It's not a use (3.2) if we're in an unevaluated context. */ || cp_unevaluated_operand) - { - if (processing_template_decl) - /* For a use of an outer static/unevaluated var, return the id - so that we'll look it up again in the instantiation. */ - return id_expression; - } + /* OK */; else { tree context = DECL_CONTEXT (decl); @@ -3190,13 +3185,13 @@ finish_id_expression (tree id_expression, the complexity of the problem" FIXME update for final resolution of core issue 696. */ - if (decl_constant_var_p (decl)) + if (decl_maybe_constant_var_p (decl)) { if (processing_template_decl) /* In a template, the constant value may not be in a usable - form, so look it up again at instantiation time. */ - return id_expression; - else + form, so wait until instantiation time. */ + return decl; + else if (decl_constant_var_p (decl)) return integral_constant_value (decl); } -- 2.30.2