diff options
author | Jason Merrill <jason@redhat.com> | 2010-11-01 23:29:52 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2010-11-01 23:32:03 -0400 |
commit | d29b209e37cb85fdf1cb1d8e0ae263cc3c59312b (patch) | |
tree | 0e6b797a6c1a23c50603805706926a5eaa2184f1 /gcc/cp/semantics.c | |
parent | 2450a78a38a727e7ec673b132315c8379db3b27d (diff) | |
parent | c0000147b2aef6b69e2c6b6d29a9963910f6da98 (diff) | |
download | gcc-constexpr.tar.gz |
Merge remote branch 'trunk' into constexprconstexpr
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r-- | gcc/cp/semantics.c | 79 |
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; |