diff options
-rw-r--r-- | gcc/ChangeLog | 23 | ||||
-rw-r--r-- | gcc/common.opt | 4 | ||||
-rw-r--r-- | gcc/diagnostic.c | 98 | ||||
-rw-r--r-- | gcc/diagnostic.h | 10 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 9 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 1 | ||||
-rw-r--r-- | gcc/input.c | 59 | ||||
-rw-r--r-- | gcc/input.h | 1 | ||||
-rw-r--r-- | gcc/opts.c | 5 | ||||
-rw-r--r-- | gcc/pretty-print.h | 3 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/lib/prune.exp | 2 | ||||
-rw-r--r-- | gcc/toplev.c | 2 | ||||
-rw-r--r-- | libmudflap/ChangeLog | 5 | ||||
-rw-r--r-- | libmudflap/testsuite/lib/libmudflap.exp | 3 | ||||
-rw-r--r-- | libstdc++-v3/ChangeLog | 5 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/lib/prune.exp | 7 |
17 files changed, 241 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 62a4e88..b4a02dd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +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> PR rtl-optimization/52881 diff --git a/gcc/common.opt b/gcc/common.opt index 98fa2bb..39f1679 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -999,6 +999,10 @@ Enum(diagnostic_prefixing_rule) String(once) Value(DIAGNOSTICS_SHOW_PREFIX_ONCE) EnumValue 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 Common Var(flag_diagnostics_show_option) Init(1) Amend appropriate diagnostic messages with the command line option that controls them diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index a68d6ce..60773d3 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -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. */ void 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); for (i = 0; i < n_opts; i++) 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->abort_on_error = false; context->show_column = false; @@ -196,6 +227,72 @@ diagnostic_build_prefix (diagnostic_context *context, : 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 is written out. This function does not always return. */ static void @@ -547,6 +644,7 @@ diagnostic_report_diagnostic (diagnostic_context *context, pp_format (context->printer, &diagnostic->message); (*diagnostic_starter (context)) (context, diagnostic); pp_output_formatted_text (context->printer); + diagnostic_show_locus (context, diagnostic); (*diagnostic_finalizer (context)) (context, diagnostic); pp_flush (context->printer); diagnostic_action_after_output (context, diagnostic); diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 4b1265b..63eb385 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -99,6 +99,13 @@ struct diagnostic_context int *push_list; 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 each diagnostic, if known. */ bool show_option_requested; @@ -254,6 +261,7 @@ extern diagnostic_context *global_dc; extern void diagnostic_initialize (diagnostic_context *, int); extern void diagnostic_finish (diagnostic_context *); 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. */ extern diagnostic_t diagnostic_classify_diagnostic (diagnostic_context *, @@ -275,6 +283,8 @@ extern void diagnostic_set_info_translated (diagnostic_info *, const char *, extern char *diagnostic_build_prefix (diagnostic_context *, diagnostic_info *); void default_diagnostic_starter (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. */ extern char *file_name_as_prefix (const char *); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index cf6c9f2..2dde9c7 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -230,7 +230,7 @@ Objective-C and Objective-C++ Dialects}. @xref{Language Independent Options,,Options to Control Diagnostic Messages Formatting}. @gccoptlist{-fmessage-length=@var{n} @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 @xref{Warning Options,,Options to Request or Suppress Warnings}. @@ -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{-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 @node Warning Options diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index ca88fc5..7e2ce58 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -18369,6 +18369,7 @@ gen_producer_string (void) case OPT__output_pch_: case OPT_fdiagnostics_show_location_: case OPT_fdiagnostics_show_option: + case OPT_fdiagnostics_show_caret: case OPT_fverbose_asm: case OPT____: case OPT__sysroot_: diff --git a/gcc/input.c b/gcc/input.c index 4077f9e..bf5fe48 100644 --- a/gcc/input.c +++ b/gcc/input.c @@ -50,6 +50,65 @@ expand_location (source_location loc) 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_M (ONE_K * ONE_K) diff --git a/gcc/input.h b/gcc/input.h index f2f3513..4b15222 100644 --- a/gcc/input.h +++ b/gcc/input.h @@ -38,6 +38,7 @@ extern char builtins_location_check[(BUILTINS_LOCATION < RESERVED_LOCATION_COUNT) ? 1 : -1]; 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. This could be removed but it hardly seems worth the effort. */ @@ -1499,6 +1499,10 @@ common_handle_option (struct gcc_options *opts, case OPT_fdiagnostics_show_location_: diagnostic_prefixing_rule (dc) = (diagnostic_prefixing_rule_t) value; break; + + case OPT_fdiagnostics_show_caret: + dc->show_caret = value; + break; case OPT_fdiagnostics_show_option: dc->show_option_requested = value; @@ -1539,6 +1543,7 @@ common_handle_option (struct gcc_options *opts, case OPT_fmessage_length_: pp_set_line_maximum_length (dc->printer, value); + diagnostic_set_caret_max_width (dc, value); break; case OPT_fpack_struct_: diff --git a/gcc/pretty-print.h b/gcc/pretty-print.h index bb1d156..a7b5a9f 100644 --- a/gcc/pretty-print.h +++ b/gcc/pretty-print.h @@ -201,6 +201,9 @@ struct pretty_print_info #define pp_set_line_maximum_length(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_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_remaining_character_count_for_line(PP) \ pp_base_remaining_character_count_for_line (pp_base (PP)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7176e6a..61d83ff 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +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> PR rtl-optimization/52881 diff --git a/gcc/testsuite/lib/prune.exp b/gcc/testsuite/lib/prune.exp index 68a77b6..d2ba49e 100644 --- a/gcc/testsuite/lib/prune.exp +++ b/gcc/testsuite/lib/prune.exp @@ -17,6 +17,8 @@ # Prune messages from gcc that aren't useful. +set TEST_ALWAYS_FLAGS "-fno-diagnostics-show-caret $TEST_ALWAYS_FLAGS" + proc prune_gcc_output { text } { #send_user "Before:$text\n" diff --git a/gcc/toplev.c b/gcc/toplev.c index e01ed81..51d52e1 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1169,6 +1169,8 @@ general_init (const char *argv0) /* Set a default printer. Language specific initializations will override it later. */ 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_options_init.x_flag_diagnostics_show_option; global_dc->show_column diff --git a/libmudflap/ChangeLog b/libmudflap/ChangeLog index 3d3e5af..9fb1cac 100644 --- a/libmudflap/ChangeLog +++ b/libmudflap/ChangeLog @@ -1,3 +1,8 @@ +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> PR libmudflap/40778 diff --git a/libmudflap/testsuite/lib/libmudflap.exp b/libmudflap/testsuite/lib/libmudflap.exp index f960355..00699e8 100644 --- a/libmudflap/testsuite/lib/libmudflap.exp +++ b/libmudflap/testsuite/lib/libmudflap.exp @@ -298,6 +298,9 @@ proc libmudflap-dg-prune { system 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]*In function.*pthread_create[^\n]*} $text "" text regsub -all {(^|\n)[^\n]*the use of .pthread.*is deprecated[^\n]*} $text "" text diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 9bd4268..ba608fe 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,8 @@ +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> Partially revert: diff --git a/libstdc++-v3/testsuite/lib/prune.exp b/libstdc++-v3/testsuite/lib/prune.exp index a564406..a2371c6 100644 --- a/libstdc++-v3/testsuite/lib/prune.exp +++ b/libstdc++-v3/testsuite/lib/prune.exp @@ -32,6 +32,12 @@ proc dg-prune-output { args } { proc libstdc++-dg-prune { system text } { 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 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 } { } } +# send_user "After:$text\n" return $text } |