From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22311 invoked by alias); 16 Jul 2011 14:38:03 -0000 Received: (qmail 21804 invoked by uid 22791); 16 Jul 2011 14:37:55 -0000 X-SWARE-Spam-Status: No, hits=-0.3 required=5.0 tests=AWL,BAYES_20,SARE_MSGID_LONG40 X-Spam-Check-By: sourceware.org Received: from seketeli.net (HELO ms.seketeli.net) (91.121.166.71) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 16 Jul 2011 14:37:35 +0000 Received: from localhost (torimasen.com [82.237.12.13]) by ms.seketeli.net (Postfix) with ESMTP id 697BFEA04D; Sat, 16 Jul 2011 16:32:05 +0200 (CEST) Received: by localhost (Postfix, from userid 500) id 2819929C059; Sat, 16 Jul 2011 16:37:33 +0200 (CEST) From: Dodji Seketeli To: gcc-patches@gcc.gnu.org Cc: tromey@redhat.com, gdr@integrable-solutions.net, joseph@codesourcery.com, burnus@net-b.de, charlet@act-europe.fr, paolo@gnu.org, jason@redhat.com Subject: [PATCH 3/7] Emit macro expansion related diagnostics Date: Sat, 16 Jul 2011 14:38:00 -0000 Message-Id: <7ab852c58faea9efd81130c5a1ddc9e78b34bcc5.1310824121.git.dodji@redhat.com> In-Reply-To: References: <1291979498-1604-1-git-send-email-dodji@redhat.com> In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2011-07/txt/msg01320.txt.bz2 In this third instalment the diagnostic machinery -- when faced with the virtual location of a token resulting from macro expansion -- uses the new linemap APIs to unwind the stack of macro expansions that led to that token and emits a [hopefully] more useful message than what we have today. diagnostic_report_current_module has been slightly changed to use the location given by client code instead of the global input_location variable. This results in more precise diagnostic locations in general but then the patch adjusts some C++ tests which output changed as a result of this. Three new regression tests have been added. The mandatory screenshot goes like this: [dodji@adjoa gcc]$ cat -n test.c 1 #define OPERATE(OPRD1, OPRT, OPRD2) \ 2 OPRD1 OPRT OPRD2; 3 4 #define SHIFTL(A,B) \ 5 OPERATE (A,<<,B) 6 7 #define MULT(A) \ 8 SHIFTL (A,1) 9 10 void 11 g () 12 { 13 MULT (1.0);/* 1.0 << 1; <-- so this is an error. */ 14 } [dodji@adjoa gcc]$ ./cc1 -quiet -ftrack-macro-expansion test.c test.c: In function ‘g’: test.c:5:14: erreur: invalid operands to binary << (have ‘double’ and ‘int’) test.c:2:9: note: in expansion of macro 'OPERATE' test.c:5:3: note: expanded from here test.c:5:14: note: in expansion of macro 'SHIFTL' test.c:8:3: note: expanded from here test.c:8:3: note: in expansion of macro 'MULT2' test.c:13:3: note: expanded from here The combination of this patch and the previous ones boostrapped with --enable-languages=all,ada and passed regression tests on x86_64-unknown-linux-gnu. libcpp/ * include/line-map.h (linemap_expand_location_full): Add an output parameter returning the spelling location the input location got resolved to, at declaration point ... * line-map.c (linemap_expand_location_full): ... and at definition point. gcc/ * gcc/diagnostic.h (diagnostic_report_current_module): Add a location parameter. * diagnostic.c (diagnostic_report_current_module): Add a location parameter to the function definition. Use it instead of input_location. Fully expand the location rather than just looking up its map and risking to touch a resulting macro map. (default_diagnostic_starter): Pass the relevant diagnostic location to diagnostic_report_current_module. * tree-diagnostic.c (maybe_unwind_expanded_macro_loc): New. (virt_loc_aware_diagnostic_finalizer): Likewise. (diagnostic_report_current_function): Pass the relevant location to diagnostic_report_current_module. * tree-diagnostic.h (virt_loc_aware_diagnostic_finalizer): Declare new function. * input.c (expand_location): Adjust call to linemap_expand_location_full. * toplev.c (general_init): By default, use the new virt_loc_aware_diagnostic_finalizer as diagnostic finalizer. gcc/cp/ * error.c (cp_diagnostic_starter): Pass the relevant location to diagnostic_report_current_module. (cp_diagnostic_finalizer): Call virt_loc_aware_diagnostic_finalizer. gcc/testsuite/ * gcc.dg/cpp/macro-exp-tracking-1.c: New test. * gcc.dg/cpp/macro-exp-tracking-2.c: Likewise. * gcc.dg/cpp/macro-exp-tracking-3.c: Likewise. * gcc.dg/cpp/pragma-diagnostic-2.c: Likewise. * g++.dg/cpp0x/initlist15.C: Discard errors pointing at multiple levels of included files. * g++.old-deja/g++.robertl/eb43.C: Likewise. * g++.old-deja/g++.robertl/eb79.C: Likewise. * gcc.target/i386/sse-vect-types.c: Likewise. --- gcc/Makefile.in | 2 +- gcc/cp/error.c | 5 +- gcc/diagnostic.c | 14 +- gcc/diagnostic.h | 2 +- gcc/input.c | 2 +- gcc/testsuite/g++.dg/cpp0x/initlist15.C | 1 + gcc/testsuite/g++.old-deja/g++.robertl/eb43.C | 4 + gcc/testsuite/g++.old-deja/g++.robertl/eb79.C | 4 + gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-1.c | 21 +++ gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-2.c | 21 +++ gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-3.c | 14 ++ gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-4.c | 14 ++ gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-2.c | 34 +++++ gcc/testsuite/gcc.target/i386/sse-vect-types.c | 6 + gcc/toplev.c | 3 + gcc/tree-diagnostic.c | 181 ++++++++++++++++++++++- gcc/tree-diagnostic.h | 3 +- libcpp/include/line-map.h | 14 ++- libcpp/line-map.c | 4 +- 19 files changed, 332 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-1.c create mode 100644 gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-2.c create mode 100644 gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-3.c create mode 100644 gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-4.c create mode 100644 gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-2.c diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 47e14fa..e800685 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2792,7 +2792,7 @@ fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(GGC_H) $(TM_P_H) langhooks.h $(MD5_H) intl.h $(TARGET_H) \ $(GIMPLE_H) realmpfr.h $(TREE_FLOW_H) diagnostic.o : diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ - version.h $(INPUT_H) intl.h $(DIAGNOSTIC_H) diagnostic.def + version.h $(INPUT_H) intl.h $(DIAGNOSTIC_H) diagnostic.def $(VEC_H) opts.o : opts.c $(OPTS_H) $(OPTIONS_H) $(DIAGNOSTIC_CORE_H) $(CONFIG_H) $(SYSTEM_H) \ coretypes.h $(TM_H) \ $(DIAGNOSTIC_H) insn-attr-common.h intl.h $(COMMON_TARGET_H) \ diff --git a/gcc/cp/error.c b/gcc/cp/error.c index b16fce6..964797d 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -2763,7 +2763,7 @@ static void cp_diagnostic_starter (diagnostic_context *context, diagnostic_info *diagnostic) { - diagnostic_report_current_module (context); + diagnostic_report_current_module (context, diagnostic->location); cp_print_error_function (context, diagnostic); maybe_print_instantiation_context (context); maybe_print_constexpr_context (context); @@ -2773,8 +2773,9 @@ cp_diagnostic_starter (diagnostic_context *context, static void cp_diagnostic_finalizer (diagnostic_context *context, - diagnostic_info *diagnostic ATTRIBUTE_UNUSED) + diagnostic_info *diagnostic) { + virt_loc_aware_diagnostic_finalizer (context, diagnostic); pp_base_destroy_prefix (context->printer); } diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index b46eb35..c41e88d 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "input.h" #include "intl.h" #include "diagnostic.h" +#include "vec.h" #define pedantic_warning_kind(DC) \ ((DC)->pedantic_errors ? DK_ERROR : DK_WARNING) @@ -255,9 +256,9 @@ diagnostic_action_after_output (diagnostic_context *context, } void -diagnostic_report_current_module (diagnostic_context *context) +diagnostic_report_current_module (diagnostic_context *context, location_t where) { - const struct line_map *map; + const struct line_map *map = NULL; if (pp_needs_newline (context->printer)) { @@ -265,10 +266,13 @@ diagnostic_report_current_module (diagnostic_context *context) pp_needs_newline (context->printer) = false; } - if (input_location <= BUILTINS_LOCATION) + if (where <= BUILTINS_LOCATION) return; - map = linemap_lookup (line_table, input_location); + linemap_expand_location_full (line_table, where, + LRK_MACRO_PARM_REPLACEMENT_POINT, + NULL, &map); + if (map && diagnostic_last_module_changed (context, map)) { diagnostic_set_last_module (context, map); @@ -301,7 +305,7 @@ void default_diagnostic_starter (diagnostic_context *context, diagnostic_info *diagnostic) { - diagnostic_report_current_module (context); + diagnostic_report_current_module (context, diagnostic->location); pp_set_prefix (context->printer, diagnostic_build_prefix (context, diagnostic)); } diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 8074354..4b1265b 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -253,7 +253,7 @@ extern diagnostic_context *global_dc; /* Diagnostic related functions. */ extern void diagnostic_initialize (diagnostic_context *, int); extern void diagnostic_finish (diagnostic_context *); -extern void diagnostic_report_current_module (diagnostic_context *); +extern void diagnostic_report_current_module (diagnostic_context *, location_t); /* Force diagnostics controlled by OPTIDX to be kind KIND. */ extern diagnostic_t diagnostic_classify_diagnostic (diagnostic_context *, diff --git a/gcc/input.c b/gcc/input.c index 29e4de1..f3c7bfa 100644 --- a/gcc/input.c +++ b/gcc/input.c @@ -57,7 +57,7 @@ expand_location (source_location loc) (expand_to_expansion_point_p) ? LRK_MACRO_EXPANSION_POINT : LRK_SPELLING_LOCATION, - NULL); + NULL, NULL); } return xloc; } diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist15.C b/gcc/testsuite/g++.dg/cpp0x/initlist15.C index b75cc81..cca56b1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist15.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist15.C @@ -2,6 +2,7 @@ // Just discard errors pointing at header files // { dg-prune-output "include" } +// { dg-prune-output " from" } #include #include diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb43.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb43.C index 1dc4328..bd784b1 100644 --- a/gcc/testsuite/g++.old-deja/g++.robertl/eb43.C +++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb43.C @@ -6,6 +6,10 @@ // { dg-prune-output "note" } +// Discard errors pointing at header files +// { dg-prune-output "In file included from" } +// { dg-prune-output " from" } + #include #include #include diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb79.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb79.C index 1c1ad3e..60cc713 100644 --- a/gcc/testsuite/g++.old-deja/g++.robertl/eb79.C +++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb79.C @@ -1,5 +1,9 @@ // { dg-do assemble } // { dg-prune-output "note" } + +// Discard errors pointing at header files +// { dg-prune-output "In file included from" } +// { dg-prune-output " from" } // Makes bogus x86 assembly code. #include diff --git a/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-1.c b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-1.c new file mode 100644 index 0000000..d975c8c --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-1.c @@ -0,0 +1,21 @@ +/* + { dg-options "-ftrack-macro-expansion=1" } + { dg-do compile } +*/ + +#define OPERATE(OPRD1, OPRT, OPRD2) \ +do \ +{ \ + OPRD1 OPRT OPRD2; /* { dg-message "expansion" }*/ \ +} while (0) + +#define SHIFTL(A,B) \ + OPERATE (A,<<,B) /* { dg-message "expanded|expansion" } */ + +void +foo () +{ + SHIFTL (0.1,0.2); /* { dg-message "expanded" } */ +} + +/* { dg-error "invalid operands" "" { target *-*-* } 13 } */ diff --git a/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-2.c b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-2.c new file mode 100644 index 0000000..684af4c --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-2.c @@ -0,0 +1,21 @@ +/* + { dg-options "-ftrack-macro-expansion=1" } + { dg-do compile } +*/ + +#define OPERATE(OPRD1, OPRT, OPRD2) \ + OPRD1 OPRT OPRD2; /* { dg-message "expansion" } */ + +#define SHIFTL(A,B) \ + OPERATE (A,<<,B) /* { dg-message "expanded|expansion" } */ + +#define MULT(A) \ + SHIFTL (A,1) /* { dg-message "expanded|expansion" } */ + +void +foo () +{ + MULT (1.0); /* { dg-message "expanded" } */ +} + +/* { dg-error "invalid operands to binary <<" "" { target *-*-* } { 10 } } */ diff --git a/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-3.c b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-3.c new file mode 100644 index 0000000..119053e --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-3.c @@ -0,0 +1,14 @@ +/* + { dg-options "-fshow-column -ftrack-macro-expansion=1" } + { dg-do compile } + */ + +#define SQUARE(A) A * A /* { dg-message "expansion" } */ + +void +foo() +{ + SQUARE (1 << 0.1); /* { dg-message "expanded" } */ +} + +/* { dg-error "16:invalid operands to binary <<" "" {target *-*-* } { 11 } } */ diff --git a/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-4.c b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-4.c new file mode 100644 index 0000000..1f9fe6a --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-4.c @@ -0,0 +1,14 @@ +/* + { dg-options "-fshow-column -ftrack-macro-expansion=2" } + { dg-do compile } + */ + +#define SQUARE(A) A * A /* { dg-message "expansion" } */ + +void +foo() +{ + SQUARE (1 << 0.1); /* { dg-message "expanded" } */ +} + +/* { dg-error "13:invalid operands to binary <<" "" { target *-*-* } { 11 } } */ diff --git a/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-2.c b/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-2.c new file mode 100644 index 0000000..7ab95b0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-2.c @@ -0,0 +1,34 @@ +/* + { dg-options "-Wuninitialized -ftrack-macro-expansion=2" } + { dg-do compile } +*/ + +void f (unsigned); + +#define CODE_WITH_WARNING \ + int a; /* { dg-message "expansion|declared here" } */ \ + f (a) /* { dg-message "expansion" } */ + +#pragma GCC diagnostic ignored "-Wuninitialized" + +void +g (void) +{ + CODE_WITH_WARNING; +} + +#pragma GCC diagnostic push + +#pragma GCC diagnostic error "-Wuninitialized" + +void +h (void) +{ + CODE_WITH_WARNING; /* { dg-message "expanded" } */ +} + +/* + { dg-message "some warnings being treated as errors" "" {target *-*-*} 0 } +*/ + +/* { dg-error "uninitialized" "" { target *-*-* } { 10 } } */ diff --git a/gcc/testsuite/gcc.target/i386/sse-vect-types.c b/gcc/testsuite/gcc.target/i386/sse-vect-types.c index 9cb6f3e..ce70125 100644 --- a/gcc/testsuite/gcc.target/i386/sse-vect-types.c +++ b/gcc/testsuite/gcc.target/i386/sse-vect-types.c @@ -1,6 +1,12 @@ /* { dg-do compile } */ /* { dg-options "-O0 -msse2" } */ + +/* + Just discard diagnostic prolog about errors in include files + { dg-prune-output "In file included from" } +*/ + #include __m128d foo1(__m128d z, __m128d a, int N) { diff --git a/gcc/toplev.c b/gcc/toplev.c index 109325c..9a98c5f 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1132,6 +1132,9 @@ general_init (const char *argv0) can give warnings and errors. */ diagnostic_initialize (global_dc, N_OPTS); diagnostic_starter (global_dc) = default_tree_diagnostic_starter; + /* By default print macro expansion contexts in the diagnostic + finalizer -- for tokens resulting from macro macro expansion. */ + diagnostic_finalizer (global_dc) = virt_loc_aware_diagnostic_finalizer; /* Set a default printer. Language specific initializations will override it later. */ pp_format_decoder (global_dc->printer) = &default_tree_printer; diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c index b456a2a..6fae644 100644 --- a/gcc/tree-diagnostic.c +++ b/gcc/tree-diagnostic.c @@ -35,7 +35,7 @@ void diagnostic_report_current_function (diagnostic_context *context, diagnostic_info *diagnostic) { - diagnostic_report_current_module (context); + diagnostic_report_current_module (context, diagnostic->location); lang_hooks.print_error_function (context, input_filename, diagnostic); } @@ -47,3 +47,182 @@ default_tree_diagnostic_starter (diagnostic_context *context, pp_set_prefix (context->printer, diagnostic_build_prefix (context, diagnostic)); } + +/* Unwind the different macro expansions that lead to the token which + location is WHERE and emit diagnostics showing the resulting + unwound macro expansion stack. If TOPMOST_EXP_POINT_MAP is + non-null, *TOPMOST_EXP_POINT_MAP is set to the map of the expansion + point of the top most macro of the stack. This must be an ordinary + map. */ + +static void +maybe_unwind_expanded_macro_loc (diagnostic_context *context, + diagnostic_info *diagnostic, + source_location where, + const struct line_map **topmost_exp_point_map) +{ + typedef struct + { + const struct line_map *map; + source_location where; + } loc_t; + + const struct line_map *map, *resolved_map; + bool unwind = true; + source_location resolved_location; + unsigned loc_vec_capacity = 0, num_locs = 0; + loc_t *loc_vec = NULL; + unsigned ix; + loc_t loc, *iter; + +#define APPEND_LOC_TO_VEC(LOC) \ + if (num_locs >= loc_vec_capacity) \ + { \ + loc_vec_capacity += 4; \ + loc_vec = XRESIZEVEC (loc_t, loc_vec, loc_vec_capacity); \ + } \ + loc_vec[num_locs++] = LOC; + + map = linemap_lookup (line_table, where); + if (!linemap_macro_expansion_map_p (map)) + return; + + /* Let's unwind the stack of macros that got expanded and that led + to the token which location is WHERE. We are going to store the + stack into MAP_VEC, so that we can later walk MAP_VEC backward to + display a somewhat meaningful trace of the macro expansion + history to the user. Note that the deepest macro expansion is + going to be stored at the beginning of MAP_VEC. */ + while (unwind) + { + loc.where = where; + loc.map = map; + + APPEND_LOC_TO_VEC (loc); + + /* WHERE is the location of a token inside the expansion of a + macro. MAP is the map holding the locations of that macro + expansion. Let's get the location of the token inside the + *definition* of the macro of MAP, that got expanded at + WHERE. This is basically how we go "up" in the stack of + macro expansions that led to WHERE. */ + resolved_location = + linemap_macro_map_loc_to_def_point (map, where, false); + resolved_map = linemap_lookup (line_table, resolved_location); + + /* If the token at RESOLVED_LOCATION [at macro definition point] + is itself inside an expanded macro then we keep unwinding the + expansion stack by tracing the "parent macro" that got expanded + inside the definition of the macro of MAP... */ + if (linemap_macro_expansion_map_p (resolved_map)) + { + where = resolved_location; + map = resolved_map; + } + else + { + /* Otherwise, let's consider the location of the expansion + point of the macro of MAP. Keep in mind that MAP is a + macro expansion map. To get a "normal map" (i.e a non + macro expansion map) and be done with the unwinding, we + must either consider the location of the location + expansion point of the macro or the location of the token + inside the macro definition that got expanded to + WHERE. */ + where = + linemap_macro_map_loc_to_exp_point (map, where); + map = linemap_lookup (line_table, where); + } + if (!linemap_macro_expansion_map_p (map)) + unwind = false; + } + + if (topmost_exp_point_map) + *topmost_exp_point_map = map; + + /* Walk the map_vec and print the macro expansion stack, unless the + topmost macro which expansion triggered this stack [assuming the + stack grows downwards] was expanded inside a system header. */ + if (!LINEMAP_SYSP (resolved_map)) + for (ix = 0; num_locs && ix < num_locs; ++ix) + { + source_location resolved_def_loc = 0, resolved_exp_loc = 0; + diagnostic_t saved_kind; + const char *saved_prefix; + source_location saved_location; + + iter = &loc_vec[ix]; + + /* Okay, now here is what we want. For each token resulting + from macro expansion we want to show: 1/ where in the + definition of the macro the token comes from. + + 2/ where the macro got expanded. */ + + /* Expand the location iter->where into the locus 1/ of the + comment above. */ + linemap_expand_location_full (line_table, iter->where, + LRK_MACRO_PARM_REPLACEMENT_POINT, + &resolved_def_loc, + NULL); + + /* Expand the location of the expansion point of the macro + which expansion gave the token at represented by def_loc. + This is the locus 2/ of the earlier comment. */ + linemap_expand_location_full (line_table, + MACRO_MAP_EXPANSION_POINT_LOCATION + (iter->map), + LRK_MACRO_PARM_REPLACEMENT_POINT, + &resolved_exp_loc, + NULL); + + saved_kind = diagnostic->kind; + saved_prefix = context->printer->prefix; + saved_location = diagnostic->location; + + diagnostic->kind = DK_NOTE; + diagnostic->location = resolved_def_loc; + pp_base_set_prefix (context->printer, + diagnostic_build_prefix (context, + diagnostic)); + pp_newline (context->printer); + pp_printf (context->printer, "in expansion of macro '%s'", + linemap_map_get_macro_name (iter->map)); + pp_destroy_prefix (context->printer); + diagnostic->location = resolved_exp_loc; + pp_base_set_prefix (context->printer, + diagnostic_build_prefix (context, + diagnostic)); + pp_newline (context->printer); + pp_printf (context->printer, "expanded from here"); + pp_destroy_prefix (context->printer); + + diagnostic->kind = saved_kind; + diagnostic->location = saved_location; + context->printer->prefix = saved_prefix; + } + + free (loc_vec); +} + +/* This is a diagnostic finalizer implementation that is aware of + virtual locations produced by libcpp. + + It has to be called by the diagnostic finalizer of front ends that + uses libcpp and wish to get diagnostics involving tokens resulting + from macro expansion. + + For a given location, if said location belongs to a token + resulting from a macro expansion, this starter prints the context + of the token. E.g, for a multiply nested macro expansions, it + unwinds the nested macro expansions and prints them in a manner + that is similar to what is done for function call stacks, or + template instantiation contexts. */ +void +virt_loc_aware_diagnostic_finalizer (diagnostic_context *context, + diagnostic_info *diagnostic) +{ + maybe_unwind_expanded_macro_loc (context, diagnostic, + diagnostic->location, + NULL); +} diff --git a/gcc/tree-diagnostic.h b/gcc/tree-diagnostic.h index 7d88089..6b8e8e6 100644 --- a/gcc/tree-diagnostic.h +++ b/gcc/tree-diagnostic.h @@ -52,5 +52,6 @@ along with GCC; see the file COPYING3. If not see void default_tree_diagnostic_starter (diagnostic_context *, diagnostic_info *); extern void diagnostic_report_current_function (diagnostic_context *, diagnostic_info *); - +void virt_loc_aware_diagnostic_finalizer (diagnostic_context *, + diagnostic_info *); #endif /* ! GCC_TREE_DIAGNOSTIC_H */ diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index 399194c..e04aa77 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -827,9 +827,15 @@ expanded_location linemap_expand_location (struct line_maps *, If LOC is the locus of a token that is not an argument of a function-like macro, then the function behaves as if LRK was set to - LRK_SPELLING_LOCATION. */ + LRK_SPELLING_LOCATION. + + Finally, if SPELLING_LOC is not NULL, *RESULTING_LOC is set to the + location to which LOC was resolved, and similarly, *LOC_MAP is set + to its map. */ expanded_location linemap_expand_location_full (struct line_maps *, - source_location, - enum location_resolution_kind, - const struct line_map**); + source_location loc, + enum location_resolution_kind lrk, + source_location *resulting_loc, + const struct line_map **loc_map); + #endif /* !LIBCPP_LINE_MAP_H */ diff --git a/libcpp/line-map.c b/libcpp/line-map.c index 693ed0b..5bd864d 100644 --- a/libcpp/line-map.c +++ b/libcpp/line-map.c @@ -768,6 +768,7 @@ expanded_location linemap_expand_location_full (struct line_maps *set, source_location loc, enum location_resolution_kind lrk, + source_location *resulting_loc, const struct line_map **loc_map) { const struct line_map *map; @@ -796,6 +797,7 @@ linemap_expand_location_full (struct line_maps *set, xloc.sysp = LINEMAP_SYSP (map) != 0; if (loc_map) *loc_map = map; - + if (resulting_loc) + *resulting_loc = loc; return xloc; } -- 1.7.6