From a5cb563b79b71ef5dbf3c3c0aca014c785f79927 Mon Sep 17 00:00:00 2001
From: Joseph Myers <joseph@codesourcery.com>
Date: Sat, 18 Apr 2009 16:28:40 +0100
Subject: [PATCH] re PR preprocessor/39647 (Syntax checks in #line not quite
 right)

libcpp:
	PR preprocessor/39647
	* directives.c (check_eol): Add parameter expand.
	(do_undef, parse_include, do_line, do_linemarker, do_ident,
	do_pragma_once, do_pragma_system_header, do_ifdef, do_ifndef,
	do_else, do_endif, do_assert, do_unassert): All callers changed.
	Pass true from do_line, false elsewhere.

gcc/testsuite:
	* gcc.dg/cpp/line7.c: New test.

From-SVN: r146316
---
 gcc/testsuite/ChangeLog          |  5 +++++
 gcc/testsuite/gcc.dg/cpp/line7.c | 19 ++++++++++++++++
 libcpp/ChangeLog                 |  9 ++++++++
 libcpp/directives.c              | 37 +++++++++++++++++---------------
 4 files changed, 53 insertions(+), 17 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/cpp/line7.c

diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 846725e1daa6..58ea48782cca 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-04-18  Joseph Myers  <joseph@codesourcery.com>
+
+	PR preprocessor/39647
+	* gcc.dg/cpp/line7.c: New test.
+
 2009-04-18  Richard Guenther  <rguenther@suse.de>
 
 	PR middle-end/39804
diff --git a/gcc/testsuite/gcc.dg/cpp/line7.c b/gcc/testsuite/gcc.dg/cpp/line7.c
new file mode 100644
index 000000000000..754727e885f9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/line7.c
@@ -0,0 +1,19 @@
+/* Test #line syntax, including macro expansion and empty macros.  PR
+   39647.  */
+
+/* { dg-do preprocess } */
+/* { dg-options "-std=c99 -pedantic-errors" } */
+
+#define EMPTY_OBJ
+#define EMPTY_FUNC()
+
+#define A 12 "line7.c"
+#line A
+
+#line EMPTY_OBJ /* { dg-error "unexpected end of file" } */
+#line X /* { dg-error "is not a positive integer" } */
+#line 16 16 /* { dg-error "is not a valid filename" } */
+
+#line 18 "line7.c" EMPTY_OBJ
+#line 19 "line7.c" EMPTY_FUNC()
+#line 20 "line7.c" foo /* { dg-error "extra tokens at end" } */
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index d1383af17802..ce7bbe059cdb 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,12 @@
+2009-04-18  Joseph Myers  <joseph@codesourcery.com>
+
+	PR preprocessor/39647
+	* directives.c (check_eol): Add parameter expand.
+	(do_undef, parse_include, do_line, do_linemarker, do_ident,
+	do_pragma_once, do_pragma_system_header, do_ifdef, do_ifndef,
+	do_else, do_endif, do_assert, do_unassert): All callers changed.
+	Pass true from do_line, false elsewhere.
+
 2009-04-12  Joseph Myers  <joseph@codesourcery.com>
 
 	PR preprocessor/31869
diff --git a/libcpp/directives.c b/libcpp/directives.c
index 0fdcc048cfe1..9cb8506bb136 100644
--- a/libcpp/directives.c
+++ b/libcpp/directives.c
@@ -92,7 +92,7 @@ struct directive
 /* Forward declarations.  */
 
 static void skip_rest_of_line (cpp_reader *);
-static void check_eol (cpp_reader *);
+static void check_eol (cpp_reader *, bool);
 static void start_directive (cpp_reader *);
 static void prepare_directive_trad (cpp_reader *);
 static void end_directive (cpp_reader *, int);
@@ -208,11 +208,14 @@ skip_rest_of_line (cpp_reader *pfile)
       ;
 }
 
-/* Ensure there are no stray tokens at the end of a directive.  */
+/* Ensure there are no stray tokens at the end of a directive.  If
+   EXPAND is true, tokens macro-expanding to nothing are allowed.  */
 static void
-check_eol (cpp_reader *pfile)
+check_eol (cpp_reader *pfile, bool expand)
 {
-  if (! SEEN_EOL () && _cpp_lex_token (pfile)->type != CPP_EOF)
+  if (! SEEN_EOL () && (expand
+			? cpp_get_token (pfile)
+			: _cpp_lex_token (pfile))->type != CPP_EOF)
     cpp_error (pfile, CPP_DL_PEDWARN, "extra tokens at end of #%s directive",
 	       pfile->directive->name);
 }
