re PR c++/24985 (caret diagnostics)

2012-04-11  Manuel López-Ibáñez  <manu@gcc.gnu.org>

	PR 24985
gcc/
        * diagnostic.h (show_caret): Declare.
	(caret_max_width): Declare.
	(diagnostic_show_locus): Declare.
        * diagnostic.c (diagnostic_initialize): Initialize to false.
        (diagnostic_show_locus): New.
        (diagnostic_report_diagnostic): Call it.
	(getenv_columns): New.
	(adjust_line): New.
	(diagnostic_set_caret_max_width): New.
        * input.c (read_line): New.
	(location_get_source_line): New.
        * input.h (location_get_source_line): Declare.
        * toplev.c (general_init): Initialize show_caret from options.
        * dwarf2out.c (gen_producer_string): Handle fdiagnostics-show-caret.
        * opts.c (common_handle_option): Likewise.
	* pretty-print.h (pp_get_prefix): New.
	(pp_base_get_prefix): New.
        * common.opt (fdiagnostics-show-caret): New option.
	* doc/invoke.texi (fdiagnostics-show-caret): Document it.
testsuite/
        * lib/prune.exp: Add -fno-diagnostics-show-caret.
libstdc++-v3/
	* testsuite/lib/prune.exp: Handle caret.
libmudflap/
	* testsuite/lib/libmudflap.exp: Handle caret.

