diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 988a41ba5610e6f9d580ad050c83c67906b51f85..03f611250493516d5a0c9b2ae7a7ceb61a7d9e3c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2007-05-23  Simon Martin  <simartin@users.sourceforge.net>
+
+	PR preprocessor/20077
+	* gcc.dg/cpp/paste15.c: New test.
+
 2007-05-23  Sandra Loosemore  <sandra@codesourcery.com>
 	    Nigel Stephens  <nigel@mips.com>
 	    Richard Sandiford  <richard@codesourcery.com>
diff --git a/gcc/testsuite/gcc.dg/cpp/paste15.c b/gcc/testsuite/gcc.dg/cpp/paste15.c
new file mode 100644
index 0000000000000000000000000000000000000000..9d4ec36315c0fb1e38332d7cbf4417f6287a613c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/paste15.c
@@ -0,0 +1,15 @@
+/* PR preprocessor/20077 */
+/* { dg-do preprocess } */
+
+#define a   a ## ## /* { dg-error "end of a macro expansion" } */
+#define b() b ## ## /* { dg-error "end of a macro expansion" } */
+#define c   c ##    /* { dg-error "end of a macro expansion" } */
+#define d() d ##    /* { dg-error "end of a macro expansion" } */
+
+
+#define e   ## ## e /* { dg-error "end of a macro expansion" } */
+#define f() ## ## f /* { dg-error "end of a macro expansion" } */
+#define g   ## g    /* { dg-error "end of a macro expansion" } */
+#define h() ## h    /* { dg-error "end of a macro expansion" } */
+#define i   ##      /* { dg-error "end of a macro expansion" } */
+#define j() ##      /* { dg-error "end of a macro expansion" } */
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 44023594743b1d988f05b7e8038c051692b9132b..8f760cc1d9592e790b9e4d75960c144bceb8f34c 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,10 @@
+2007-05-23  Simon Martin  <simartin@users.sourceforge.net>
+
+	PR preprocessor/20077
+	* macro.c (create_iso_definition): Fixed the method to determine
+	whether the token-pasting operator appears at the beginning or the end
+	of a macro.
+
 2007-05-21  Ian Lance Taylor  <iant@google.com>
 
 	* internal.h (struct cpp_reader): Add new fields:
diff --git a/libcpp/macro.c b/libcpp/macro.c
index 748635f408ed9cd9550c7f8061f5f735fa25ead3..12681c34338806579292aa899c9dc42b88654da3 100644
--- a/libcpp/macro.c
+++ b/libcpp/macro.c
@@ -1434,6 +1434,9 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
 {
   cpp_token *token;
   const cpp_token *ctoken;
+  bool following_paste_op = false;
+  const char *paste_op_error_msg =
+    N_("'##' cannot appear at either end of a macro expansion");
 
   /* Get the first token of the expansion (or the '(' of a
      function-like macro).  */
@@ -1527,26 +1530,34 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro)
 	}
 
       if (token->type == CPP_EOF)
-	break;
+	{
+	  /* Paste operator constraint 6.10.3.3.1:
+	     Token-paste ##, can appear in both object-like and
+	     function-like macros, but not at the end.  */
+	  if (following_paste_op)
+	    {
+	      cpp_error (pfile, CPP_DL_ERROR, paste_op_error_msg);
+	      return false;
+	    }
+	  break;
+	}
 
       /* Paste operator constraint 6.10.3.3.1.  */
       if (token->type == CPP_PASTE)
 	{
 	  /* Token-paste ##, can appear in both object-like and
-	     function-like macros, but not at the ends.  */
-	  if (--macro->count > 0)
-	    token = lex_expansion_token (pfile, macro);
-
-	  if (macro->count == 0 || token->type == CPP_EOF)
+	     function-like macros, but not at the beginning.  */
+	  if (macro->count == 1)
 	    {
-	      cpp_error (pfile, CPP_DL_ERROR,
-		 "'##' cannot appear at either end of a macro expansion");
+	      cpp_error (pfile, CPP_DL_ERROR, paste_op_error_msg);
 	      return false;
 	    }
 
+	  --macro->count;
 	  token[-1].flags |= PASTE_LEFT;
 	}
 
+      following_paste_op = (token->type == CPP_PASTE);
       token = lex_expansion_token (pfile, macro);
     }