From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 23292 invoked by alias); 17 Oct 2011 10:42:51 -0000 Received: (qmail 23270 invoked by uid 22791); 17 Oct 2011 10:42:47 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW X-Spam-Check-By: sourceware.org Received: from mail-gy0-f175.google.com (HELO mail-gy0-f175.google.com) (209.85.160.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 17 Oct 2011 10:42:30 +0000 Received: by gyc15 with SMTP id 15so3242580gyc.20 for ; Mon, 17 Oct 2011 03:42:29 -0700 (PDT) MIME-Version: 1.0 Received: by 10.182.44.9 with SMTP id a9mr3274221obm.61.1318848149221; Mon, 17 Oct 2011 03:42:29 -0700 (PDT) Received: by 10.182.28.138 with HTTP; Mon, 17 Oct 2011 03:42:29 -0700 (PDT) In-Reply-To: <1318845428-32182-4-git-send-email-dodji@redhat.com> References: <1318845428-32182-1-git-send-email-dodji@redhat.com> <1318845428-32182-4-git-send-email-dodji@redhat.com> Date: Mon, 17 Oct 2011 10:56:00 -0000 Message-ID: Subject: Re: [PATCH 3/6] Emit macro expansion related diagnostics From: Richard Guenther To: Dodji Seketeli Cc: gcc-patches@gcc.gnu.org, jason@redhat.com, tromey@redhat.com, gdr@integrable-solutions.net, joseph@codesourcery.com, burnus@net-b.de, charlet@act-europe.fr Content-Type: text/plain; charset=ISO-8859-1 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-10/txt/msg01484.txt.bz2 On Mon, Oct 17, 2011 at 11:57 AM, Dodji Seketeli wrote: > 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. =A0This 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 > =A0 =A0 1 =A0 =A0#define OPERATE(OPRD1, OPRT, OPRD2) \ > =A0 =A0 2 =A0 =A0 =A0OPRD1 OPRT OPRD2; > =A0 =A0 3 > =A0 =A0 4 =A0 =A0#define SHIFTL(A,B) \ > =A0 =A0 5 =A0 =A0 =A0OPERATE (A,<<,B) > =A0 =A0 6 > =A0 =A0 7 =A0 =A0#define MULT(A) \ > =A0 =A0 8 =A0 =A0 =A0SHIFTL (A,1) > =A0 =A0 9 > =A0 =A010 =A0 =A0void > =A0 =A011 =A0 =A0g () > =A0 =A012 =A0 =A0{ > =A0 =A013 =A0 =A0 =A0MULT (1.0);/* 1.0 << 1; <-- so this is an error. =A0= */ > =A0 =A014 =A0 =A0} > > [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 'in= t') > 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 This broke bootstrap on x86_64-linux. /space/rguenther/src/svn/trunk/libcpp/line-map.c: In function 'source_location linemap_macro_map_loc_to_exp_point(const line_map*, source_location)': /space/rguenther/src/svn/trunk/libcpp/line-map.c:628:12: error: variable 'token_no' set but not used [-Werror=3Dunused-but-set-variable] cc1plus: all warnings being treated as errors make[3]: *** [line-map.o] Error 1 > gcc/ChangeLog > 2011-10-15 =A0Tom Tromey =A0 > =A0 =A0 =A0 =A0 =A0 =A0Dodji Seketeli =A0 > > =A0 =A0 =A0 =A0* gcc/diagnostic.h (diagnostic_report_current_module): Add= a > =A0 =A0 =A0 =A0location parameter. > =A0 =A0 =A0 =A0* diagnostic.c (diagnostic_report_current_module): Add a l= ocation > =A0 =A0 =A0 =A0parameter to the function definition. =A0Use it instead of > =A0 =A0 =A0 =A0input_location. =A0Resolve the virtual location rather tha= n just > =A0 =A0 =A0 =A0looking up its map and risking to touch a resulting macro = map. > =A0 =A0 =A0 =A0(default_diagnostic_starter): Pass the relevant diagnostic > =A0 =A0 =A0 =A0location to diagnostic_report_current_module. > =A0 =A0 =A0 =A0* tree-diagnostic.c (maybe_unwind_expanded_macro_loc): New. > =A0 =A0 =A0 =A0(virt_loc_aware_diagnostic_finalizer): Likewise. > =A0 =A0 =A0 =A0(diagnostic_report_current_function): Pass the > =A0 =A0 =A0 =A0relevant location to diagnostic_report_current_module. > =A0 =A0 =A0 =A0* tree-diagnostic.h (virt_loc_aware_diagnostic_finalizer):= Declare > =A0 =A0 =A0 =A0new function. > =A0 =A0 =A0 =A0* toplev.c (general_init): By default, use the new > =A0 =A0 =A0 =A0virt_loc_aware_diagnostic_finalizer as diagnostic finalize= r. > =A0 =A0 =A0 =A0* Makefile.in: Add vec.h dependency to tree-diagnostic.c. > > gcc/cp/ChangeLog > 2011-10-15 =A0Tom Tromey =A0 > =A0 =A0 =A0 =A0 =A0 =A0Dodji Seketeli =A0 > > =A0 =A0 =A0 =A0* error.c (cp_diagnostic_starter): Pass the relevant locat= ion to > =A0 =A0 =A0 =A0diagnostic_report_current_module. > =A0 =A0 =A0 =A0(cp_diagnostic_finalizer): Call virt_loc_aware_diagnostic_= finalizer. > > gcc/testsuite/ChangeLog > 2011-10-15 =A0Tom Tromey =A0 > =A0 =A0 =A0 =A0 =A0 =A0Dodji Seketeli =A0 > > =A0 =A0 =A0 =A0* lib/prune.exp (prune_gcc_output): =A0Prune output referr= ing to > =A0 =A0 =A0 =A0included files. > =A0 =A0 =A0 =A0* gcc.dg/cpp/macro-exp-tracking-1.c: New test. > =A0 =A0 =A0 =A0* gcc.dg/cpp/macro-exp-tracking-2.c: Likewise. > =A0 =A0 =A0 =A0* gcc.dg/cpp/macro-exp-tracking-3.c: Likewise. > =A0 =A0 =A0 =A0* gcc.dg/cpp/pragma-diagnostic-2.c: Likewise. > > --- > =A0gcc/ChangeLog =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 | =A0 21 +++ > =A0gcc/Makefile.in =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 | =A0 =A03 +- > =A0gcc/cp/ChangeLog =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0| =A0 =A07 + > =A0gcc/cp/error.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= =A0 =A0 =A0| =A0 =A05 +- > =A0gcc/diagnostic.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0| =A0 13 +- > =A0gcc/diagnostic.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0| =A0 =A02 +- > =A0gcc/testsuite/ChangeLog =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 | =A0 10 ++ > =A0gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-1.c | =A0 21 +++ > =A0gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-2.c | =A0 21 +++ > =A0gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-3.c | =A0 14 ++ > =A0gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-4.c | =A0 14 ++ > =A0gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-2.c =A0| =A0 34 +++++ > =A0gcc/testsuite/lib/prune.exp =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 | = =A0 =A01 + > =A0gcc/toplev.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0| =A0 =A03 + > =A0gcc/tree-diagnostic.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 | =A0182 ++++++++++++++++++++++- > =A0gcc/tree-diagnostic.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 | =A0 =A03 +- > =A016 files changed, 343 insertions(+), 11 deletions(-) > =A0create mode 100644 gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-1.c > =A0create mode 100644 gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-2.c > =A0create mode 100644 gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-3.c > =A0create mode 100644 gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-4.c > =A0create mode 100644 gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-2.c > > diff --git a/gcc/Makefile.in b/gcc/Makefile.in > index baec5fe..70dc0b8 100644 > --- a/gcc/Makefile.in > +++ b/gcc/Makefile.in > @@ -2805,7 +2805,8 @@ tree-pretty-print.o : tree-pretty-print.c $(CONFIG_= H) $(SYSTEM_H) \ > =A0 =A0$(TM_H) coretypes.h tree-iterator.h $(SCEV_H) langhooks.h \ > =A0 =A0$(TREE_PASS_H) value-prof.h output.h tree-pretty-print.h > =A0tree-diagnostic.o : tree-diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretype= s.h \ > - =A0 $(TREE_H) $(DIAGNOSTIC_H) tree-diagnostic.h langhooks.h $(LANGHOOKS= _DEF_H) > + =A0 $(TREE_H) $(DIAGNOSTIC_H) tree-diagnostic.h langhooks.h $(LANGHOOKS= _DEF_H) \ > + =A0 $(VEC_H) > =A0fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H= ) \ > =A0 =A0$(TREE_H) $(FLAGS_H) $(DIAGNOSTIC_CORE_H) $(HASHTAB_H) $(EXPR_H) $= (RTL_H) \ > =A0 =A0$(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 4d12a0d..c7c4525 100644 > --- a/gcc/cp/error.c > +++ b/gcc/cp/error.c > @@ -2768,7 +2768,7 @@ static void > =A0cp_diagnostic_starter (diagnostic_context *context, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 diagnostic_info *diagnostic) > =A0{ > - =A0diagnostic_report_current_module (context); > + =A0diagnostic_report_current_module (context, diagnostic->location); > =A0 cp_print_error_function (context, diagnostic); > =A0 maybe_print_instantiation_context (context); > =A0 maybe_print_constexpr_context (context); > @@ -2778,8 +2778,9 @@ cp_diagnostic_starter (diagnostic_context *context, > > =A0static void > =A0cp_diagnostic_finalizer (diagnostic_context *context, > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0diagnostic_info *diagnos= tic ATTRIBUTE_UNUSED) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0diagnostic_info *diagnos= tic) > =A0{ > + =A0virt_loc_aware_diagnostic_finalizer (context, diagnostic); > =A0 pp_base_destroy_prefix (context->printer); > =A0} > > diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c > index b46eb35..a8c0e66 100644 > --- a/gcc/diagnostic.c > +++ b/gcc/diagnostic.c > @@ -255,9 +255,9 @@ diagnostic_action_after_output (diagnostic_context *c= ontext, > =A0} > > =A0void > -diagnostic_report_current_module (diagnostic_context *context) > +diagnostic_report_current_module (diagnostic_context *context, location_= t where) > =A0{ > - =A0const struct line_map *map; > + =A0const struct line_map *map =3D NULL; > > =A0 if (pp_needs_newline (context->printer)) > =A0 =A0 { > @@ -265,10 +265,13 @@ diagnostic_report_current_module (diagnostic_contex= t *context) > =A0 =A0 =A0 pp_needs_newline (context->printer) =3D false; > =A0 =A0 } > > - =A0if (input_location <=3D BUILTINS_LOCATION) > + =A0if (where <=3D BUILTINS_LOCATION) > =A0 =A0 return; > > - =A0map =3D linemap_lookup (line_table, input_location); > + =A0linemap_resolve_location (line_table, where, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 LRK_MACRO_DEFINITIO= N_LOCATION, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 &map); > + > =A0 if (map && diagnostic_last_module_changed (context, map)) > =A0 =A0 { > =A0 =A0 =A0 diagnostic_set_last_module (context, map); > @@ -301,7 +304,7 @@ void > =A0default_diagnostic_starter (diagnostic_context *context, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0diagnostic_info *d= iagnostic) > =A0{ > - =A0diagnostic_report_current_module (context); > + =A0diagnostic_report_current_module (context, diagnostic->location); > =A0 pp_set_prefix (context->printer, diagnostic_build_prefix (context, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0diagnostic)); > =A0} > 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; > =A0/* Diagnostic related functions. =A0*/ > =A0extern void diagnostic_initialize (diagnostic_context *, int); > =A0extern void diagnostic_finish (diagnostic_context *); > -extern void diagnostic_report_current_module (diagnostic_context *); > +extern void diagnostic_report_current_module (diagnostic_context *, loca= tion_t); > > =A0/* Force diagnostics controlled by OPTIDX to be kind KIND. =A0*/ > =A0extern diagnostic_t diagnostic_classify_diagnostic (diagnostic_context= *, > diff --git a/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-1.c b/gcc/testsu= ite/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 @@ > +/* > + =A0 { dg-options "-ftrack-macro-expansion=3D1" } > + =A0 { dg-do compile } > +*/ > + > +#define OPERATE(OPRD1, OPRT, OPRD2) \ > +do \ > +{ \ > + =A0OPRD1 OPRT OPRD2; /* { dg-message "expansion" }*/ =A0 =A0 =A0 \ > +} while (0) > + > +#define SHIFTL(A,B) \ > + =A0OPERATE (A,<<,B) /* { dg-message "expanded|expansion" } */ > + > +void > +foo () > +{ > + =A0SHIFTL (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/testsu= ite/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 @@ > +/* > + =A0 { dg-options "-ftrack-macro-expansion=3D1" } > + =A0 { dg-do compile } > +*/ > + > +#define OPERATE(OPRD1, OPRT, OPRD2) \ > + OPRD1 OPRT OPRD2; =A0 =A0 =A0 =A0 =A0 =A0 /* { dg-message "expansion" }= */ > + > +#define SHIFTL(A,B) \ > + =A0OPERATE (A,<<,B) /* { dg-message "expanded|expansion" } */ > + > +#define MULT(A) \ > + =A0SHIFTL (A,1) =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* { dg-message "expand= ed|expansion" } */ > + > +void > +foo () > +{ > + =A0MULT (1.0); =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* { dg-message "expa= nded" } */ > +} > + > +/* { dg-error "invalid operands to binary <<" "" { target *-*-* } { 10 }= } */ > diff --git a/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-3.c b/gcc/testsu= ite/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 @@ > +/* > + =A0{ dg-options "-fshow-column -ftrack-macro-expansion=3D1" } > + =A0{ dg-do compile } > + */ > + > +#define SQUARE(A) A * A =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* { dg-message "= expansion" } */ > + > +void > +foo() > +{ > + =A0SQUARE (1 << 0.1); =A0 =A0 =A0 =A0 =A0 /* { 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/testsu= ite/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 @@ > +/* > + =A0{ dg-options "-fshow-column -ftrack-macro-expansion=3D2" } > + =A0{ dg-do compile } > + */ > + > +#define SQUARE(A) A * A =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* { dg-message "= expansion" } */ > + > +void > +foo() > +{ > + =A0SQUARE (1 << 0.1); =A0 =A0 =A0 =A0 =A0 /* { dg-message "expanded" } = */ > +} > + > +/* { dg-error "13:invalid operands to binary <<" "" { target *-*-* } { 1= 1 } } */ > diff --git a/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-2.c b/gcc/testsui= te/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 @@ > +/* > + =A0{ dg-options "-Wuninitialized -ftrack-macro-expansion=3D2" } > + =A0{ dg-do compile } > +*/ > + > +void f (unsigned); > + > +#define CODE_WITH_WARNING \ > + =A0int a; /* { dg-message "expansion|declared here" } */ =A0\ > + =A0f (a) =A0 =A0 =A0 =A0 /* { dg-message "expansion" } */ > + > +#pragma GCC diagnostic ignored "-Wuninitialized" > + > +void > +g (void) > +{ > + =A0CODE_WITH_WARNING; > +} > + > +#pragma GCC diagnostic push > + > +#pragma GCC diagnostic error "-Wuninitialized" > + > +void > +h (void) > +{ > + =A0CODE_WITH_WARNING; =A0 =A0 =A0 =A0 =A0 /* { dg-message "expanded" } = */ > +} > + > +/* > + =A0{ 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 } { > =A0 =A0 regsub -all "(^|\n)collect: re(compiling|linking)\[^\n\]*" $text = "" text > =A0 =A0 regsub -all "(^|\n)Please submit.*instructions\[^\n\]*" $text "" = text > =A0 =A0 regsub -all "(^|\n)\[0-9\]\[0-9\]* errors\." $text "" text > + =A0 =A0regsub -all "(^|\n)(In file included|\[ \]+from)\[^\n\]*" $text = "" text > > =A0 =A0 # Ignore informational notes. > =A0 =A0 regsub -all "(^|\n)\[^\n\]*: note: \[^\n\]*" $text "" text > diff --git a/gcc/toplev.c b/gcc/toplev.c > index ab6b5a4..0188755 100644 > --- a/gcc/toplev.c > +++ b/gcc/toplev.c > @@ -1171,6 +1171,9 @@ general_init (const char *argv0) > =A0 =A0 =A0can give warnings and errors. =A0*/ > =A0 diagnostic_initialize (global_dc, N_OPTS); > =A0 diagnostic_starter (global_dc) =3D default_tree_diagnostic_starter; > + =A0/* By default print macro expansion contexts in the diagnostic > + =A0 =A0 finalizer -- for tokens resulting from macro macro expansion. = =A0*/ > + =A0diagnostic_finalizer (global_dc) =3D virt_loc_aware_diagnostic_final= izer; > =A0 /* Set a default printer. =A0Language specific initializations will > =A0 =A0 =A0override it later. =A0*/ > =A0 pp_format_decoder (global_dc->printer) =3D &default_tree_printer; > diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c > index b456a2a..53b350b 100644 > --- a/gcc/tree-diagnostic.c > +++ b/gcc/tree-diagnostic.c > @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. =A0If not see > =A0#include "tree-diagnostic.h" > =A0#include "langhooks.h" > =A0#include "langhooks-def.h" > +#include "vec.h" > > =A0/* Prints out, if necessary, the name of the current function > =A0 =A0that caused an error. =A0Called from all error and warning functio= ns. =A0*/ > @@ -35,7 +36,7 @@ void > =A0diagnostic_report_current_function (diagnostic_context *context, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0di= agnostic_info *diagnostic) > =A0{ > - =A0diagnostic_report_current_module (context); > + =A0diagnostic_report_current_module (context, diagnostic->location); > =A0 lang_hooks.print_error_function (context, input_filename, diagnostic); > =A0} > > @@ -47,3 +48,182 @@ default_tree_diagnostic_starter (diagnostic_context *= context, > =A0 pp_set_prefix (context->printer, diagnostic_build_prefix (context, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0diagnostic)); > =A0} > + > +/* This is a pair made of a location and the line map it originated > + =A0 from. =A0It's used in the maybe_unwind_expanded_macro_loc function > + =A0 below. =A0*/ > +typedef struct > +{ > + =A0const struct line_map *map; > + =A0source_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 > + =A0 location is WHERE and emit diagnostics showing the resulting > + =A0 unwound macro expansion trace. =A0Let's look at an example to see h= ow > + =A0 the trace looks like. =A0Suppose we have this piece of code, > + =A0 artificially annotated with the line numbers to increase > + =A0 legibility: > + > + =A0 =A0$ cat -n test.c > + =A0 =A0 =A01 =A0 =A0#define OPERATE(OPRD1, OPRT, OPRD2) \ > + =A0 =A0 =A02 =A0 =A0 =A0OPRD1 OPRT OPRD2; > + =A0 =A0 =A03 > + =A0 =A0 =A04 =A0 =A0#define SHIFTL(A,B) \ > + =A0 =A0 =A05 =A0 =A0 =A0OPERATE (A,<<,B) > + =A0 =A0 =A06 > + =A0 =A0 =A07 =A0 =A0#define MULT(A) \ > + =A0 =A0 =A08 =A0 =A0 =A0SHIFTL (A,1) > + =A0 =A0 =A09 > + =A0 =A0 10 =A0 =A0void > + =A0 =A0 11 =A0 =A0g () > + =A0 =A0 12 =A0 =A0{ > + =A0 =A0 13 =A0 =A0 =A0MULT (1.0);// 1.0 << 1; <-- so this is an error. > + =A0 =A0 14 =A0 =A0} > + > + =A0 Here is the diagnostic that we want the compiler to generate: > + > + =A0 =A0test.c: In function 'g': > + =A0 =A0test.c:5:14: error: invalid operands to binary << (have 'double'= and 'int') > + =A0 =A0test.c:2:9: note: in expansion of macro 'OPERATE' > + =A0 =A0test.c:5:3: note: expanded from here > + =A0 =A0test.c:5:14: note: in expansion of macro 'SHIFTL' > + =A0 =A0test.c:8:3: note: expanded from here > + =A0 =A0test.c:8:3: note: in expansion of macro 'MULT2' > + =A0 =A0test.c:13:3: note: expanded from here > + > + =A0 The part that goes from the third to the eighth line of this > + =A0 diagnostic (the lines containing the 'note:' string) is called the > + =A0 unwound macro expansion trace. =A0That's the part generated by this > + =A0 function. > + > + =A0 If FIRST_EXP_POINT_MAP is non-null, *FIRST_EXP_POINT_MAP is set to > + =A0 the map of the location in the source that first triggered the > + =A0 macro expansion. =A0This must be an ordinary map. =A0*/ > + > +static void > +maybe_unwind_expanded_macro_loc (diagnostic_context *context, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 diagnos= tic_info *diagnostic, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 source_= location where, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 const s= truct line_map **first_exp_point_map) > +{ > + =A0const struct line_map *map; > + =A0VEC(loc_t,heap) *loc_vec =3D NULL; > + =A0unsigned ix; > + =A0loc_t loc, *iter; > + > + =A0map =3D linemap_lookup (line_table, where); > + =A0if (!linemap_macro_expansion_map_p (map)) > + =A0 =A0return; > + > + =A0/* Let's unwind the macros that got expanded and led to the token > + =A0 =A0 which location is WHERE. =A0We are going to store these macros = into > + =A0 =A0 LOC_VEC, so that we can later walk it at our convenience to > + =A0 =A0 display a somewhat meaningful trace of the macro expansion > + =A0 =A0 history to the user. =A0Note that the first macro of the trace > + =A0 =A0 (which is OPERATE in the example above) is going to be stored at > + =A0 =A0 the beginning of LOC_VEC. =A0*/ > + > + =A0do > + =A0 =A0{ > + =A0 =A0 =A0loc.where =3D where; > + =A0 =A0 =A0loc.map =3D map; > + > + =A0 =A0 =A0VEC_safe_push (loc_t, heap, loc_vec, &loc); > + > + =A0 =A0 =A0/* WHERE is the location of a token inside the expansion of a > + =A0 =A0 =A0 =A0 macro. =A0MAP is the map holding the locations of that = macro > + =A0 =A0 =A0 =A0 expansion. =A0Let's get the location of the token insid= e the > + =A0 =A0 =A0 =A0 context that triggered the expansion of this macro. > + =A0 =A0 =A0 =A0 This is basically how we go "down" in the trace of macro > + =A0 =A0 =A0 =A0 expansions that led to WHERE. =A0*/ > + =A0 =A0 =A0where =3D linemap_unwind_toward_expansion (line_table, where= , &map); > + =A0 =A0} while (linemap_macro_expansion_map_p (map)); > + > + =A0if (first_exp_point_map) > + =A0 =A0*first_exp_point_map =3D map; > + > + =A0/* Walk LOC_VEC and print the macro expansion trace, unless the > + =A0 =A0 first macro which expansion triggered this trace was expanded > + =A0 =A0 inside a system header. =A0*/ > + =A0if (!LINEMAP_SYSP (map)) > + =A0 =A0FOR_EACH_VEC_ELT (loc_t, loc_vec, ix, iter) > + =A0 =A0 =A0{ > + =A0 =A0 =A0 =A0source_location resolved_def_loc =3D 0, resolved_exp_loc= =3D 0; > + =A0 =A0 =A0 =A0diagnostic_t saved_kind; > + =A0 =A0 =A0 =A0const char *saved_prefix; > + =A0 =A0 =A0 =A0source_location saved_location; > + > + =A0 =A0 =A0 =A0/* Okay, now here is what we want. =A0For each token res= ulting > + =A0 =A0 =A0 =A0 =A0 from macro expansion we want to show: 1/ where in t= he > + =A0 =A0 =A0 =A0 =A0 definition of the macro the token comes from; 2/ wh= ere the > + =A0 =A0 =A0 =A0 =A0 macro got expanded. =A0*/ > + > + =A0 =A0 =A0 =A0/* Resolve the location iter->where into the locus 1/ of= the > + =A0 =A0 =A0 =A0 =A0 comment above. =A0*/ > + =A0 =A0 =A0 =A0resolved_def_loc =3D > + =A0 =A0 =A0 =A0 =A0linemap_resolve_location (line_table, iter->where, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= LRK_MACRO_DEFINITION_LOCATION, NULL); > + > + =A0 =A0 =A0 =A0/* Resolve the location of the expansion point of the ma= cro > + =A0 =A0 =A0 =A0 =A0 which expansion gave the token represented by def_l= oc. > + =A0 =A0 =A0 =A0 =A0 This is the locus 2/ of the earlier comment. =A0*/ > + =A0 =A0 =A0 =A0resolved_exp_loc =3D > + =A0 =A0 =A0 =A0 =A0linemap_resolve_location (line_table, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= MACRO_MAP_EXPANSION_POINT_LOCATION (iter->map), > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= LRK_MACRO_DEFINITION_LOCATION, NULL); > + > + =A0 =A0 =A0 =A0saved_kind =3D diagnostic->kind; > + =A0 =A0 =A0 =A0saved_prefix =3D context->printer->prefix; > + =A0 =A0 =A0 =A0saved_location =3D diagnostic->location; > + > + =A0 =A0 =A0 =A0diagnostic->kind =3D DK_NOTE; > + =A0 =A0 =A0 =A0diagnostic->location =3D resolved_def_loc; > + =A0 =A0 =A0 =A0pp_base_set_prefix (context->printer, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0diagnostic_build= _prefix (context, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 diagnostic)); > + =A0 =A0 =A0 =A0pp_newline (context->printer); > + =A0 =A0 =A0 =A0pp_printf (context->printer, "in expansion of macro '%s'= ", > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 linemap_map_get_macro_name (iter->m= ap)); > + =A0 =A0 =A0 =A0pp_destroy_prefix (context->printer); > + > + =A0 =A0 =A0 =A0diagnostic->location =3D resolved_exp_loc; > + =A0 =A0 =A0 =A0pp_base_set_prefix (context->printer, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0diagnostic_build= _prefix (context, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 diagnostic)); > + =A0 =A0 =A0 =A0pp_newline (context->printer); > + =A0 =A0 =A0 =A0pp_printf (context->printer, "expanded from here"); > + =A0 =A0 =A0 =A0pp_destroy_prefix (context->printer); > + > + =A0 =A0 =A0 =A0diagnostic->kind =3D saved_kind; > + =A0 =A0 =A0 =A0diagnostic->location =3D saved_location; > + =A0 =A0 =A0 =A0context->printer->prefix =3D saved_prefix; > + =A0 =A0 =A0} > + > + =A0VEC_free (loc_t, heap, loc_vec); > +} > + > +/* =A0This is a diagnostic finalizer implementation that is aware of > + =A0 =A0virtual locations produced by libcpp. > + > + =A0 =A0It has to be called by the diagnostic finalizer of front ends th= at > + =A0 =A0uses libcpp and wish to get diagnostics involving tokens resulti= ng > + =A0 =A0from macro expansion. > + > + =A0 =A0For a given location, if said location belongs to a token > + =A0 =A0resulting from a macro expansion, this starter prints the context > + =A0 =A0of the token. =A0E.g, for multiply nested macro expansion, it > + =A0 =A0unwinds the nested macro expansions and prints them in a manner > + =A0 =A0that is similar to what is done for function call stacks, or > + =A0 =A0template instantiation contexts. =A0*/ > +void > +virt_loc_aware_diagnostic_finalizer (diagnostic_context *context, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= diagnostic_info *diagnostic) > +{ > + =A0maybe_unwind_expanded_macro_loc (context, diagnostic, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0diag= nostic->location, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0NULL= ); > +} > 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. =A0If not see > =A0void default_tree_diagnostic_starter (diagnostic_context *, diagnostic= _info *); > =A0extern void diagnostic_report_current_function (diagnostic_context *, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0 =A0diagnostic_info *); > - > +void virt_loc_aware_diagnostic_finalizer (diagnostic_context *, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0= =A0 =A0 diagnostic_info *); > =A0#endif /* ! GCC_TREE_DIAGNOSTIC_H */ > -- > 1.7.6.4 > >