[PATCH] Support printing inlining call stack in diagnostic messages

Jakub Jelinek jakub@redhat.com
Mon Sep 10 12:23:00 GMT 2007


On Fri, Aug 31, 2007 at 03:25:12PM -0400, Daniel Jacobowitz wrote:
> On Fri, Aug 31, 2007 at 03:05:20PM -0400, Jakub Jelinek wrote:
> > Currently, the above will generate compile time warning about buffer
> > overflow in a wrong spot:
> > nn.c: In function 'foo':
> > nn.c:12: warning: call to __builtin___memcpy_chk will always overflow destination buffer
> > While the function name is right, the file and line number points into
> > the glibc headers, so doesn't help much location the error.
> 
> Would this be better?
> 
> nn.c: In function 'memcpy':
> nn.c:12: warning: call to __builtin___memcpy_chk will always overflow destination buffer
> nn.c:18: note: inlined from here

If so, I think it would be better to do this instead of the builtins.c
hunk of that patch:

For
# 1 "builtin-stringop-chk-3.c"
# 1 "builtin-stringop-chk-1.h" 1
# 1 "builtin-stringop-chk-2.h" 1

char buf[4];
extern inline __attribute__((always_inline, gnu_inline)) int foo (void)
{
  __builtin___memcpy_chk (buf, "abcd", 5, __builtin_object_size (buf, 0));
  return 4;
}

# 2 "builtin-stringop-chk-1.h" 2

extern inline __attribute__((always_inline, gnu_inline)) int bar (void)
{
  buf[2] = 'b';
  foo ();
  return 6;
}

# 2 "builtin-stringop-chk-3.c" 2

int baz (void)
{
  bar ();
  return 5;
}

GCC currently prints:
builtin-stringop-chk-2.h: In function 'baz':
builtin-stringop-chk-2.h:5: warning: call to __builtin___memcpy_chk will always overflow destination buffer

which is not very useful for fixing the diagnosed problem and
is very inconsistent.  The "In function" part reports the ultimate
function this has been inlined into, while the file/line comes
from within the innermost inlined function.
With the patch below it instead prints:

LC_ALL=C ./xgcc -B ./ -O2 builtin-stringop-chk-3.c -S
In function 'foo',
    inlined from 'bar' at builtin-stringop-chk-1.h:6,
    inlined from 'baz' at builtin-stringop-chk-3.c:5:
builtin-stringop-chk-2.h:5: warning: call to __builtin___memcpy_chk will always overflow destination buffer
LC_ALL=C ./xgcc -B ./ -O2 -xc++ builtin-stringop-chk-3.c -S
In function 'int foo()',
    inlined from 'int bar()' at builtin-stringop-chk-1.h:6,
    inlined from 'int baz()' at builtin-stringop-chk-3.c:5:
builtin-stringop-chk-2.h:5: warning: call to void* __builtin___memcpy_chk(void*, const void*, long unsigned int, long unsigned int) will always overflow destination buffer

which allows the compiler user to locate precisely where the
bug is.  I have just changed 3 diagnostic messages to use it,
but IMHO it is generally useful for most of the diagnostic
messages emitted after inlining, e.g. during expansion.

I haven't figured out yet how to teach dejagnu about this,
couldn't find where it ignores the already before this patch
emitted
builtin-stringop-chk-2.h: In function 'baz':
style lines, Janis, any ideas on this?

Another thing is that without -g the virtual backtrace is sometimes
incomplete, e.g. on the above testcase without the buf[2] = 'b';
statement prints
LC_ALL=C ./xgcc -B ./ -O2 -S builtin-stringop-chk-3.c
In function 'foo',
    inlined from 'baz' at builtin-stringop-chk-1.h:5:
builtin-stringop-chk-2.h:5: warning: call to __builtin___memcpy_chk will always overflow destination buffer
LC_ALL=C ./xgcc -B ./ -O2 -g -S builtin-stringop-chk-3.c
In function 'foo',
    inlined from 'bar' at builtin-stringop-chk-1.h:5,
    inlined from 'baz' at builtin-stringop-chk-3.c:5:
builtin-stringop-chk-2.h:5: warning: call to __builtin___memcpy_chk will always overflow destination buffer

