When building new-expressions, we use cp_lexer_previous_token and access its location to get the final position in the source range.
Within g++.dg/cpp0x/nsdmi-template14.C, the previous token within a new expr can have been purged, leading to UNKNOWN_LOCATION. g++.dg/cpp0x/nsdmi-template14.C:11:10: error: recursive instantiation of non-static data member initializer for ‘B<1>::p’ B* p = new B<N>; (note the lack of caret) (gdb) p *end_tok $54 = {type = CPP_GREATER, keyword = RID_MAX, flags = 0 '\000', pragma_kind = PRAGMA_NONE, implicit_extern_c = 0, error_reported = 0, purged_p = 1, location = 0, u = {tree_check_value = 0x0, value = <tree 0x0>}} This patch adds bulletproofing to detect purged tokens, and avoid using them. Alternatively, is it OK to access purged tokens for this kind of thing? If so, would it make more sense to instead leave their locations untouched when purging them? The patch also updates the location of a dg-error directive in the testcase to reflect improved location information. gcc/cp/ChangeLog: * parser.c (cp_parser_new_expression): Avoid accessing purged tokens when getting end of location range. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/nsdmi-template14.C: Move dg-error directive. --- gcc/cp/parser.c | 10 +++++++--- gcc/testsuite/g++.dg/cpp0x/nsdmi-template14.C | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index d859a89..f3d406e 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -7957,9 +7957,13 @@ cp_parser_new_expression (cp_parser* parser) with caret == start at the start of the "new" token, and the end at the end of the final token we consumed. */ cp_token *end_tok = cp_lexer_previous_token (parser->lexer); - location_t end_loc = get_finish (end_tok->location); - location_t combined_loc = make_location (start_loc, start_loc, end_loc); - + location_t combined_loc = start_loc; + if (!end_tok->purged_p) + { + location_t end_loc = get_finish (end_tok->location); + gcc_assert (end_loc); + combined_loc = make_location (start_loc, start_loc, end_loc); + } /* Create a representation of the new-expression. */ ret = build_new (&placement, type, nelts, &initializer, global_scope_p, tf_warning_or_error); diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template14.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template14.C index 9cb01f1..47f5b63 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template14.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template14.C @@ -8,10 +8,10 @@ template<int> struct A // { dg-error "has been parsed" } template<int N> struct B { - B* p = new B<N>; + B* p = new B<N>; // { dg-error "recursive instantiation of non-static data" } }; -B<1> x; // { dg-error "recursive instantiation of non-static data" } +B<1> x; struct C { -- 1.8.5.3