clear_fold_cache ();
}
+/* Internal function handling expressions in templates for
+ fold_non_dependent_expr and fold_non_dependent_init.
+
+ If we're in a template, but T isn't value dependent, simplify
+ it. We're supposed to treat:
+
+ template <typename T> void f(T[1 + 1]);
+ template <typename T> void f(T[2]);
+
+ as two declarations of the same function, for example. */
+
+static tree
+fold_non_dependent_expr_template (tree t, tsubst_flags_t complain,
+ bool manifestly_const_eval)
+{
+ gcc_assert (processing_template_decl);
+
+ if (is_nondependent_constant_expression (t))
+ {
+ processing_template_decl_sentinel s;
+ t = instantiate_non_dependent_expr_internal (t, complain);
+
+ if (type_unknown_p (t) || BRACE_ENCLOSED_INITIALIZER_P (t))
+ {
+ if (TREE_OVERFLOW_P (t))
+ {
+ t = build_nop (TREE_TYPE (t), t);
+ TREE_CONSTANT (t) = false;
+ }
+ return t;
+ }
+
+ tree r = cxx_eval_outermost_constant_expr (t, true, true,
+ manifestly_const_eval,
+ NULL_TREE);
+ /* cp_tree_equal looks through NOPs, so allow them. */
+ gcc_checking_assert (r == t
+ || CONVERT_EXPR_P (t)
+ || TREE_CODE (t) == VIEW_CONVERT_EXPR
+ || (TREE_CONSTANT (t) && !TREE_CONSTANT (r))
+ || !cp_tree_equal (r, t));
+ return r;
+ }
+ else if (TREE_OVERFLOW_P (t))
+ {
+ t = build_nop (TREE_TYPE (t), t);
+ TREE_CONSTANT (t) = false;
+ }
+
+ return t;
+}
+
/* Like maybe_constant_value but first fully instantiate the argument.
Note: this is equivalent to instantiate_non_dependent_expr_sfinae
if (t == NULL_TREE)
return NULL_TREE;
- /* If we're in a template, but T isn't value dependent, simplify
- it. We're supposed to treat:
+ if (processing_template_decl)
+ return fold_non_dependent_expr_template (t, complain,
+ manifestly_const_eval);
- template <typename T> void f(T[1 + 1]);
- template <typename T> void f(T[2]);
+ return maybe_constant_value (t, NULL_TREE, manifestly_const_eval);
+}
- as two declarations of the same function, for example. */
- if (processing_template_decl)
- {
- if (is_nondependent_constant_expression (t))
- {
- processing_template_decl_sentinel s;
- t = instantiate_non_dependent_expr_internal (t, complain);
- if (type_unknown_p (t)
- || BRACE_ENCLOSED_INITIALIZER_P (t))
- {
- if (TREE_OVERFLOW_P (t))
- {
- t = build_nop (TREE_TYPE (t), t);
- TREE_CONSTANT (t) = false;
- }
- return t;
- }
+/* Like maybe_constant_init but first fully instantiate the argument. */
- tree r = cxx_eval_outermost_constant_expr (t, true, true,
- manifestly_const_eval,
- NULL_TREE);
- /* cp_tree_equal looks through NOPs, so allow them. */
- gcc_checking_assert (r == t
- || CONVERT_EXPR_P (t)
- || TREE_CODE (t) == VIEW_CONVERT_EXPR
- || (TREE_CONSTANT (t) && !TREE_CONSTANT (r))
- || !cp_tree_equal (r, t));
- return r;
- }
- else if (TREE_OVERFLOW_P (t))
+tree
+fold_non_dependent_init (tree t,
+ tsubst_flags_t complain /*=tf_warning_or_error*/,
+ bool manifestly_const_eval /*=false*/)
+{
+ if (t == NULL_TREE)
+ return NULL_TREE;
+
+ if (processing_template_decl)
+ {
+ t = fold_non_dependent_expr_template (t, complain,
+ manifestly_const_eval);
+ /* maybe_constant_init does this stripping, so do it here too. */
+ if (TREE_CODE (t) == TARGET_EXPR)
{
- t = build_nop (TREE_TYPE (t), t);
- TREE_CONSTANT (t) = false;
+ tree init = TARGET_EXPR_INITIAL (t);
+ if (TREE_CODE (init) == CONSTRUCTOR)
+ t = init;
}
return t;
}
- return maybe_constant_value (t, NULL_TREE, manifestly_const_eval);
+ return maybe_constant_init (t, NULL_TREE, manifestly_const_eval);
}
/* Like maybe_constant_value, but returns a CONSTRUCTOR directly, rather