From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7184 invoked by alias); 16 Sep 2011 07:56:57 -0000 Received: (qmail 7169 invoked by uid 22791); 16 Sep 2011 07:56:54 -0000 X-SWARE-Spam-Status: No, hits=-6.2 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,SPF_HELO_PASS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 16 Sep 2011 07:56:31 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p8G7u3ib010304 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 16 Sep 2011 03:56:03 -0400 Received: from localhost (ovpn-113-40.phx2.redhat.com [10.3.113.40]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p8G7u0sA032543 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 16 Sep 2011 03:56:02 -0400 Received: by localhost (Postfix, from userid 500) id B0F7F29C0CB; Fri, 16 Sep 2011 09:55:59 +0200 (CEST) From: Dodji Seketeli To: Jason Merrill Cc: gcc-patches@gcc.gnu.org, tromey@redhat.com, gdr@integrable-solutions.net, joseph@codesourcery.com, burnus@net-b.de, charlet@act-europe.fr, bonzini@gnu.org 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> <4E6E73F8.4030603@redhat.com> X-URL: http://www.redhat.com Date: Fri, 16 Sep 2011 08:19:00 -0000 In-Reply-To: <4E6E73F8.4030603@redhat.com> (Jason Merrill's message of "Mon, 12 Sep 2011 17:04:56 -0400") 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 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-09/txt/msg00953.txt.bz2 > On 08/04/2011 11:32 AM, Dodji Seketeli wrote: > > +++ 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 > Do you still need this? Oops, no. Removed and adjusted gcc/Makefile.in accordingly. >=20 > > // Just discard errors pointing at header files > > // { dg-prune-output "include" } > > +// { dg-prune-output " from" } >=20 > These should be pruned by testsuite/lib/prune.exp. I'm surprised they > aren't already. OK. I have added that pruning to prune.exp and removed it from the relevant test case files. >=20 > > +#define APPEND_LOC_TO_VEC(LOC) = \ > > + if (num_locs >=3D3D loc_vec_capacity) = \ > > + { = \ > > + loc_vec_capacity +=3D3D 4; = \ > > + loc_vec =3D3D XRESIZEVEC (loc_t, loc_vec, loc_vec_capacity); > > \ > > + } = \ > > + loc_vec[num_locs++] =3D3D LOC; >=20 > Why not use VEC since we're in gcc/ here? This is another leftover of when this code wasn't in gcc/. I am using VEC now in the amended patch. >=20 > > +/* 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. */ >=20 > I find the use of "top" here confusing. You mean the place in the > source that first triggered the macro expansion, right? Yes. > Can we avoid talking about stacks here? OK. Sorry for the confusion. I have removed the stack analogy added hopefully more accurate comments. [...] > > + while (unwind) > > + { > ... > > + if (!linemap_macro_expansion_map_p (map)) > > + unwind =3D3D false; > > + } >=20 > This seems like a job for do/while. Updated accordingly. I have fixed some other nits in the patch, bootstrapped and tested it on x86_64-unknown-linux-gnu against a tree based on trunk and containing the previous patches of the set. Thanks. 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. * Makefile.in: Add vec.h dependency to tree-diagnostic.c. 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/ * lib/prune.exp (prune_gcc_output): Prune output referring to included files. * 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. --- gcc/Makefile.in | 3 +- gcc/cp/error.c | 5 +- gcc/diagnostic.c | 13 +- gcc/diagnostic.h | 2 +- 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/lib/prune.exp | 1 + gcc/toplev.c | 3 + gcc/tree-diagnostic.c | 208 +++++++++++++++++++= +++- gcc/tree-diagnostic.h | 3 +- 13 files changed, 331 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 92016f2..d26c682 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2796,7 +2796,8 @@ tree-pretty-print.o : tree-pretty-print.c $(CONFIG_H)= $(SYSTEM_H) \ $(TM_H) coretypes.h tree-iterator.h $(SCEV_H) langhooks.h \ $(TREE_PASS_H) value-prof.h output.h tree-pretty-print.h tree-diagnostic.o : tree-diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ - $(TREE_H) $(DIAGNOSTIC_H) tree-diagnostic.h langhooks.h $(LANGHOOKS_DEF= _H) + $(TREE_H) $(DIAGNOSTIC_H) tree-diagnostic.h langhooks.h $(LANGHOOKS_DEF= _H) \ + $(VEC_H) fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) $(FLAGS_H) $(DIAGNOSTIC_CORE_H) $(HASHTAB_H) $(EXPR_H) $(RTL_= H) \ $(GGC_H) $(TM_P_H) langhooks.h $(MD5_H) intl.h $(TARGET_H) \ diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 598ddf1..8fa163f 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -2767,7 +2767,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); @@ -2777,8 +2777,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..0344937 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -255,9 +255,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 +265,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 +304,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/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/lib/prune.exp b/gcc/testsuite/lib/prune.exp index 4683f93..09d2581 100644 --- a/gcc/testsuite/lib/prune.exp +++ b/gcc/testsuite/lib/prune.exp @@ -29,6 +29,7 @@ proc prune_gcc_output { text } { regsub -all "(^|\n)collect: re(compiling|linking)\[^\n\]*" $text "" te= xt regsub -all "(^|\n)Please submit.*instructions\[^\n\]*" $text "" text regsub -all "(^|\n)\[0-9\]\[0-9\]* errors\." $text "" text + regsub -all "(^|\n)(In file included|\[ \]+from)\[^\n\]*" $text "" text =20 # Ignore informational notes. regsub -all "(^|\n)\[^\n\]*: note: \[^\n\]*" $text "" text 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..ff7a749 100644 --- a/gcc/tree-diagnostic.c +++ b/gcc/tree-diagnostic.c @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-diagnostic.h" #include "langhooks.h" #include "langhooks-def.h" +#include "vec.h" =20 /* Prints out, if necessary, the name of the current function that caused an error. Called from all error and warning functions. */ @@ -35,7 +36,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 +48,208 @@ default_tree_diagnostic_starter (diagnostic_context *co= ntext, pp_set_prefix (context->printer, diagnostic_build_prefix (context, diagnostic)); } + +/* This is a pair made of a location and the line map it originated + from. It's used in the maybe_unwind_expanded_macro_loc function + below. */ +typedef struct +{ + const struct line_map *map; + source_location where; +} loc_t; + +DEF_VEC_O (loc_t); +DEF_VEC_ALLOC_O (loc_t, heap); + +/* Unwind the different macro expansions that lead to the token which + location is WHERE and emit diagnostics showing the resulting + unwound macro expansion trace. Let's look at an example to see how + the trace looks like. Suppose we have this piece of code, + artificially annotated with the line numbers to increase + legibility: + + $ 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 } + + Here is the diagnostic that we want the compiler to generate: + + test.c: In function =E2=80=98g=E2=80=99: + test.c:5:14: error: invalid operands to binary << (have =E2=80=98doubl= e=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 part that goes from the third to the sixth line of this + diagnostic (the lines containing the 'note:' string) is called the + unwound macro expansion trace. That's the part generated by this + function. + + If FIRST_EXP_POINT_MAP is non-null, *FIRST_EXP_POINT_MAP is set to + the map of the location in the source that first triggered the + macro expansion. 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 **first_exp_point_m= ap) +{ + const struct line_map *map, *resolved_map; + source_location resolved_location; + VEC(loc_t,heap) *loc_vec =3D NULL; + unsigned ix; + loc_t loc, *iter; + + map =3D linemap_lookup (line_table, where); + if (!linemap_macro_expansion_map_p (map)) + return; + + /* Let's unwind the macros that got expanded and led to the token + which location is WHERE. We are going to store these macros into + LOC_VEC, so that we can later walk it at our convenience to + display a somewhat meaningful trace of the macro expansion + history to the user. Note that the first macro of the trace + (which is OPERATE in the example above) is going to be stored at + the beginning of LOC_VEC. */ + + do + { + loc.where =3D where; + loc.map =3D map; + + VEC_safe_push (loc_t, heap, loc_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 "down" in the trace 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 + trace by reaching 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 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); + } + } while (linemap_macro_expansion_map_p (map)); + + if (first_exp_point_map) + *first_exp_point_map =3D map; + + /* Walk LOC_VEC and print the macro expansion trace, unless the + first macro which expansion triggered this trace was expanded + inside a system header. */ + if (!LINEMAP_SYSP (resolved_map)) + FOR_EACH_VEC_ELT (loc_t, loc_vec, ix, iter) + { + source_location resolved_def_loc =3D 0, resolved_exp_loc =3D 0; + diagnostic_t saved_kind; + const char *saved_prefix; + source_location saved_location; + + /* 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 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_LOCATION (it= er->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; + } + + VEC_free (loc_t, heap, 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 multiply nested macro expansion, 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