From 2bfe0527cd744a6f526fe11dd6c11ab39ad0a653 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 1 Nov 2010 21:31:40 -0400 Subject: [PATCH] semantics.c (call_stack, [...]): New. * semantics.c (call_stack, call_stack_tick, cx_error_context): New. (last_cx_error_tick, push_cx_call_context, pop_cx_call_context): New. (cxx_eval_call_expression): Call push/pop_cx_call_context instead of giving follow-on errors. * error.c (maybe_print_constexpr_context): New. (cp_diagnostic_starter): Call it. * cp-tree.h: Declare cx_error_context. From-SVN: r166169 --- gcc/cp/ChangeLog | 8 +++++ gcc/cp/cp-tree.h | 1 + gcc/cp/error.c | 27 ++++++++++++++++ gcc/cp/semantics.c | 48 ++++++++++++++++++++++------ gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C | 2 +- gcc/testsuite/g++.dg/cpp0x/constexpr-throw.C | 2 +- 6 files changed, 76 insertions(+), 12 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 93f1b7a..df32c8a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,13 @@ 2010-11-01 Jason Merrill + * semantics.c (call_stack, call_stack_tick, cx_error_context): New. + (last_cx_error_tick, push_cx_call_context, pop_cx_call_context): New. + (cxx_eval_call_expression): Call push/pop_cx_call_context instead + of giving follow-on errors. + * error.c (maybe_print_constexpr_context): New. + (cp_diagnostic_starter): Call it. + * cp-tree.h: Declare cx_error_context. + * semantics.c (cxx_eval_constant_expression): Explain unacceptable use of variable better. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e408ef7..f57efb9 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5246,6 +5246,7 @@ extern tree maybe_constant_value (tree); extern tree maybe_constant_init (tree); extern bool is_sub_constant_expr (tree); extern bool reduced_constant_expression_p (tree); +extern VEC(tree,heap)* cx_error_context (void); enum { BCS_NO_SCOPE = 1, diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 9ad2b93..6f60c06 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -86,6 +86,7 @@ static void dump_scope (tree, int); static void dump_template_parms (tree, int, int); static int get_non_default_template_args_count (tree, int); static const char *function_category (tree); +static void maybe_print_constexpr_context (diagnostic_context *); static void maybe_print_instantiation_context (diagnostic_context *); static void print_instantiation_full_context (diagnostic_context *); static void print_instantiation_partial_context (diagnostic_context *, @@ -2635,6 +2636,7 @@ cp_diagnostic_starter (diagnostic_context *context, diagnostic_report_current_module (context); cp_print_error_function (context, diagnostic); maybe_print_instantiation_context (context); + maybe_print_constexpr_context (context); pp_base_set_prefix (context->printer, diagnostic_build_prefix (context, diagnostic)); } @@ -2955,6 +2957,31 @@ print_instantiation_context (void) diagnostic_flush_buffer (global_dc); } +/* Report what constexpr call(s) we're trying to expand, if any. */ + +void +maybe_print_constexpr_context (diagnostic_context *context) +{ + VEC(tree,heap) *call_stack = cx_error_context (); + unsigned ix; + tree t; + + FOR_EACH_VEC_ELT (tree, call_stack, ix, t) + { + expanded_location xloc = expand_location (EXPR_LOCATION (t)); + const char *s = expr_as_string (t, 0); + if (context->show_column) + pp_verbatim (context->printer, + _("%s:%d:%d: in constexpr expansion of %qs"), + xloc.file, xloc.line, xloc.column, s); + else + pp_verbatim (context->printer, + _("%s:%d: in constexpr expansion of %qs"), + xloc.file, xloc.line, s); + pp_base_newline (context->printer); + } +} + /* Called from output_format -- during diagnostic message processing -- to handle C++ specific format specifier with the following meanings: %A function argument-list. diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 2b8e9e3..3215410 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; } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C index ce01f8b..8294afa 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C @@ -18,7 +18,7 @@ constexpr pixel::pixel(int a) // error: square not defined, so small(2) not constant (5.19), so constexpr // not satisfied -constexpr pixel small(2); // { dg-error "" } +constexpr pixel small(2); // { dg-message "in constexpr expansion" } // error: not for parameters int next(constexpr int x) { // { dg-error "parameter" } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-throw.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-throw.C index 345b240..f1ef9dc 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-throw.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-throw.C @@ -4,5 +4,5 @@ constexpr int may_throw(bool decide) { return decide ? 42 : throw -1; // { dg-error "throw" } } -constexpr int x = may_throw(false); // { dg-error "may_throw" } +constexpr int x = may_throw(false); // { dg-message "may_throw" } constexpr int y = may_throw(true); -- 2.7.4