So I'm not sure if we just shouldn't enable this more precise
printing with write_symbols != NO_DEBUG and for -g0 just do
what we did before.

2007-09-10  Jakub Jelinek  <jakub@redhat.com>

	* builtins.c (expand_builtin): Use new %K format string specifier
	for diagnostics.
	(expand_builtin_memory_chk): Likewise.
	* langhooks-def.h (lhd_print_error_function): Add third argument.
	* langhooks.h (struct diagnostic_info): Add forward decl.
	(struct lang_hooks): Add third argument to print_error_function.
	* diagnostic.h (diagnostic_info): Add abstract_origin field.
	(diagnostic_last_function_changed, diagnostic_set_last_function): Add
	second argument.
	(diagnostic_report_current_function): Likewise.
	* toplev.c (announce_function): Pass NULL as second argument to
	diagnostic_set_last_function.
	* diagnostic.c (diagnostic_report_current_function): Add second
	argument, pass it as third argument to lang_hooks.print_error_function.
	(default_diagnostic_starter): Pass DIAGNOSTIC as second argument
	to diagnostic_report_current_function.
	(diagnostic_report_diagnostic): Initialize diagnostic->abstract_origin
	and message.abstract_origin.
	(verbatim): Initialize abstract_origin.
	* pretty-print.h (text_info): Add abstract_origin field.
	* pretty-print.c (pp_base_format): Handle %K.
	* langhooks.c (lhd_print_error_function): Add third argument.  If
	diagnostic->abstract_origin, print virtual backtrace.
	* c-format.c (gcc_diag_char_table, gcc_tdiag_char_table,
	gcc_cdiag_char_table, gcc_cxxdiag_char_table): Support %K.
	(init_dynamic_diag_info): Likewise.
cp/
	* error.c (cxx_print_error_function): Add third argument, pass
	it over to lhd_print_error_function.
	(cp_print_error_function): If diagnostic->abstract_origin, print
	virtual backtrace.
	* cp-tree.h (struct diagnostic_info): New forward decl.
	(cxx_print_error_function): Add third argument.
java/
	* lang.c (java_print_error_function): Add third argument.

