diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a3accaf7584f65c447bb022c2776b0bd8a7de449..e953e006debc486e45b6c251c87d6de839d4db19 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 0000000000000000000000000000000000000000..36d7a8c6284bfe6998f4150490ce0aaaa13a5cd0
--- /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 0000000000000000000000000000000000000000..e276bd007fe3fde8443e49af56584e7b021f2e98
--- /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 e21ea6dc524766f95b858992c85f72cf63a4f3d0..b2f0c9a2bf96384fadc6053a4b761664b11b3986 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 7159f07a688689b3255a7cbcdc9ebda798bad71c..2de65fbeaa348ec1a97f623e37923d32f3555094 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;