From-SVN: r186305
parent 13a7578b
2012-04-11 Manuel López-Ibáñez <manu@gcc.gnu.org>
PR 24985
* diagnostic.h (show_caret): Declare.
(caret_max_width): Declare.
(diagnostic_show_locus): Declare.
* diagnostic.c (diagnostic_initialize): Initialize to false.
(diagnostic_show_locus): New.
(diagnostic_report_diagnostic): Call it.
(getenv_columns): New.
(adjust_line): New.
(diagnostic_set_caret_max_width): New.
* input.c (read_line): New.
(location_get_source_line): New.
* input.h (location_get_source_line): Declare.
* toplev.c (general_init): Initialize show_caret from options.
* dwarf2out.c (gen_producer_string): Handle fdiagnostics-show-caret.
* opts.c (common_handle_option): Likewise.
* pretty-print.h (pp_get_prefix): New.
(pp_base_get_prefix): New.
* common.opt (fdiagnostics-show-caret): New option.
* doc/invoke.texi (fdiagnostics-show-caret): Document it.
2012-04-11 Richard Guenther <rguenther@suse.de> 2012-04-11 Richard Guenther <rguenther@suse.de>
PR rtl-optimization/52881 PR rtl-optimization/52881
......
...@@ -999,6 +999,10 @@ Enum(diagnostic_prefixing_rule) String(once) Value(DIAGNOSTICS_SHOW_PREFIX_ONCE) ...@@ -999,6 +999,10 @@ Enum(diagnostic_prefixing_rule) String(once) Value(DIAGNOSTICS_SHOW_PREFIX_ONCE)
EnumValue EnumValue
Enum(diagnostic_prefixing_rule) String(every-line) Value(DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE) Enum(diagnostic_prefixing_rule) String(every-line) Value(DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE)
fdiagnostics-show-caret
Common Var(flag_diagnostics_show_caret) Init(1)
Show the source line with a caret indicating the column
fdiagnostics-show-option fdiagnostics-show-option
Common Var(flag_diagnostics_show_option) Init(1) Common Var(flag_diagnostics_show_option) Init(1)
Amend appropriate diagnostic messages with the command line option that controls them Amend appropriate diagnostic messages with the command line option that controls them
......
...@@ -78,6 +78,35 @@ file_name_as_prefix (const char *f) ...@@ -78,6 +78,35 @@ file_name_as_prefix (const char *f)
/* Return the value of the getenv("COLUMNS") as an integer. If the
value is not set to a positive integer, then return INT_MAX. */
static int
getenv_columns (void)
{
const char * s = getenv ("COLUMNS");
if (s != NULL) {
int n = atoi (s);
if (n > 0)
return n;
}
return INT_MAX;
}
/* Set caret_max_width to value. */
void
diagnostic_set_caret_max_width (diagnostic_context *context, int value)
{
/* One minus to account for the leading empty space. */
value = value ? value - 1
: (isatty (fileno (context->printer->buffer->stream))
? getenv_columns () - 1: INT_MAX);
if (value <= 0)
value = INT_MAX;
context->caret_max_width = value;
}
/* Initialize the diagnostic message outputting machinery. */ /* Initialize the diagnostic message outputting machinery. */
void void
diagnostic_initialize (diagnostic_context *context, int n_opts) diagnostic_initialize (diagnostic_context *context, int n_opts)
...@@ -100,6 +129,8 @@ diagnostic_initialize (diagnostic_context *context, int n_opts) ...@@ -100,6 +129,8 @@ diagnostic_initialize (diagnostic_context *context, int n_opts)
context->classify_diagnostic = XNEWVEC (diagnostic_t, n_opts); context->classify_diagnostic = XNEWVEC (diagnostic_t, n_opts);
for (i = 0; i < n_opts; i++) for (i = 0; i < n_opts; i++)
context->classify_diagnostic[i] = DK_UNSPECIFIED; context->classify_diagnostic[i] = DK_UNSPECIFIED;
context->show_caret = false;
diagnostic_set_caret_max_width (context, pp_line_cutoff (context->printer));
context->show_option_requested = false; context->show_option_requested = false;
context->abort_on_error = false; context->abort_on_error = false;
context->show_column = false; context->show_column = false;
...@@ -196,6 +227,72 @@ diagnostic_build_prefix (diagnostic_context *context, ...@@ -196,6 +227,72 @@ diagnostic_build_prefix (diagnostic_context *context,
: build_message_string ("%s:%d: %s", s.file, s.line, text)); : build_message_string ("%s:%d: %s", s.file, s.line, text));
} }
/* If LINE is longer than MAX_WIDTH, and COLUMN is not smaller than
MAX_WIDTH by some margin, then adjust the start of the line such
that the COLUMN is smaller than MAX_WIDTH minus the margin. The
margin is either 10 characters or the difference between the column
and the length of the line, whatever is smaller. */
static const char *
adjust_line (const char *line, int max_width, int *column_p)
{
int right_margin = 10;
int line_width = strlen (line);
int column = *column_p;
right_margin = MIN(line_width - column, right_margin);
right_margin = max_width - right_margin;
if (line_width >= max_width && column > right_margin)
{
line += column - right_margin;
*column_p = right_margin;
}
return line;
}
/* Print the physical source line corresponding to the location of
this diagnostics, and a caret indicating the precise column. */
void
diagnostic_show_locus (diagnostic_context * context,
const diagnostic_info *diagnostic)
{
const char *line;
char *buffer;
expanded_location s;
int max_width;
const char *saved_prefix;
if (!context->show_caret
|| diagnostic->location <= BUILTINS_LOCATION)
return;
s = expand_location(diagnostic->location);
line = location_get_source_line (s);
if (line == NULL)
return;
max_width = context->caret_max_width;
line = adjust_line (line, max_width, &(s.column));
pp_newline (context->printer);
saved_prefix = pp_get_prefix (context->printer);
pp_set_prefix (context->printer, NULL);
pp_character (context->printer, ' ');
while (max_width > 0 && *line != '\0')
{
char c = *line == '\t' ? ' ' : *line;
pp_character (context->printer, c);
max_width--;
line++;
}
pp_newline (context->printer);
/* pp_printf does not implement %*c. */
buffer = XALLOCAVEC (char, s.column + 3);
snprintf (buffer, s.column + 3, " %*c", s.column, '^');
pp_string (context->printer, buffer);
pp_set_prefix (context->printer, saved_prefix);
}
/* Take any action which is expected to happen after the diagnostic /* Take any action which is expected to happen after the diagnostic
is written out. This function does not always return. */ is written out. This function does not always return. */
static void static void
...@@ -547,6 +644,7 @@ diagnostic_report_diagnostic (diagnostic_context *context, ...@@ -547,6 +644,7 @@ diagnostic_report_diagnostic (diagnostic_context *context,
pp_format (context->printer, &diagnostic->message); pp_format (context->printer, &diagnostic->message);
(*diagnostic_starter (context)) (context, diagnostic); (*diagnostic_starter (context)) (context, diagnostic);
pp_output_formatted_text (context->printer); pp_output_formatted_text (context->printer);
diagnostic_show_locus (context, diagnostic);
(*diagnostic_finalizer (context)) (context, diagnostic); (*diagnostic_finalizer (context)) (context, diagnostic);
pp_flush (context->printer); pp_flush (context->printer);
diagnostic_action_after_output (context, diagnostic); diagnostic_action_after_output (context, diagnostic);
......
...@@ -99,6 +99,13 @@ struct diagnostic_context ...@@ -99,6 +99,13 @@ struct diagnostic_context
int *push_list; int *push_list;
int n_push; int n_push;
/* True if we should print the source line with a caret indicating
the location. */
bool show_caret;
/* Maximum width of the source line printed. */
int caret_max_width;
/* True if we should print the command line option which controls /* True if we should print the command line option which controls
each diagnostic, if known. */ each diagnostic, if known. */
bool show_option_requested; bool show_option_requested;
...@@ -254,6 +261,7 @@ extern diagnostic_context *global_dc; ...@@ -254,6 +261,7 @@ extern diagnostic_context *global_dc;
extern void diagnostic_initialize (diagnostic_context *, int); extern void diagnostic_initialize (diagnostic_context *, int);
extern void diagnostic_finish (diagnostic_context *); extern void diagnostic_finish (diagnostic_context *);
extern void diagnostic_report_current_module (diagnostic_context *, location_t); extern void diagnostic_report_current_module (diagnostic_context *, location_t);
extern void diagnostic_show_locus (diagnostic_context *, const diagnostic_info *);
/* Force diagnostics controlled by OPTIDX to be kind KIND. */ /* Force diagnostics controlled by OPTIDX to be kind KIND. */
extern diagnostic_t diagnostic_classify_diagnostic (diagnostic_context *, extern diagnostic_t diagnostic_classify_diagnostic (diagnostic_context *,
...@@ -275,6 +283,8 @@ extern void diagnostic_set_info_translated (diagnostic_info *, const char *, ...@@ -275,6 +283,8 @@ extern void diagnostic_set_info_translated (diagnostic_info *, const char *,
extern char *diagnostic_build_prefix (diagnostic_context *, diagnostic_info *); extern char *diagnostic_build_prefix (diagnostic_context *, diagnostic_info *);
void default_diagnostic_starter (diagnostic_context *, diagnostic_info *); void default_diagnostic_starter (diagnostic_context *, diagnostic_info *);
void default_diagnostic_finalizer (diagnostic_context *, diagnostic_info *); void default_diagnostic_finalizer (diagnostic_context *, diagnostic_info *);
void diagnostic_set_caret_max_width (diagnostic_context *context, int value);
/* Pure text formatting support functions. */ /* Pure text formatting support functions. */
extern char *file_name_as_prefix (const char *); extern char *file_name_as_prefix (const char *);
......
...@@ -230,7 +230,7 @@ Objective-C and Objective-C++ Dialects}. ...@@ -230,7 +230,7 @@ Objective-C and Objective-C++ Dialects}.
@xref{Language Independent Options,,Options to Control Diagnostic Messages Formatting}. @xref{Language Independent Options,,Options to Control Diagnostic Messages Formatting}.
@gccoptlist{-fmessage-length=@var{n} @gol @gccoptlist{-fmessage-length=@var{n} @gol
-fdiagnostics-show-location=@r{[}once@r{|}every-line@r{]} @gol -fdiagnostics-show-location=@r{[}once@r{|}every-line@r{]} @gol
-fno-diagnostics-show-option} -fno-diagnostics-show-option -fno-diagnostics-show-caret}
@item Warning Options @item Warning Options
@xref{Warning Options,,Options to Request or Suppress Warnings}. @xref{Warning Options,,Options to Request or Suppress Warnings}.
...@@ -2894,6 +2894,13 @@ command-line option that directly controls the diagnostic (if such an ...@@ -2894,6 +2894,13 @@ command-line option that directly controls the diagnostic (if such an
option is known to the diagnostic machinery). Specifying the option is known to the diagnostic machinery). Specifying the
@option{-fno-diagnostics-show-option} flag suppresses that behavior. @option{-fno-diagnostics-show-option} flag suppresses that behavior.
@item -fno-diagnostics-show-caret
@opindex fno-diagnostics-show-caret
@opindex fdiagnostics-show-caret
By default, each diagnostic emitted includes the original source line
and a caret '^' indicating the column. This option suppresses this
information.
@end table @end table
@node Warning Options @node Warning Options
......
...@@ -18369,6 +18369,7 @@ gen_producer_string (void) ...@@ -18369,6 +18369,7 @@ gen_producer_string (void)
case OPT__output_pch_: case OPT__output_pch_:
case OPT_fdiagnostics_show_location_: case OPT_fdiagnostics_show_location_:
case OPT_fdiagnostics_show_option: case OPT_fdiagnostics_show_option:
case OPT_fdiagnostics_show_caret:
case OPT_fverbose_asm: case OPT_fverbose_asm:
case OPT____: case OPT____:
case OPT__sysroot_: case OPT__sysroot_:
......
...@@ -50,6 +50,65 @@ expand_location (source_location loc) ...@@ -50,6 +50,65 @@ expand_location (source_location loc)
return xloc; return xloc;
} }
/* Reads one line from file into a static buffer. */
static const char *
read_line (FILE *file)
{
static char *string;
static size_t string_len;
size_t pos = 0;
char *ptr;
if (!string_len)
{
string_len = 200;
string = XNEWVEC (char, string_len);
}
while ((ptr = fgets (string + pos, string_len - pos, file)))
{
size_t len = strlen (string + pos);
if (string[pos + len - 1] == '\n')
{
string[pos + len - 1] = 0;
return string;
}
pos += len;
ptr = XNEWVEC (char, string_len * 2);
if (ptr)
{
memcpy (ptr, string, pos);
string = ptr;
string_len += 2;
}
else
pos = 0;
}
return pos ? string : NULL;
}
/* Return the physical source line that corresponds to xloc in a
buffer that is statically allocated. The newline is replaced by
the null character. */
const char *
location_get_source_line(expanded_location xloc)
{
const char *buffer;
int lines = 1;
FILE *stream = xloc.file ? fopen (xloc.file, "r") : NULL;
if (!stream)
return NULL;
while ((buffer = read_line (stream)) && lines < xloc.line)
lines++;
fclose (stream);
return buffer;
}
#define ONE_K 1024 #define ONE_K 1024
#define ONE_M (ONE_K * ONE_K) #define ONE_M (ONE_K * ONE_K)
......
...@@ -38,6 +38,7 @@ extern char builtins_location_check[(BUILTINS_LOCATION ...@@ -38,6 +38,7 @@ extern char builtins_location_check[(BUILTINS_LOCATION
< RESERVED_LOCATION_COUNT) ? 1 : -1]; < RESERVED_LOCATION_COUNT) ? 1 : -1];
extern expanded_location expand_location (source_location); extern expanded_location expand_location (source_location);
extern const char * location_get_source_line(expanded_location xloc);
/* Historically GCC used location_t, while cpp used source_location. /* Historically GCC used location_t, while cpp used source_location.
This could be removed but it hardly seems worth the effort. */ This could be removed but it hardly seems worth the effort. */
......
...@@ -1499,6 +1499,10 @@ common_handle_option (struct gcc_options *opts, ...@@ -1499,6 +1499,10 @@ common_handle_option (struct gcc_options *opts,
case OPT_fdiagnostics_show_location_: case OPT_fdiagnostics_show_location_:
diagnostic_prefixing_rule (dc) = (diagnostic_prefixing_rule_t) value; diagnostic_prefixing_rule (dc) = (diagnostic_prefixing_rule_t) value;
break; break;
case OPT_fdiagnostics_show_caret:
dc->show_caret = value;
break;
case OPT_fdiagnostics_show_option: case OPT_fdiagnostics_show_option:
dc->show_option_requested = value; dc->show_option_requested = value;
...@@ -1539,6 +1543,7 @@ common_handle_option (struct gcc_options *opts, ...@@ -1539,6 +1543,7 @@ common_handle_option (struct gcc_options *opts,
case OPT_fmessage_length_: case OPT_fmessage_length_:
pp_set_line_maximum_length (dc->printer, value); pp_set_line_maximum_length (dc->printer, value);
diagnostic_set_caret_max_width (dc, value);
break; break;
case OPT_fpack_struct_: case OPT_fpack_struct_:
......
...@@ -201,6 +201,9 @@ struct pretty_print_info ...@@ -201,6 +201,9 @@ struct pretty_print_info
#define pp_set_line_maximum_length(PP, L) \ #define pp_set_line_maximum_length(PP, L) \
pp_base_set_line_maximum_length (pp_base (PP), L) pp_base_set_line_maximum_length (pp_base (PP), L)
#define pp_set_prefix(PP, P) pp_base_set_prefix (pp_base (PP), P) #define pp_set_prefix(PP, P) pp_base_set_prefix (pp_base (PP), P)
#define pp_get_prefix(PP) pp_base_get_prefix (pp_base (PP))
static inline const char *
pp_base_get_prefix (const pretty_printer *pp) { return pp->prefix; }
#define pp_destroy_prefix(PP) pp_base_destroy_prefix (pp_base (PP)) #define pp_destroy_prefix(PP) pp_base_destroy_prefix (pp_base (PP))
#define pp_remaining_character_count_for_line(PP) \ #define pp_remaining_character_count_for_line(PP) \
pp_base_remaining_character_count_for_line (pp_base (PP)) pp_base_remaining_character_count_for_line (pp_base (PP))
......
2012-04-11 Manuel López-Ibáñez <manu@gcc.gnu.org>
PR 24985
* lib/prune.exp: Add -fno-diagnostics-show-caret.
2012-04-11 Richard Guenther <rguenther@suse.de> 2012-04-11 Richard Guenther <rguenther@suse.de>
PR rtl-optimization/52881 PR rtl-optimization/52881
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
# Prune messages from gcc that aren't useful. # Prune messages from gcc that aren't useful.
set TEST_ALWAYS_FLAGS "-fno-diagnostics-show-caret $TEST_ALWAYS_FLAGS"
proc prune_gcc_output { text } { proc prune_gcc_output { text } {
#send_user "Before:$text\n" #send_user "Before:$text\n"
......
...@@ -1169,6 +1169,8 @@ general_init (const char *argv0) ...@@ -1169,6 +1169,8 @@ general_init (const char *argv0)
/* Set a default printer. Language specific initializations will /* Set a default printer. Language specific initializations will
override it later. */ override it later. */
pp_format_decoder (global_dc->printer) = &default_tree_printer; pp_format_decoder (global_dc->printer) = &default_tree_printer;
global_dc->show_caret
= global_options_init.x_flag_diagnostics_show_caret;
global_dc->show_option_requested global_dc->show_option_requested
= global_options_init.x_flag_diagnostics_show_option; = global_options_init.x_flag_diagnostics_show_option;
global_dc->show_column global_dc->show_column
......
2012-04-11 Manuel López-Ibáñez <manu@gcc.gnu.org>
PR 24985
* testsuite/lib/libmudflap.exp: Handle caret.
2012-01-19 Jakub Jelinek <jakub@redhat.com> 2012-01-19 Jakub Jelinek <jakub@redhat.com>
PR libmudflap/40778 PR libmudflap/40778
......
...@@ -298,6 +298,9 @@ proc libmudflap-dg-prune { system text } { ...@@ -298,6 +298,9 @@ proc libmudflap-dg-prune { system text } {
proc prune_gcc_output { text } { proc prune_gcc_output { text } {
# Ignore caret diagnostics. Unfortunately dejaGNU trims leading
# spaces, so one cannot rely on them being present.
regsub -all "(^|\n)\[^\n\]+\n *\\^\n" $text "\n" text
regsub -all {(^|\n)[^\n]*ld: warning: libgcc_s[^\n]*not found[^\n]*try using[^\n]*} $text "" text regsub -all {(^|\n)[^\n]*ld: warning: libgcc_s[^\n]*not found[^\n]*try using[^\n]*} $text "" text
regsub -all {(^|\n)[^\n]*In function.*pthread_create[^\n]*} $text "" text regsub -all {(^|\n)[^\n]*In function.*pthread_create[^\n]*} $text "" text
regsub -all {(^|\n)[^\n]*the use of .pthread.*is deprecated[^\n]*} $text "" text regsub -all {(^|\n)[^\n]*the use of .pthread.*is deprecated[^\n]*} $text "" text
......
2012-04-11 Manuel López-Ibáñez <manu@gcc.gnu.org>
PR 24985
* testsuite/lib/prune.exp: Handle caret.
2012-04-05 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> 2012-04-05 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
Partially revert: Partially revert:
......
...@@ -32,6 +32,12 @@ proc dg-prune-output { args } { ...@@ -32,6 +32,12 @@ proc dg-prune-output { args } {
proc libstdc++-dg-prune { system text } { proc libstdc++-dg-prune { system text } {
global additional_prunes global additional_prunes
# send_user "Before:$text\n"
# Ignore caret diagnostics. Unfortunately dejaGNU trims leading
# spaces, so one cannot rely on them being present.
regsub -all "(^|\n)\[^\n\]+\n *\\^\n" $text "\n" text
# Cygwin warns about -ffunction-sections # Cygwin warns about -ffunction-sections
regsub -all "(^|\n)\[^\n\]*: -ffunction-sections may affect debugging on some targets\[^\n\]*" $text "" text regsub -all "(^|\n)\[^\n\]*: -ffunction-sections may affect debugging on some targets\[^\n\]*" $text "" text
...@@ -68,5 +74,6 @@ proc libstdc++-dg-prune { system text } { ...@@ -68,5 +74,6 @@ proc libstdc++-dg-prune { system text } {
} }
} }
# send_user "After:$text\n"
return $text return $text
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment