From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15623 invoked by alias); 4 Aug 2011 15:32:37 -0000 Received: (qmail 15612 invoked by uid 22791); 4 Aug 2011 15:32:34 -0000 X-SWARE-Spam-Status: No, hits=-1.4 required=5.0 tests=AWL,BAYES_00 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; Thu, 04 Aug 2011 15:32:15 +0000 Received: from localhost (torimasen.com [82.237.12.13]) by ms.seketeli.net (Postfix) with ESMTP id 6313CEA040; Thu, 4 Aug 2011 17:24:55 +0200 (CEST) Received: by localhost (Postfix, from userid 500) id 59EA229C06A; Thu, 4 Aug 2011 17:32:13 +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, bonzini@gnu.org, jason@redhat.com Subject: Re: [PATCH 3/7] Emit macro expansion related diagnostics References: <1291979498-1604-1-git-send-email-dodji@redhat.com> <7ab852c58faea9efd81130c5a1ddc9e78b34bcc5.1310824121.git.dodji@redhat.com> X-URL: http://www.seketeli.net/~dodji Date: Thu, 04 Aug 2011 15:32:00 -0000 In-Reply-To: <7ab852c58faea9efd81130c5a1ddc9e78b34bcc5.1310824121.git.dodji@redhat.com> (Dodji Seketeli's message of "Sat, 16 Jul 2011 16:37:29 +0200") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable 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-08/txt/msg00509.txt.bz2 Hello, Below is an amended version of this patch after Jason's comments at http://gcc.gnu.org/ml/gcc-patches/2011-08/msg00099.html. From: Dodji Seketeli Date: Sat, 4 Dec 2010 16:31:35 +0100 Subject: [PATCH 3/7] Emit macro expansion related diagnostics 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 =E2=80=98g=E2=80=99: test.c:5:14: erreur: invalid operands to binary << (have =E2=80=98double=E2= =80=99 and =E2=80=98int=E2=80=99) 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=3Dall,ada and passed regression tests on x86_64-unknown-linux-gnu. 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. Resolve the virtual 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. * 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/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 | 176 +++++++++++++++++++= +++- gcc/tree-diagnostic.h | 3 +- 16 files changed, 313 insertions(+), 11 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 116a70b..2dae39d 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2793,7 +2793,7 @@ fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) c= oretypes.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 d435bbe..4915315 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, =20 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); } =20 diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index b46eb35..06e73a5 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" =20 #define pedantic_warning_kind(DC) \ ((DC)->pedantic_errors ? DK_ERROR : DK_WARNING) @@ -255,9 +256,9 @@ diagnostic_action_after_output (diagnostic_context *con= text, } =20 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 =3D NULL; =20 if (pp_needs_newline (context->printer)) { @@ -265,10 +266,13 @@ diagnostic_report_current_module (diagnostic_context = *context) pp_needs_newline (context->printer) =3D false; } =20 - if (input_location <=3D BUILTINS_LOCATION) + if (where <=3D BUILTINS_LOCATION) return; =20 - map =3D linemap_lookup (line_table, input_location); + linemap_resolve_location (line_table, where, + LRK_MACRO_PARM_REPLACEMENT_POINT, + &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 *, locati= on_t); =20 /* Force diagnostics controlled by OPTIDX to be kind KIND. */ extern diagnostic_t diagnostic_classify_diagnostic (diagnostic_context *, 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 @@ =20 // Just discard errors pointing at header files // { dg-prune-output "include" } +// { dg-prune-output " from" } =20 #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 @@ =20 // { dg-prune-output "note" } =20 +// 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 =20 diff --git a/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-1.c b/gcc/testsuit= e/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=3D1" } + { 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/testsuit= e/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 @@ +/*=20 + { dg-options "-ftrack-macro-expansion=3D1" } + { 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/testsuit= e/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=3D1" } + { 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/testsuit= e/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=3D2" } + { 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=3D2" } + { 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" } */ =20 + +/* + Just discard diagnostic prolog about errors in include files + { dg-prune-output "In file included from" } +*/ + #include =20 __m128d foo1(__m128d z, __m128d a, int N) {=20 diff --git a/gcc/toplev.c b/gcc/toplev.c index de0a58a..5f63b69 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) =3D 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) =3D virt_loc_aware_diagnostic_finalizer; /* Set a default printer. Language specific initializations will override it later. */ pp_format_decoder (global_dc->printer) =3D &default_tree_printer; diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c index b456a2a..be4a4c2 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); } =20 @@ -47,3 +47,177 @@ default_tree_diagnostic_starter (diagnostic_context *co= ntext, 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 =3D true; + source_location resolved_location; + unsigned loc_vec_capacity =3D 0, num_locs =3D 0; + loc_t *loc_vec =3D NULL; + unsigned ix; + loc_t loc, *iter; + +#define APPEND_LOC_TO_VEC(LOC) \ + if (num_locs >=3D loc_vec_capacity) \ + { \ + loc_vec_capacity +=3D 4; \ + loc_vec =3D XRESIZEVEC (loc_t, loc_vec, loc_vec_capacity); \ + } \ + loc_vec[num_locs++] =3D LOC; + + map =3D 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 =3D where; + loc.map =3D 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 =3D + linemap_macro_map_loc_to_def_point (map, where, false); + resolved_map =3D 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 =3D resolved_location; + map =3D 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 =3D + linemap_macro_map_loc_to_exp_point (map, where); + map =3D linemap_lookup (line_table, where); + } + if (!linemap_macro_expansion_map_p (map)) + unwind =3D false; + } + + if (topmost_exp_point_map) + *topmost_exp_point_map =3D 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 =3D 0; num_locs && ix < num_locs; ++ix) + { + source_location resolved_def_loc =3D 0, resolved_exp_loc =3D 0; + diagnostic_t saved_kind; + const char *saved_prefix; + source_location saved_location; + + iter =3D &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. */ + + /* Resolve the location iter->where into the locus 1/ of the + comment above. */ + resolved_def_loc =3D + linemap_resolve_location (line_table, iter->where, + LRK_MACRO_PARM_REPLACEMENT_POINT, NULL); + + /* Resolve 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. */ + resolved_exp_loc =3D + linemap_resolve_location (line_table, MACRO_MAP_EXPANSION_POINT_LOCATIO= N (iter->map), + LRK_MACRO_PARM_REPLACEMENT_POINT, NULL); + + saved_kind =3D diagnostic->kind; + saved_prefix =3D context->printer->prefix; + saved_location =3D diagnostic->location; + + diagnostic->kind =3D DK_NOTE; + diagnostic->location =3D 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 =3D 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 =3D saved_kind; + diagnostic->location =3D saved_location; + context->printer->prefix =3D 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_inf= o *); 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 */ --=20 Dodji