aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2014-05-30 15:09:40 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2014-05-30 15:09:40 +0000
commit4b6067c6a1dba36396e8f08a82415830bd528975 (patch)
tree1b58c907a8d9915d5c59be98bbf9e8aaebb3902f
parenta33fe80e4ac03b7761ba3a6e027db4270743c73a (diff)
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@211084 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/pt.c81
-rw-r--r--gcc/cp/semantics.c15
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 <jason@redhat.com>
+
+ 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 <jason@redhat.com>
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);
}