@@ -609,7 +612,7 @@ do_undef (cpp_reader *pfile)
 	}
     }
 
-  check_eol (pfile);
+  check_eol (pfile, false);
 }
 
 /* Undefine a single macro/assertion/whatever.  */
@@ -721,7 +724,7 @@ parse_include (cpp_reader *pfile, int *pangle_brackets,
       /* This pragma allows extra tokens after the file name.  */
     }
   else if (buf == NULL || CPP_OPTION (pfile, discard_comments))
-    check_eol (pfile);
+    check_eol (pfile, false);
   else
     {
       /* If we are not discarding comments, then gather them while
@@ -911,7 +914,7 @@ do_line (cpp_reader *pfile)
       if (cpp_interpret_string_notranslate (pfile, &token->val.str, 1,
 					    &s, false))
 	new_file = (const char *)s.text;
-      check_eol (pfile);
+      check_eol (pfile, true);
     }
   else if (token->type != CPP_EOF)
     {
@@ -991,7 +994,7 @@ do_linemarker (cpp_reader *pfile)
 	}
       pfile->buffer->sysp = new_sysp;
 
-      check_eol (pfile);
+      check_eol (pfile, false);
     }
   else if (token->type != CPP_EOF)
     {
@@ -1068,7 +1071,7 @@ do_ident (cpp_reader *pfile)
   else if (pfile->cb.ident)
     pfile->cb.ident (pfile, pfile->directive_line, &str->val.str);
 
-  check_eol (pfile);
+  check_eol (pfile, false);
 }
 
 /* Lookup a PRAGMA name in a singly-linked CHAIN.  Returns the
@@ -1401,7 +1404,7 @@ do_pragma_once (cpp_reader *pfile)
   if (cpp_in_primary_file (pfile))
     cpp_error (pfile, CPP_DL_WARNING, "#pragma once in main file");
 
-  check_eol (pfile);
+  check_eol (pfile, false);
   _cpp_mark_file_once_only (pfile, pfile->buffer->file);
 }
 
@@ -1453,7 +1456,7 @@ do_pragma_system_header (cpp_reader *pfile)
 	       "#pragma system_header ignored outside include file");
   else
     {
-      check_eol (pfile);
+      check_eol (pfile, false);
       skip_rest_of_line (pfile);
       cpp_make_system_header (pfile, 1, 0);
     }
@@ -1694,7 +1697,7 @@ do_ifdef (cpp_reader *pfile)
 		    pfile->cb.used_undef (pfile, pfile->directive_line, node);
 		}
 	    }
-	  check_eol (pfile);
+	  check_eol (pfile, false);
 	}
     }
 
@@ -1730,7 +1733,7 @@ do_ifndef (cpp_reader *pfile)
 		    pfile->cb.used_undef (pfile, pfile->directive_line, node);
 		}
 	    }
-	  check_eol (pfile);
+	  check_eol (pfile, false);
 	}
     }
 
@@ -1783,7 +1786,7 @@ do_else (cpp_reader *pfile)
 
       /* Only check EOL if was not originally skipping.  */
       if (!ifs->was_skipping && CPP_OPTION (pfile, warn_endif_labels))
-	check_eol (pfile);
+	check_eol (pfile, false);
     }
 }
 
@@ -1844,7 +1847,7 @@ do_endif (cpp_reader *pfile)
     {
       /* Only check EOL if was not originally skipping.  */
       if (!ifs->was_skipping && CPP_OPTION (pfile, warn_endif_labels))
-	check_eol (pfile);
+	check_eol (pfile, false);
 
       /* If potential control macro, we go back outside again.  */
       if (ifs->next == 0 && ifs->mi_cmacro)
@@ -2088,7 +2091,7 @@ do_assert (cpp_reader *pfile)
 
       node->type = NT_ASSERTION;
       node->value.answers = new_answer;
-      check_eol (pfile);
+      check_eol (pfile, false);
     }
 }
 
@@ -2116,7 +2119,7 @@ do_unassert (cpp_reader *pfile)
 	  if (node->value.answers == 0)
 	    node->type = NT_VOID;
 
-	  check_eol (pfile);
+	  check_eol (pfile, false);
 	}
       else
 	_cpp_free_definition (node);
-- 
GitLab