aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog23
-rw-r--r--gcc/common.opt4
-rw-r--r--gcc/diagnostic.c98
-rw-r--r--gcc/diagnostic.h10
-rw-r--r--gcc/doc/invoke.texi9
-rw-r--r--gcc/dwarf2out.c1
-rw-r--r--gcc/input.c59
-rw-r--r--gcc/input.h1
-rw-r--r--gcc/opts.c5
-rw-r--r--gcc/pretty-print.h3
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/lib/prune.exp2
-rw-r--r--gcc/toplev.c2
-rw-r--r--libmudflap/ChangeLog5
-rw-r--r--libmudflap/testsuite/lib/libmudflap.exp3
-rw-r--r--libstdc++-v3/ChangeLog5
-rw-r--r--libstdc++-v3/testsuite/lib/prune.exp7
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. */
diff --git a/gcc/opts.c b/gcc/opts.c
index 6532b56..4e8b3c0 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -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
}