summaryrefslogtreecommitdiff
path: root/gcc/cp/semantics.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r--gcc/cp/semantics.c79
1 files changed, 68 insertions, 11 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 397d383f650..32154108107 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5805,6 +5805,40 @@ cxx_bind_parameters_in_call (const constexpr_call *old_call, tree t,
}
}
+/* Variables and functions to manage constexpr call expansion context.
+ These do not need to be marked for PCH or GC. */
+
+static VEC(tree,heap) *call_stack = NULL;
+static int call_stack_tick;
+static int last_cx_error_tick;
+
+static void
+push_cx_call_context (tree call)
+{
+ ++call_stack_tick;
+ if (!EXPR_HAS_LOCATION (call))
+ SET_EXPR_LOCATION (call, input_location);
+ VEC_safe_push (tree, heap, call_stack, call);
+}
+
+static void
+pop_cx_call_context (void)
+{
+ ++call_stack_tick;
+ VEC_pop (tree, call_stack);
+}
+
+VEC(tree,heap) *
+cx_error_context (void)
+{
+ VEC(tree,heap) *r = NULL;
+ if (call_stack_tick != last_cx_error_tick
+ && !VEC_empty (tree, call_stack))
+ r = call_stack;
+ last_cx_error_tick = call_stack_tick;
+ return r;
+}
+
/* Subroutine of cxx_eval_constant_expression.
Evaluate the call expression tree T in the context of OLD_CALL expression
evaluation. */
@@ -5814,13 +5848,11 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
bool allow_non_constant, bool addr,
bool *non_constant_p)
{
- location_t loc = EXPR_LOCATION (t);
+ location_t loc = EXPR_LOC_OR_HERE (t);
tree fun = get_function_named_in_call (t);
tree result;
constexpr_call new_call = { NULL, NULL, NULL, 0 };
constexpr_call **slot;
- if (loc == UNKNOWN_LOCATION)
- loc = input_location;
if (TREE_CODE (fun) != FUNCTION_DECL)
{
/* Might be a constexpr function pointer. */
@@ -5875,6 +5907,8 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
if (*non_constant_p)
return t;
+ push_cx_call_context (t);
+
new_call.hash
= iterative_hash_template_arg (new_call.bindings,
constexpr_fundef_hash (new_call.fundef));
@@ -5933,13 +5967,7 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
}
}
- if (result == error_mark_node)
- {
- if (!allow_non_constant)
- error_at (loc, "in expansion of %qE", t);
- *non_constant_p = true;
- result = t;
- }
+ pop_cx_call_context ();
return result;
}
@@ -6513,7 +6541,36 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
if (DECL_P (r))
{
if (!allow_non_constant)
- error ("%qD cannot appear in a constant expression", r);
+ {
+ tree type = TREE_TYPE (r);
+ error ("the value of %qD is not usable in a constant "
+ "expression", r);
+ if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+ {
+ if (!CP_TYPE_CONST_P (type))
+ inform (DECL_SOURCE_LOCATION (r),
+ "%q#D is not const", r);
+ else if (CP_TYPE_VOLATILE_P (type))
+ inform (DECL_SOURCE_LOCATION (r),
+ "%q#D is volatile", r);
+ else if (!DECL_INITIAL (r))
+ inform (DECL_SOURCE_LOCATION (r),
+ "%qD was not initialized with a constant "
+ "expression", r);
+ else
+ gcc_unreachable ();
+ }
+ else
+ {
+ if (cxx_dialect >= cxx0x && !DECL_DECLARED_CONSTEXPR_P (r))
+ inform (DECL_SOURCE_LOCATION (r),
+ "%qD was not declared %<constexpr%>", r);
+ else
+ inform (DECL_SOURCE_LOCATION (r),
+ "%qD does not have integral or enumeration type",
+ r);
+ }
+ }
*non_constant_p = true;
}
break;