From d09e893f10b6bb8bea9eafce9fd3f008f9cb5027 Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Sun, 1 Jan 2006 00:45:58 +0100
Subject: [PATCH] re PR c++/25294 (Bogus "unterminated comment" error from
 #pragma comment)

	PR c++/25294
	* directives.c (do_pragma): If pragma line ends with multi-line
	block comment, end the saved deferred pragma string before that
	comment.  Handle embedded '\0' chars on the pragma line.

	* gcc.dg/pragma-pack-3.c: New test.
	* g++.dg/parse/pragma3.C: New test.

From-SVN: r109201
---
 gcc/testsuite/ChangeLog              |  6 ++++
 gcc/testsuite/g++.dg/parse/pragma3.C | 26 ++++++++++++++
 gcc/testsuite/gcc.dg/pragma-pack-3.c | 27 ++++++++++++++
 libcpp/ChangeLog                     |  7 ++++
 libcpp/directives.c                  | 53 +++++++++++++++++++++++++---
 5 files changed, 115 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/parse/pragma3.C
 create mode 100644 gcc/testsuite/gcc.dg/pragma-pack-3.c

diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a3accaf7584f..e953e006debc 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2006-01-01  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c++/25294
+	* gcc.dg/pragma-pack-3.c: New test.
+	* g++.dg/parse/pragma3.C: New test.
+
 2005-12-30  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
 	PR middle-end/24827
diff --git a/gcc/testsuite/g++.dg/parse/pragma3.C b/gcc/testsuite/g++.dg/parse/pragma3.C
new file mode 100644
index 000000000000..36d7a8c6284b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/pragma3.C
@@ -0,0 +1,26 @@
+// PR c++/25294
+// { dg-do run }
+
+extern "C" void abort (void);
+
+struct S
+{
+  char a[3];
+#pragma pack(1) /* A block comment
+		   that ends on the next line.  */
+  struct T
+  {
+    char b;
+    int c;
+  } d;
+#pragma pack /*/ */ () // C++ comment
+  int e;
+} s;
+
+int
+main ()
+{
+  if (sizeof (int) == 4 && sizeof (s) != 12)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pragma-pack-3.c b/gcc/testsuite/gcc.dg/pragma-pack-3.c
new file mode 100644
index 000000000000..e276bd007fe3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pragma-pack-3.c
@@ -0,0 +1,27 @@
+/* PR c++/25294 */
+/* { dg-options "-std=gnu99" } */
+/* { dg-do run } */
+
+extern void abort (void);
+
+struct S
+{
+  char a[3];
+#pragma pack(1) /* A block comment
+		   that ends on the next line.  */
+  struct T
+  {
+    char b;
+    int c;
+  } d;
+#pragma pack /*/ */ () // C++ comment
+  int e;
+} s;
+
+int
+main ()
+{
+  if (sizeof (int) == 4 && sizeof (s) != 12)
+    abort ();
+  return 0;
+}
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index e21ea6dc5247..b2f0c9a2bf96 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,10 @@
+2006-01-01  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c++/25294
+	* directives.c (do_pragma): If pragma line ends with multi-line
+	block comment, end the saved deferred pragma string before that
+	comment.  Handle embedded '\0' chars on the pragma line.
+
 2005-12-22  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
 	PR c++/23333
diff --git a/libcpp/directives.c b/libcpp/directives.c
index 7159f07a6886..2de65fbeaa34 100644
--- a/libcpp/directives.c
+++ b/libcpp/directives.c
@@ -1,6 +1,7 @@
 /* CPP Library. (Directive handling.)
    Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
    Contributed by Per Bothner, 1994-95.
    Based on CCCP program by Paul Rubin, June 1986
    Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -1280,15 +1281,59 @@ do_pragma (cpp_reader *pfile)
 	  /* Squirrel away the pragma text.  Pragmas are
 	     newline-terminated. */
 	  const uchar *line_end;
-	  uchar *s;
+	  uchar *s, c, cc;
 	  cpp_string body;
 	  cpp_token *ptok;
 
-	  line_end = ustrchr (line_start, '\n');
+	  for (line_end = line_start; (c = *line_end) != '\n'; line_end++)
+	    if (c == '"' || c == '\'')
+	      {
+		/* Skip over string literal.  */
+		do
+		  {
+		    cc = *++line_end;
+		    if (cc == '\\' && line_end[1] != '\n')
+		      line_end++;
+		    else if (cc == '\n')
+		      {
+			line_end--;
+			break;
+		      }
+		  }
+		while (cc != c);
+	      }
+	    else if (c == '/')
+	      {
+		if (line_end[1] == '*')
+		  {
+		    /* Skip over C block comment, unless it is multi-line.
+		       When encountering multi-line block comment, terminate
+		       the pragma token right before that block comment.  */
+		    const uchar *le = line_end + 2;
+		    while (*le != '\n')
+		      if (*le++ == '*' && *le == '/')
+			{
+			  line_end = le;
+			  break;
+			}
+		    if (line_end < le)
+		      break;
+		  }
+		else if (line_end[1] == '/'
+			 && (CPP_OPTION (pfile, cplusplus_comments)
+			     || cpp_in_system_header (pfile)))
+		  {
+		    line_end += 2;
+		    while (*line_end != '\n')
+		      line_end++;
+		    break;
+		  }
+	      }
 
 	  body.len = (line_end - line_start) + 1;
 	  s = _cpp_unaligned_alloc (pfile, body.len + 1);
-	  memcpy (s, line_start, body.len);
+	  memcpy (s, line_start, body.len - 1);
+	  s[body.len - 1] = '\n';
 	  s[body.len] = '\0';
 	  body.text = s;
 
-- 
GitLab