--- gcc/builtins.c.jj	2007-09-08 09:58:45.000000000 +0200
+++ gcc/builtins.c	2007-09-10 11:58:42.000000000 +0200
@@ -6273,13 +6273,13 @@ expand_builtin (tree exp, rtx target, rt
     case BUILT_IN_VA_ARG_PACK:
       /* All valid uses of __builtin_va_arg_pack () are removed during
 	 inlining.  */
-      error ("invalid use of %<__builtin_va_arg_pack ()%>");
+      error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
       return const0_rtx;
 
     case BUILT_IN_VA_ARG_PACK_LEN:
       /* All valid uses of __builtin_va_arg_pack_len () are removed during
 	 inlining.  */
-      error ("invalid use of %<__builtin_va_arg_pack_len ()%>");
+      error ("%Kinvalid use of %<__builtin_va_arg_pack_len ()%>", exp);
       return const0_rtx;
 
       /* Return the address of the first anonymous stack arg.  */
@@ -11527,9 +11527,8 @@ expand_builtin_memory_chk (tree exp, rtx
 
       if (! integer_all_onesp (size) && tree_int_cst_lt (size, len))
 	{
-	  location_t locus = EXPR_LOCATION (exp);
-	  warning (0, "%Hcall to %D will always overflow destination buffer",
-		   &locus, get_callee_fndecl (exp));
+	  warning (0, "%Kcall to %D will always overflow destination buffer",
+		   exp, get_callee_fndecl (exp));
 	  return NULL_RTX;
 	}
 
--- gcc/langhooks-def.h.jj	2007-08-27 10:15:33.000000000 +0200
+++ gcc/langhooks-def.h	2007-09-10 10:25:13.000000000 +0200
@@ -53,7 +53,7 @@ extern int lhd_types_compatible_p (tree,
 extern rtx lhd_expand_expr (tree, rtx, enum machine_mode, int, rtx *);
 extern int lhd_expand_decl (tree);
 extern void lhd_print_error_function (struct diagnostic_context *,
-				      const char *);
+				      const char *, struct diagnostic_info *);
 extern void lhd_set_decl_assembler_name (tree);
 extern bool lhd_warn_unused_global_decl (const_tree);
 extern void lhd_incomplete_type_error (const_tree, const_tree);
--- gcc/langhooks.h.jj	2007-08-27 10:15:33.000000000 +0200
+++ gcc/langhooks.h	2007-09-10 10:25:28.000000000 +0200
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  
 /* This file should be #include-d after tree.h.  */
 
 struct diagnostic_context;
+struct diagnostic_info;
 
 struct gimplify_omp_ctx;
 
@@ -361,7 +362,8 @@ struct lang_hooks
   tree (*lang_get_callee_fndecl) (const_tree);
 
   /* Called by report_error_function to print out function name.  */
-  void (*print_error_function) (struct diagnostic_context *, const char *);
+  void (*print_error_function) (struct diagnostic_context *, const char *,
+				struct diagnostic_info *);
 
   /* Called from expr_size to calculate the size of the value of an
      expression in a language-dependent way.  Returns a tree for the size
--- gcc/diagnostic.h.jj	2007-08-13 15:11:18.000000000 +0200
+++ gcc/diagnostic.h	2007-09-10 11:02:29.000000000 +0200
@@ -37,10 +37,13 @@ typedef enum
 /* A diagnostic is described by the MESSAGE to send, the FILE and LINE of
    its context and its KIND (ice, error, warning, note, ...)  See complete
    list in diagnostic.def.  */
-typedef struct
+typedef struct diagnostic_info
 {
   text_info message;
   location_t location;
+  /* TREE_BLOCK if the diagnostic is to be reported in some inline
+     function inlined into other function, otherwise NULL.  */
+  tree abstract_origin;
   /* The kind of diagnostic it is about.  */
   diagnostic_t kind;
   /* Which OPT_* directly controls this diagnostic.  */
@@ -137,13 +140,15 @@ struct diagnostic_context
 
 /* True if the last function in which a diagnostic was reported is
    different from the current one.  */
-#define diagnostic_last_function_changed(DC) \
-  ((DC)->last_function != current_function_decl)
+#define diagnostic_last_function_changed(DC, DI) \
+  ((DC)->last_function != ((DI)->abstract_origin \
+			   ? (DI)->abstract_origin : current_function_decl))
 
 /* Remember the current function as being the last one in which we report
    a diagnostic.  */
-#define diagnostic_set_last_function(DC) \
-  (DC)->last_function = current_function_decl
+#define diagnostic_set_last_function(DC, DI) \
+  (DC)->last_function = (((DI) && (DI)->abstract_origin) \
+			 ? (DI)->abstract_origin : current_function_decl)
 
 /* True if the last module or file in which a diagnostic was reported is
    different from the current one.  */
@@ -185,7 +190,8 @@ extern diagnostic_context *global_dc;
 /* Diagnostic related functions.  */
 extern void diagnostic_initialize (diagnostic_context *);
 extern void diagnostic_report_current_module (diagnostic_context *);
-extern void diagnostic_report_current_function (diagnostic_context *);
+extern void diagnostic_report_current_function (diagnostic_context *,
+						diagnostic_info *);
 
 /* Force diagnostics controlled by OPTIDX to be kind KIND.  */
 extern diagnostic_t diagnostic_classify_diagnostic (diagnostic_context *,
--- gcc/toplev.c.jj	2007-09-07 10:29:37.000000000 +0200
+++ gcc/toplev.c	2007-09-10 11:07:34.000000000 +0200
@@ -440,7 +440,7 @@ announce_function (tree decl)
 	fprintf (stderr, " %s", lang_hooks.decl_printable_name (decl, 2));
       fflush (stderr);
       pp_needs_newline (global_dc->printer) = true;
-      diagnostic_set_last_function (global_dc);
+      diagnostic_set_last_function (global_dc, (diagnostic_info *) NULL);
     }
 }
 
--- gcc/diagnostic.c.jj	2007-08-13 15:11:18.000000000 +0200
+++ gcc/diagnostic.c	2007-09-10 12:14:55.000000000 +0200
@@ -261,10 +261,11 @@ diagnostic_action_after_output (diagnost
 /* Prints out, if necessary, the name of the current function
    that caused an error.  Called from all error and warning functions.  */
 void
-diagnostic_report_current_function (diagnostic_context *context)
+diagnostic_report_current_function (diagnostic_context *context,
+				    diagnostic_info *diagnostic)
 {
   diagnostic_report_current_module (context);
-  lang_hooks.print_error_function (context, input_filename);
+  lang_hooks.print_error_function (context, input_filename, diagnostic);
 }
 
 void
@@ -302,7 +303,7 @@ static void
 default_diagnostic_starter (diagnostic_context *context,
 			    diagnostic_info *diagnostic)
 {
-  diagnostic_report_current_function (context);
+  diagnostic_report_current_function (context, diagnostic);
   pp_set_prefix (context->printer, diagnostic_build_prefix (diagnostic));
 }
 
@@ -414,6 +415,8 @@ diagnostic_report_diagnostic (diagnostic
 		      " [", cl_options[diagnostic->option_index].opt_text, "]", NULL));
 
       diagnostic->message.locus = &diagnostic->location;
+      diagnostic->message.abstract_origin = &diagnostic->abstract_origin;
+      diagnostic->abstract_origin = NULL;
       pp_format (context->printer, &diagnostic->message);
       (*diagnostic_starter (context)) (context, diagnostic);
       pp_output_formatted_text (context->printer);
@@ -421,6 +424,7 @@ diagnostic_report_diagnostic (diagnostic
       pp_flush (context->printer);
       diagnostic_action_after_output (context, diagnostic);
       diagnostic->message.format_spec = saved_format_spec;
+      diagnostic->abstract_origin = NULL;
     }
 
   context->lock--;
@@ -472,6 +476,7 @@ verbatim (const char *gmsgid, ...)
   text.args_ptr = ≈
   text.format_spec = _(gmsgid);
   text.locus = NULL;
+  text.abstract_origin = NULL;
   pp_format_verbatim (global_dc->printer, &text);
   pp_flush (global_dc->printer);
   va_end (ap);
--- gcc/pretty-print.h.jj	2007-08-13 15:11:18.000000000 +0200
+++ gcc/pretty-print.h	2007-09-10 10:03:12.000000000 +0200
@@ -35,6 +35,7 @@ typedef struct
   va_list *args_ptr;
   int err_no;  /* for %m */
   location_t *locus;
+  tree *abstract_origin;
 } text_info;
 
 /* How often diagnostics are prefixed by their locations:
--- gcc/pretty-print.c.jj	2007-09-04 23:09:30.000000000 +0200
+++ gcc/pretty-print.c	2007-09-10 10:18:47.000000000 +0200
@@ -187,6 +187,7 @@ pp_base_indent (pretty_printer *pp)
    %Ns: likewise, but length specified as constant in the format string.
    %H: location_t.
    %J: a decl tree, from which DECL_SOURCE_LOCATION will be recorded.
+   %K: a statement, from which EXPR_LOCATION and TREE_BLOCK will be recorded.
    Flag 'q': quote formatted text (must come immediately after '%').
 
    Arguments can be used sequentially, or through %N$ resp. *N$
@@ -486,6 +487,33 @@ pp_base_format (pretty_printer *pp, text
 	  }
 	  break;
 
+	case 'K':
+	  {
+	    tree t = va_arg (*text->args_ptr, tree), block;
+	    gcc_assert (text->locus != NULL);
+	    *text->locus = EXPR_LOCATION (t);
+	    gcc_assert (text->abstract_origin != NULL);
+	    block = TREE_BLOCK (t);
+	    *text->abstract_origin = NULL;
+	    while (block
+		   && TREE_CODE (block) == BLOCK
+		   && BLOCK_ABSTRACT_ORIGIN (block))
+	      {
+		tree ao = BLOCK_ABSTRACT_ORIGIN (block);
+
+		while (TREE_CODE (ao) == BLOCK && BLOCK_ABSTRACT_ORIGIN (ao))
+		  ao = BLOCK_ABSTRACT_ORIGIN (ao);
+
+		if (TREE_CODE (ao) == FUNCTION_DECL)
+		  {
+		    *text->abstract_origin = block;
+		    break;
+		  }
+		block = BLOCK_SUPERCONTEXT (block);
+	      }
+	  }
+	  break;
+
 	case '.':
 	  {
 	    int n;
--- gcc/langhooks.c.jj	2007-08-28 11:38:37.000000000 +0200
+++ gcc/langhooks.c	2007-09-10 11:27:31.000000000 +0200
@@ -381,12 +381,15 @@ lhd_initialize_diagnostics (struct diagn
 /* The default function to print out name of current function that caused
    an error.  */
 void
-lhd_print_error_function (diagnostic_context *context, const char *file)
+lhd_print_error_function (diagnostic_context *context, const char *file,
+			  diagnostic_info *diagnostic)
 {
-  if (diagnostic_last_function_changed (context))
+  if (diagnostic_last_function_changed (context, diagnostic))
     {
       const char *old_prefix = context->printer->prefix;
-      char *new_prefix = file ? file_name_as_prefix (file) : NULL;
+      tree abstract_origin = diagnostic->abstract_origin;
+      char *new_prefix = (file && abstract_origin == NULL)
+			 ? file_name_as_prefix (file) : NULL;
 
       pp_set_prefix (context->printer, new_prefix);
 
@@ -394,17 +397,95 @@ lhd_print_error_function (diagnostic_con
 	pp_printf (context->printer, _("At top level:"));
       else
 	{
-	  if (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE)
+	  tree fndecl, ao;
+
+	  if (abstract_origin)
+	    {
+	      ao = BLOCK_ABSTRACT_ORIGIN (abstract_origin);
+	      while (TREE_CODE (ao) == BLOCK && BLOCK_ABSTRACT_ORIGIN (ao))
+		ao = BLOCK_ABSTRACT_ORIGIN (ao);
+	      gcc_assert (TREE_CODE (ao) == FUNCTION_DECL);
+	      fndecl = ao;
+	    }
+	  else
+	    fndecl = current_function_decl;
+
+	  if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE)
 	    pp_printf
-	      (context->printer, _("In member function %qs:"),
-	       lang_hooks.decl_printable_name (current_function_decl, 2));
+	      (context->printer, _("In member function %qs"),
+	       lang_hooks.decl_printable_name (fndecl, 2));
 	  else
 	    pp_printf
-	      (context->printer, _("In function %qs:"),
-	       lang_hooks.decl_printable_name (current_function_decl, 2));
+	      (context->printer, _("In function %qs"),
+	       lang_hooks.decl_printable_name (fndecl, 2));
+
+	  while (abstract_origin)
+	    {
+	      location_t *locus;
+	      tree block = abstract_origin;
+
+	      locus = &BLOCK_SOURCE_LOCATION (block);
+	      fndecl = NULL;
+	      block = BLOCK_SUPERCONTEXT (block);
+	      while (block && TREE_CODE (block) == BLOCK
+		     && BLOCK_ABSTRACT_ORIGIN (block))
+		{
+		  ao = BLOCK_ABSTRACT_ORIGIN (block);
+
+		  while (TREE_CODE (ao) == BLOCK && BLOCK_ABSTRACT_ORIGIN (ao))
+		    ao = BLOCK_ABSTRACT_ORIGIN (ao);
+
+		  if (TREE_CODE (ao) == FUNCTION_DECL)
+		    {
+		      fndecl = ao;
+		      break;
+		    }
+		  else if (TREE_CODE (ao) != BLOCK)
+		    break;
+
+		  block = BLOCK_SUPERCONTEXT (block);
+		}
+	      if (fndecl)
+		abstract_origin = block;
+	      else
+		{
+		  while (block && TREE_CODE (block) == BLOCK)
+		    block = BLOCK_SUPERCONTEXT (block);
+
+		  if (TREE_CODE (block) == FUNCTION_DECL)
+		    fndecl = block;
+		  abstract_origin = NULL;
+		}
+	      if (fndecl)
+		{
+		  expanded_location s = expand_location (*locus);
+		  pp_character (context->printer, ',');
+		  pp_newline (context->printer);
+		  if (s.file != NULL)
+		    {
+#ifdef USE_MAPPED_LOCATION
+		      if (flag_show_column && s.column != 0)
+			pp_printf (context->printer,
+				   _("    inlined from %qs at %s:%d:%d"),
+				   lang_hooks.decl_printable_name (fndecl, 2),
+				   s.file, s.line, s.column);
+		      else
+#endif
+			pp_printf (context->printer,
+				   _("    inlined from %qs at %s:%d"),
+				   lang_hooks.decl_printable_name (fndecl, 2),
+				   s.file, s.line);
+
+		    }
+		  else
+		    pp_printf (context->printer, _("    inlined from %qs"),
+			       lang_hooks.decl_printable_name (fndecl, 2));
+		}
+	    }
+	  pp_character (context->printer, ':');
 	}
 
-      diagnostic_set_last_function (context);
+      diagnostic_set_last_function (context, diagnostic);
       pp_flush (context->printer);
       context->printer->prefix = old_prefix;
       free ((char*) new_prefix);
--- gcc/c-format.c.jj	2007-09-05 21:38:53.000000000 +0200
+++ gcc/c-format.c	2007-09-10 11:06:39.000000000 +0200
@@ -559,7 +559,7 @@ static const format_char_info gcc_diag_c
   { "H",   0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
 
   /* These will require a "tree" at runtime.  */
-  { "J", 0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",    "",   NULL },
+  { "JK", 0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",    "",   NULL },
 
   { "<>'", 0, STD_C89, NOARGUMENTS, "",      "",   NULL },
   { "m",   0, STD_C89, NOARGUMENTS, "q",     "",   NULL },
@@ -582,7 +582,7 @@ static const format_char_info gcc_tdiag_
   { "H",   0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
 
   /* These will require a "tree" at runtime.  */
-  { "DFJT", 0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+", "",   NULL },
+  { "DFJKT", 0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+", "",   NULL },
 
   { "<>'", 0, STD_C89, NOARGUMENTS, "",      "",   NULL },
   { "m",   0, STD_C89, NOARGUMENTS, "q",     "",   NULL },
@@ -605,7 +605,7 @@ static const format_char_info gcc_cdiag_
   { "H",   0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
 
   /* These will require a "tree" at runtime.  */
-  { "DEFJT", 0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+", "",   NULL },
+  { "DEFJKT", 0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+", "",   NULL },
 
   { "<>'", 0, STD_C89, NOARGUMENTS, "",      "",   NULL },
   { "m",   0, STD_C89, NOARGUMENTS, "q",     "",   NULL },
@@ -628,7 +628,7 @@ static const format_char_info gcc_cxxdia
   { "H",   0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
 
   /* These will require a "tree" at runtime.  */
-  { "ADEFJTV",0,STD_C89,{ T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+#",   "",   NULL },
+  { "ADEFJKTV",0,STD_C89,{ T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+#",   "",   NULL },
 
   /* These accept either an 'int' or an 'enum tree_code' (which is handled as an 'int'.)  */
   { "CLOPQ",0,STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
@@ -2599,6 +2599,9 @@ init_dynamic_diag_info (void)
 	  i = find_char_info_specifier_index (diag_fci, 'J');
 	  diag_fci[i].types[0].type = &t;
 	  diag_fci[i].pointer_count = 1;
+	  i = find_char_info_specifier_index (diag_fci, 'K');
+	  diag_fci[i].types[0].type = &t;
+	  diag_fci[i].pointer_count = 1;
 	}
 
       /* Handle the __gcc_tdiag__ format specifics.  */
@@ -2623,6 +2626,9 @@ init_dynamic_diag_info (void)
 	  i = find_char_info_specifier_index (tdiag_fci, 'J');
 	  tdiag_fci[i].types[0].type = &t;
 	  tdiag_fci[i].pointer_count = 1;
+	  i = find_char_info_specifier_index (tdiag_fci, 'K');
+	  tdiag_fci[i].types[0].type = &t;
+	  tdiag_fci[i].pointer_count = 1;
 	}
 
       /* Handle the __gcc_cdiag__ format specifics.  */
@@ -2647,6 +2653,9 @@ init_dynamic_diag_info (void)
 	  i = find_char_info_specifier_index (cdiag_fci, 'J');
 	  cdiag_fci[i].types[0].type = &t;
 	  cdiag_fci[i].pointer_count = 1;
+	  i = find_char_info_specifier_index (cdiag_fci, 'K');
+	  cdiag_fci[i].types[0].type = &t;
+	  cdiag_fci[i].pointer_count = 1;
 	}
 
       /* Handle the __gcc_cxxdiag__ format specifics.  */
@@ -2671,6 +2680,9 @@ init_dynamic_diag_info (void)
 	  i = find_char_info_specifier_index (cxxdiag_fci, 'J');
 	  cxxdiag_fci[i].types[0].type = &t;
 	  cxxdiag_fci[i].pointer_count = 1;
+	  i = find_char_info_specifier_index (cxxdiag_fci, 'K');
+	  cxxdiag_fci[i].types[0].type = &t;
+	  cxxdiag_fci[i].pointer_count = 1;
 	}
     }
 }
--- gcc/cp/error.c.jj	2007-08-29 13:47:46.000000000 +0200
+++ gcc/cp/error.c	2007-09-10 11:44:45.000000000 +0200
@@ -2317,9 +2317,10 @@ cv_to_string (tree p, int v)
 
 /* Langhook for print_error_function.  */
 void
-cxx_print_error_function (diagnostic_context *context, const char *file)
+cxx_print_error_function (diagnostic_context *context, const char *file,
+			  diagnostic_info *diagnostic)
 {
-  lhd_print_error_function (context, file);
+  lhd_print_error_function (context, file, diagnostic);
   pp_base_set_prefix (context->printer, file);
   maybe_print_instantiation_context (context);
 }
@@ -2347,23 +2348,105 @@ static void
 cp_print_error_function (diagnostic_context *context,
 			 diagnostic_info *diagnostic)
 {
-  if (diagnostic_last_function_changed (context))
+  if (diagnostic_last_function_changed (context, diagnostic))
     {
       const char *old_prefix = context->printer->prefix;
       const char *file = LOCATION_FILE (diagnostic->location);
-      char *new_prefix = file ? file_name_as_prefix (file) : NULL;
+      tree abstract_origin = diagnostic->abstract_origin;
+      char *new_prefix = (file && abstract_origin == NULL)
+			 ? file_name_as_prefix (file) : NULL;
 
       pp_base_set_prefix (context->printer, new_prefix);
 
       if (current_function_decl == NULL)
 	pp_base_string (context->printer, "At global scope:");
       else
-	pp_printf (context->printer, "In %s %qs:",
-		   function_category (current_function_decl),
-		   cxx_printable_name (current_function_decl, 2));
+	{
+	  tree fndecl, ao;
+
+	  if (abstract_origin)
+	    {
+	      ao = BLOCK_ABSTRACT_ORIGIN (abstract_origin);
+	      while (TREE_CODE (ao) == BLOCK && BLOCK_ABSTRACT_ORIGIN (ao))
+		ao = BLOCK_ABSTRACT_ORIGIN (ao);
+	      gcc_assert (TREE_CODE (ao) == FUNCTION_DECL);
+	      fndecl = ao;
+	    }
+	  else
+	    fndecl = current_function_decl;
+
+	  pp_printf (context->printer, "In %s %qs",
+		     function_category (fndecl),
+		     cxx_printable_name (fndecl, 2));
+
+	  while (abstract_origin)
+	    {
+	      location_t *locus;
+	      tree block = abstract_origin;
+
+	      locus = &BLOCK_SOURCE_LOCATION (block);
+	      fndecl = NULL;
+	      block = BLOCK_SUPERCONTEXT (block);
+	      while (block && TREE_CODE (block) == BLOCK
+		     && BLOCK_ABSTRACT_ORIGIN (block))
+		{
+		  ao = BLOCK_ABSTRACT_ORIGIN (block);
+
+		  while (TREE_CODE (ao) == BLOCK && BLOCK_ABSTRACT_ORIGIN (ao))
+		    ao = BLOCK_ABSTRACT_ORIGIN (ao);
+
+		  if (TREE_CODE (ao) == FUNCTION_DECL)
+		    {
+		      fndecl = ao;
+		      break;
+		    }
+		  else if (TREE_CODE (ao) != BLOCK)
+		    break;
+
+		  block = BLOCK_SUPERCONTEXT (block);
+		}
+	      if (fndecl)
+		abstract_origin = block;
+	      else
+		{
+		  while (block && TREE_CODE (block) == BLOCK)
+		    block = BLOCK_SUPERCONTEXT (block);
+
+		  if (TREE_CODE (block) == FUNCTION_DECL)
+		    fndecl = block;
+		  abstract_origin = NULL;
+		}
+	      if (fndecl)
+		{
+		  expanded_location s = expand_location (*locus);
+		  pp_base_character (context->printer, ',');
+		  pp_base_newline (context->printer);
+		  if (s.file != NULL)
+		    {
+#ifdef USE_MAPPED_LOCATION
+		      if (flag_show_column && s.column != 0)
+			pp_printf (context->printer,
+				   "    inlined from %qs at %s:%d:%d",
+				   cxx_printable_name (fndecl, 2),
+				   s.file, s.line, s.column);
+		      else
+#endif
+			pp_printf (context->printer,
+				   "    inlined from %qs at %s:%d",
+				   cxx_printable_name (fndecl, 2),
+				   s.file, s.line);
+
+		    }
+		  else
+		    pp_printf (context->printer, "    inlined from %qs",
+			       cxx_printable_name (fndecl, 2));
+		}
+	    }
+	  pp_base_character (context->printer, ':');
+	}
       pp_base_newline (context->printer);
 
-      diagnostic_set_last_function (context);
+      diagnostic_set_last_function (context, diagnostic);
       pp_base_destroy_prefix (context->printer);
       context->printer->prefix = old_prefix;
     }
--- gcc/cp/cp-tree.h.jj	2007-09-07 10:29:32.000000000 +0200
+++ gcc/cp/cp-tree.h	2007-09-10 11:30:35.000000000 +0200
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.  
 #include "c-common.h"
 #include "name-lookup.h"
 struct diagnostic_context;
+struct diagnostic_info;
 
 /* Usage of TREE_LANG_FLAG_?:
    0: IDENTIFIER_MARKED (IDENTIFIER_NODEs)
@@ -4133,7 +4134,8 @@ extern void cxx_print_decl			(FILE *, tr
 extern void cxx_print_type			(FILE *, tree, int);
 extern void cxx_print_identifier		(FILE *, tree, int);
 extern void cxx_print_error_function	(struct diagnostic_context *,
-						 const char *);
+						 const char *,
+						 struct diagnostic_info *);
 extern void build_self_reference		(void);
 extern int same_signature_p			(const_tree, const_tree);
 extern void maybe_add_class_template_decl_list	(tree, tree, int);
--- gcc/java/lang.c.jj	2007-09-07 10:29:32.000000000 +0200
+++ gcc/java/lang.c	2007-09-10 11:47:06.000000000 +0200
@@ -54,7 +54,8 @@ static bool java_post_options (const cha
 static int java_handle_option (size_t scode, const char *arg, int value);
 static void put_decl_string (const char *, int);
 static void put_decl_node (tree);
-static void java_print_error_function (diagnostic_context *, const char *);
+static void java_print_error_function (diagnostic_context *, const char *,
+				       diagnostic_info *);
 static int merge_init_test_initialization (void * *, void *);
 static int inline_init_test_initialization (void * *, void *);
 static bool java_dump_tree (void *, tree);
@@ -492,7 +493,8 @@ static GTY(()) tree last_error_function_
 static GTY(()) tree last_error_function;
 static void
 java_print_error_function (diagnostic_context *context ATTRIBUTE_UNUSED,
-			   const char *file)
+			   const char *file,
+			   diagnostic_info *diagnostic ATTRIBUTE_UNUSED)
 {
   /* Don't print error messages with bogus function prototypes.  */
   if (inhibit_error_function_printing)


	Jakub



More information about the Gcc-patches mailing list