aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/c-family/ChangeLog15
-rw-r--r--gcc/c-family/c-ppoutput.c76
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/cpp/syshdr4.c24
-rw-r--r--gcc/testsuite/gcc.dg/cpp/syshdr4.h8
-rw-r--r--gcc/testsuite/gcc.dg/cpp/syshdr5.c14
-rw-r--r--gcc/testsuite/gcc.dg/cpp/syshdr5.h6
7 files changed, 124 insertions, 24 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 25acae8..049a571 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,18 @@
+2014-07-01 Dodji Seketeli <dodji@redhat.com>
+
+ PR preprocessor/60723
+ * c-ppoutput.c (struct print::prev_was_system_token): New data
+ member.
+ (init_pp_output): Initialize it.
+ (maybe_print_line_1, maybe_print_line, print_line_1, print_line)
+ (do_line_change): Return a flag saying if a line marker was
+ emitted or not.
+ (scan_translation_unit): Detect if the system-ness of the token we
+ are about to emit is different from the one of the previously
+ emitted token. If so, emit a line marker. Avoid emitting useless
+ adjacent line markers.
+ (scan_translation_unit_directives_only): Adjust.
+
2014-07-01 Marek Polacek <polacek@redhat.com>
* c.opt (Wint-conversion): New option.
diff --git a/gcc/c-family/c-ppoutput.c b/gcc/c-family/c-ppoutput.c
index f3b5fa4..618e1c9 100644
--- a/gcc/c-family/c-ppoutput.c
+++ b/gcc/c-family/c-ppoutput.c
@@ -36,6 +36,8 @@ static struct
unsigned char printed; /* Nonzero if something output at line. */
bool first_time; /* pp_file_change hasn't been called yet. */
const char *src_file; /* Current source file. */
+ bool prev_was_system_token; /* True if the previous token was a
+ system token.*/
} print;
/* Defined and undefined macros being queued for output with -dU at
@@ -58,11 +60,11 @@ static void account_for_newlines (const unsigned char *, size_t);
static int dump_macro (cpp_reader *, cpp_hashnode *, void *);
static void dump_queued_macros (cpp_reader *);
-static void print_line_1 (source_location, const char*, FILE *);
-static void print_line (source_location, const char *);
-static void maybe_print_line_1 (source_location, FILE *);
-static void maybe_print_line (source_location);
-static void do_line_change (cpp_reader *, const cpp_token *,
+static bool print_line_1 (source_location, const char*, FILE *);
+static bool print_line (source_location, const char *);
+static bool maybe_print_line_1 (source_location, FILE *);
+static bool maybe_print_line (source_location);
+static bool do_line_change (cpp_reader *, const cpp_token *,
source_location, int);
/* Callback routines for the parser. Most of these are active only
@@ -156,6 +158,7 @@ init_pp_output (FILE *out_stream)
print.outf = out_stream;
print.first_time = 1;
print.src_file = "";
+ print.prev_was_system_token = false;
}
/* Writes out the preprocessed file, handling spacing and paste
@@ -168,6 +171,7 @@ scan_translation_unit (cpp_reader *pfile)
= cpp_get_options (parse_in)->lang != CLK_ASM
&& !flag_no_line_commands;
bool in_pragma = false;
+ bool line_marker_emitted = false;
print.source = NULL;
for (;;)
@@ -200,7 +204,7 @@ scan_translation_unit (cpp_reader *pfile)
&& do_line_adjustments
&& !in_pragma)
{
- do_line_change (pfile, token, loc, false);
+ line_marker_emitted = do_line_change (pfile, token, loc, false);
putc (' ', print.outf);
}
else if (print.source->flags & PREV_WHITE
@@ -216,7 +220,7 @@ scan_translation_unit (cpp_reader *pfile)
if (src_line != print.src_line
&& do_line_adjustments
&& !in_pragma)
- do_line_change (pfile, token, loc, false);
+ line_marker_emitted = do_line_change (pfile, token, loc, false);
putc (' ', print.outf);
}
@@ -228,7 +232,7 @@ scan_translation_unit (cpp_reader *pfile)
const char *space;
const char *name;
- maybe_print_line (token->src_loc);
+ line_marker_emitted = maybe_print_line (token->src_loc);
fputs ("#pragma ", print.outf);
c_pp_lookup_pragma (token->val.pragma, &space, &name);
if (space)
@@ -248,9 +252,18 @@ scan_translation_unit (cpp_reader *pfile)
if (cpp_get_options (parse_in)->debug)
linemap_dump_location (line_table, token->src_loc,
print.outf);
+
+ if (!line_marker_emitted
+ && print.prev_was_system_token != !!in_system_header_at(loc))
+ /* The system-ness of this token is different from the one
+ of the previous token. Let's emit a line change to
+ mark the new system-ness before we emit the token. */
+ line_marker_emitted = do_line_change (pfile, token, loc, false);
cpp_output_token (token, print.outf);
+ line_marker_emitted = false;
}
+ print.prev_was_system_token = !!in_system_header_at(loc);
/* CPP_COMMENT tokens and raw-string literal tokens can
have embedded new-line characters. Rather than enumerating
all the possible token types just check if token uses
@@ -275,7 +288,7 @@ scan_translation_unit_directives_only (cpp_reader *pfile)
struct _cpp_dir_only_callbacks cb;
cb.print_lines = print_lines_directives_only;
- cb.maybe_print_line = maybe_print_line;
+ cb.maybe_print_line = (void (*) (source_location)) maybe_print_line;
_cpp_preprocess_dir_only (pfile, &cb);
}
@@ -306,11 +319,13 @@ scan_translation_unit_trad (cpp_reader *pfile)
/* If the token read on logical line LINE needs to be output on a
different line to the current one, output the required newlines or
- a line marker, and return 1. Otherwise return 0. */
+ a line marker. If a line marker was emitted, return TRUE otherwise
+ return FALSE. */
-static void
+static bool
maybe_print_line_1 (source_location src_loc, FILE *stream)
{
+ bool emitted_line_marker = false;
int src_line = LOCATION_LINE (src_loc);
const char *src_file = LOCATION_FILE (src_loc);
@@ -334,29 +349,34 @@ maybe_print_line_1 (source_location src_loc, FILE *stream)
}
}
else
- print_line_1 (src_loc, "", stream);
+ emitted_line_marker = print_line_1 (src_loc, "", stream);
+ return emitted_line_marker;
}
/* If the token read on logical line LINE needs to be output on a
different line to the current one, output the required newlines or
- a line marker, and return 1. Otherwise return 0. */
+ a line marker. If a line marker was emitted, return TRUE otherwise
+ return FALSE. */
-static void
+static bool
maybe_print_line (source_location src_loc)
{
if (cpp_get_options (parse_in)->debug)
linemap_dump_location (line_table, src_loc,
print.outf);
- maybe_print_line_1 (src_loc, print.outf);
+ return maybe_print_line_1 (src_loc, print.outf);
}
/* Output a line marker for logical line LINE. Special flags are "1"
- or "2" indicating entering or leaving a file. */
+ or "2" indicating entering or leaving a file. If the line marker
+ was effectively emitted, return TRUE otherwise return FALSE. */
-static void
+static bool
print_line_1 (source_location src_loc, const char *special_flags, FILE *stream)
{
+ bool emitted_line_marker = false;
+
/* End any previous line of text. */
if (print.printed)
putc ('\n', stream);
@@ -391,33 +411,39 @@ print_line_1 (source_location src_loc, const char *special_flags, FILE *stream)
fputs (" 3", stream);
putc ('\n', stream);
+ emitted_line_marker = true;
}
+
+ return emitted_line_marker;
}
/* Output a line marker for logical line LINE. Special flags are "1"
- or "2" indicating entering or leaving a file. */
+ or "2" indicating entering or leaving a file. Return TRUE if a
+ line marker was effectively emitted, FALSE otherwise. */
-static void
+static bool
print_line (source_location src_loc, const char *special_flags)
{
if (cpp_get_options (parse_in)->debug)
linemap_dump_location (line_table, src_loc,
print.outf);
- print_line_1 (src_loc, special_flags, print.outf);
+ return print_line_1 (src_loc, special_flags, print.outf);
}
-/* Helper function for cb_line_change and scan_translation_unit. */
-static void
+/* Helper function for cb_line_change and scan_translation_unit.
+ Return TRUE if a line marker is emitted, FALSE otherwise. */
+static bool
do_line_change (cpp_reader *pfile, const cpp_token *token,
source_location src_loc, int parsing_args)
{
+ bool emitted_line_marker = false;
if (define_queue || undef_queue)
dump_queued_macros (pfile);
if (token->type == CPP_EOF || parsing_args)
- return;
+ return false;
- maybe_print_line (src_loc);
+ emitted_line_marker = maybe_print_line (src_loc);
print.prev = 0;
print.source = 0;
@@ -434,6 +460,8 @@ do_line_change (cpp_reader *pfile, const cpp_token *token,
while (-- spaces >= 0)
putc (' ', print.outf);
}
+
+ return emitted_line_marker;
}
/* Called when a line of output is started. TOKEN is the first token
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0bb4e90..8aa7bb2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-07-01 Dodji Seketeli <dodji@redhat.com>
+
+ PR preprocessor/60723
+ * gcc.dg/cpp/syshdr{4,5}.{c,h}: New test files.
+
2014-07-01 Marek Polacek <polacek@redhat.com>
* gcc.dg/Wint-conversion.c: New test.
diff --git a/gcc/testsuite/gcc.dg/cpp/syshdr4.c b/gcc/testsuite/gcc.dg/cpp/syshdr4.c
new file mode 100644
index 0000000..fe001d2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/syshdr4.c
@@ -0,0 +1,24 @@
+/* Contributed by Nicholas Ormrod */
+/* Origin: PR preprocessor/60723 */
+
+/* This tests that multi-line macro callsites, which are defined
+ in system headers and whose expansion contains a builtin followed
+ by a non-builtin token, do not generate a line directive that
+ mark the current file as being a system file, when performing
+ non-integrated preprocessing. */
+/* System files suppress div-by-zero warnings, so the presence of
+ such indicates the lack of the bug.
+
+ { dg-do compile }
+ { dg-options -no-integrated-cpp } */
+
+#include "syshdr4.h"
+FOO(
+)
+
+int
+foo()
+{
+ return 1 / 0; /* { dg-warning "div-by-zero" } */
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cpp/syshdr4.h b/gcc/testsuite/gcc.dg/cpp/syshdr4.h
new file mode 100644
index 0000000..c464f6e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/syshdr4.h
@@ -0,0 +1,8 @@
+/* Contributed by Nicholas Ormrod
+ Origin: PR preprocessor/60723.
+
+ This file is to be included by the syshdr4.c file. */
+
+#pragma GCC system_header
+
+#define FOO() int line = __LINE__ ;
diff --git a/gcc/testsuite/gcc.dg/cpp/syshdr5.c b/gcc/testsuite/gcc.dg/cpp/syshdr5.c
new file mode 100644
index 0000000..42c6263
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/syshdr5.c
@@ -0,0 +1,14 @@
+/* Origin: PR preprocessor/60723
+
+ { dg-do compile }
+ { dg-options -no-integrated-cpp } */
+
+#include "syshdr5.h"
+
+int
+main()
+{
+ FOO(1/0 /* { dg-warning "division by zero" } */
+ );
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cpp/syshdr5.h b/gcc/testsuite/gcc.dg/cpp/syshdr5.h
new file mode 100644
index 0000000..300d6c3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/syshdr5.h
@@ -0,0 +1,6 @@
+/* Origin: PR preprocessor/60723
+
+ This header file is to be included by the syshdr5.c file. */
+
+#pragma GCC system_header
+#define FOO(A)do {int line = __LINE__ ; A;} while(0)