OSDN Git Service

2008-06-13 Andrew Haley <aph@redhat.com>
[pf3gnuchains/gcc-fork.git] / libcpp / macro.c
index a0aa93e..edc2856 100644 (file)
@@ -1,6 +1,7 @@
 /* Part of CPP library.  (Macro and #define handling.)
    Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005,
+   2006, 2007, 2008 Free Software Foundation, Inc.
    Written by Per Bothner, 1994.
    Based on CCCP program by Paul Rubin, June 1986
    Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -40,13 +41,13 @@ struct macro_arg
 
 /* Macro expansion.  */
 
-static int enter_macro_context (cpp_reader *, cpp_hashnode *);
+static int enter_macro_context (cpp_reader *, cpp_hashnode *,
+                               const cpp_token *);
 static int builtin_macro (cpp_reader *, cpp_hashnode *);
-static void push_token_context (cpp_reader *, cpp_hashnode *,
-                               const cpp_token *, unsigned int);
 static void push_ptoken_context (cpp_reader *, cpp_hashnode *, _cpp_buff *,
                                 const cpp_token **, unsigned int);
-static _cpp_buff *collect_args (cpp_reader *, const cpp_hashnode *);
+static _cpp_buff *collect_args (cpp_reader *, const cpp_hashnode *,
+                               _cpp_buff **);
 static cpp_context *next_context (cpp_reader *);
 static const cpp_token *padding_token (cpp_reader *, const cpp_token *);
 static void expand_arg (cpp_reader *, macro_arg *);
@@ -56,7 +57,8 @@ static void paste_all_tokens (cpp_reader *, const cpp_token *);
 static bool paste_tokens (cpp_reader *, const cpp_token **, const cpp_token *);
 static void replace_args (cpp_reader *, cpp_hashnode *, cpp_macro *,
                          macro_arg *);
-static _cpp_buff *funlike_invocation_p (cpp_reader *, cpp_hashnode *);
+static _cpp_buff *funlike_invocation_p (cpp_reader *, cpp_hashnode *,
+                                       _cpp_buff **);
 static bool create_iso_definition (cpp_reader *, cpp_macro *);
 
 /* #define directive parsing and handling.  */
@@ -125,6 +127,44 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)
                 NODE_NAME (node));
       break;
 
+    case BT_TIMESTAMP:
+      {
+       cpp_buffer *pbuffer = cpp_get_buffer (pfile);
+       if (pbuffer->timestamp == NULL)
+         {
+           /* Initialize timestamp value of the assotiated file. */
+            struct _cpp_file *file = cpp_get_file (pbuffer);
+           if (file)
+             {
+               /* Generate __TIMESTAMP__ string, that represents 
+                  the date and time of the last modification 
+                  of the current source file. The string constant 
+                  looks like "Sun Sep 16 01:03:52 1973".  */
+               struct tm *tb = NULL;
+               struct stat *st = _cpp_get_file_stat (file);
+               if (st)
+                 tb = localtime (&st->st_mtime);
+               if (tb)
+                 {
+                   char *str = asctime (tb);
+                   size_t len = strlen (str);
+                   unsigned char *buf = _cpp_unaligned_alloc (pfile, len + 2);
+                   buf[0] = '"';
+                   strcpy ((char *) buf + 1, str);
+                   buf[len] = '"';
+                   pbuffer->timestamp = buf;
+                 }
+               else
+                 {
+                   cpp_errno (pfile, CPP_DL_WARNING,
+                       "could not determine file timestamp");
+                   pbuffer->timestamp = UC"\"??? ??? ?? ??:??:?? ????\"";
+                 }
+             }
+         }
+       result = pbuffer->timestamp;
+      }
+      break;
     case BT_FILE:
     case BT_BASE_FILE:
       {
@@ -171,16 +211,12 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)
         However, if (a) we are in a system header, (b) the option
         stdc_0_in_system_headers is true (set by target config), and
         (c) we are not in strictly conforming mode, then it has the
-        value 0.  */
+        value 0.  (b) and (c) are already checked in cpp_init_builtins.  */
     case BT_STDC:
-      {
-       if (cpp_in_system_header (pfile)
-           && CPP_OPTION (pfile, stdc_0_in_system_headers)
-           && !CPP_OPTION (pfile,std))
-         number = 0;
-       else
-         number = 1;
-      }
+      if (cpp_in_system_header (pfile))
+       number = 0;
+      else
+       number = 1;
       break;
 
     case BT_DATE:
@@ -220,8 +256,8 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)
              cpp_errno (pfile, CPP_DL_WARNING,
                         "could not determine date and time");
                
-             pfile->date = U"\"??? ?? ????\"";
-             pfile->time = U"\"??:??:??\"";
+             pfile->date = UC"\"??? ?? ????\"";
+             pfile->time = UC"\"??:??:??\"";
            }
        }
 
@@ -230,6 +266,13 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)
       else
        result = pfile->time;
       break;
+
+    case BT_COUNTER:
+      if (CPP_OPTION (pfile, directives_only) && pfile->state.in_directive)
+       cpp_error (pfile, CPP_DL_ERROR,
+           "__COUNTER__ expanded inside directive with -fdirectives-only");
+      number = pfile->counter++;
+      break;
     }
 
   if (result == NULL)
@@ -260,15 +303,7 @@ builtin_macro (cpp_reader *pfile, cpp_hashnode *node)
       if (pfile->state.in_directive)
        return 0;
 
-      _cpp_do__Pragma (pfile);
-      if (pfile->directive_result.type == CPP_PRAGMA) 
-       {
-         cpp_token *tok = _cpp_temp_token (pfile);
-         *tok = pfile->directive_result;
-         push_token_context (pfile, NULL, tok, 1);
-       }
-
-      return 1;
+      return _cpp_do__Pragma (pfile);
     }
 
   buf = _cpp_builtin_macro_text (pfile, node);
@@ -282,7 +317,7 @@ builtin_macro (cpp_reader *pfile, cpp_hashnode *node)
 
   /* Set pfile->cur_token as required by _cpp_lex_direct.  */
   pfile->cur_token = _cpp_temp_token (pfile);
-  push_token_context (pfile, NULL, _cpp_lex_direct (pfile), 1);
+  _cpp_push_token_context (pfile, NULL, _cpp_lex_direct (pfile), 1);
   if (pfile->buffer->cur != pfile->buffer->rlimit)
     cpp_error (pfile, CPP_DL_ICE, "invalid built-in macro \"%s\"",
               NODE_NAME (node));
@@ -340,8 +375,10 @@ stringify_arg (cpp_reader *pfile, macro_arg *arg)
          continue;
        }
 
-      escape_it = (token->type == CPP_STRING || token->type == CPP_WSTRING
-                  || token->type == CPP_CHAR || token->type == CPP_WCHAR);
+      escape_it = (token->type == CPP_STRING || token->type == CPP_CHAR
+                  || token->type == CPP_WSTRING || token->type == CPP_STRING
+                  || token->type == CPP_STRING32 || token->type == CPP_CHAR32
+                  || token->type == CPP_STRING16 || token->type == CPP_CHAR16);
 
       /* Room for each char being written in octal, initial space and
         final quote and NUL.  */
@@ -405,23 +442,23 @@ stringify_arg (cpp_reader *pfile, macro_arg *arg)
 static bool
 paste_tokens (cpp_reader *pfile, const cpp_token **plhs, const cpp_token *rhs)
 {
-  unsigned char *buf, *end;
-  const cpp_token *lhs;
+  unsigned char *buf, *end, *lhsend;
+  cpp_token *lhs;
   unsigned int len;
-  bool valid;
 
-  lhs = *plhs;
-  len = cpp_token_len (lhs) + cpp_token_len (rhs) + 1;
+  len = cpp_token_len (*plhs) + cpp_token_len (rhs) + 1;
   buf = (unsigned char *) alloca (len);
-  end = cpp_spell_token (pfile, lhs, buf, false);
+  end = lhsend = cpp_spell_token (pfile, *plhs, buf, false);
 
   /* Avoid comment headers, since they are still processed in stage 3.
      It is simpler to insert a space here, rather than modifying the
      lexer to ignore comments in some circumstances.  Simply returning
      false doesn't work, since we want to clear the PASTE_LEFT flag.  */
-  if (lhs->type == CPP_DIV && rhs->type != CPP_EQ)
+  if ((*plhs)->type == CPP_DIV && rhs->type != CPP_EQ)
     *end++ = ' ';
-  end = cpp_spell_token (pfile, rhs, end, false);
+  /* In one obscure case we might see padding here.  */
+  if (rhs->type != CPP_PADDING)
+    end = cpp_spell_token (pfile, rhs, end, false);
   *end = '\n';
 
   cpp_push_buffer (pfile, buf, end - buf, /* from_stage3 */ true);
@@ -429,11 +466,33 @@ paste_tokens (cpp_reader *pfile, const cpp_token **plhs, const cpp_token *rhs)
 
   /* Set pfile->cur_token as required by _cpp_lex_direct.  */
   pfile->cur_token = _cpp_temp_token (pfile);
-  *plhs = _cpp_lex_direct (pfile);
-  valid = pfile->buffer->cur == pfile->buffer->rlimit;
-  _cpp_pop_buffer (pfile);
+  lhs = _cpp_lex_direct (pfile);
+  if (pfile->buffer->cur != pfile->buffer->rlimit)
+    {
+      source_location saved_loc = lhs->src_loc;
+
+      _cpp_pop_buffer (pfile);
+      _cpp_backup_tokens (pfile, 1);
+      *lhsend = '\0';
+
+      /* We have to remove the PASTE_LEFT flag from the old lhs, but
+        we want to keep the new location.  */
+      *lhs = **plhs;
+      *plhs = lhs;
+      lhs->src_loc = saved_loc;
+      lhs->flags &= ~PASTE_LEFT;
+
+      /* Mandatory error for all apart from assembler.  */
+      if (CPP_OPTION (pfile, lang) != CLK_ASM)
+       cpp_error (pfile, CPP_DL_ERROR,
+        "pasting \"%s\" and \"%s\" does not give a valid preprocessing token",
+                  buf, cpp_token_as_text (pfile, rhs));
+      return false;
+    }
 
-  return valid;
+  *plhs = lhs;
+  _cpp_pop_buffer (pfile);
+  return true;
 }
 
 /* Handles an arbitrarily long sequence of ## operators, with initial
@@ -462,25 +521,17 @@ paste_all_tokens (cpp_reader *pfile, const cpp_token *lhs)
        rhs = *FIRST (context).ptoken++;
 
       if (rhs->type == CPP_PADDING)
-       abort ();
-
-      if (!paste_tokens (pfile, &lhs, rhs))
        {
-         _cpp_backup_tokens (pfile, 1);
-
-         /* Mandatory error for all apart from assembler.  */
-         if (CPP_OPTION (pfile, lang) != CLK_ASM)
-           cpp_error (pfile, CPP_DL_ERROR,
-        "pasting \"%s\" and \"%s\" does not give a valid preprocessing token",
-                      cpp_token_as_text (pfile, lhs),
-                      cpp_token_as_text (pfile, rhs));
-         break;
+         if (rhs->flags & PASTE_LEFT)
+           abort ();
        }
+      if (!paste_tokens (pfile, &lhs, rhs))
+       break;
     }
   while (rhs->flags & PASTE_LEFT);
 
   /* Put the resulting token in its own context.  */
-  push_token_context (pfile, NULL, lhs, 1);
+  _cpp_push_token_context (pfile, NULL, lhs, 1);
 }
 
 /* Returns TRUE if the number of arguments ARGC supplied in an
@@ -529,9 +580,12 @@ _cpp_arguments_ok (cpp_reader *pfile, cpp_macro *macro, const cpp_hashnode *node
    invocation.  Assumes the opening parenthesis has been processed.
    If there is an error, emits an appropriate diagnostic and returns
    NULL.  Each argument is terminated by a CPP_EOF token, for the
-   future benefit of expand_arg().  */
+   future benefit of expand_arg().  If there are any deferred
+   #pragma directives among macro arguments, store pointers to the
+   CPP_PRAGMA ... CPP_PRAGMA_EOL tokens into *PRAGMA_BUFF buffer.  */
 static _cpp_buff *
-collect_args (cpp_reader *pfile, const cpp_hashnode *node)
+collect_args (cpp_reader *pfile, const cpp_hashnode *node,
+             _cpp_buff **pragma_buff)
 {
   _cpp_buff *buff, *base_buff;
   cpp_macro *macro;
@@ -599,6 +653,51 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node)
          else if (token->type == CPP_EOF
                   || (token->type == CPP_HASH && token->flags & BOL))
            break;
+         else if (token->type == CPP_PRAGMA)
+           {
+             cpp_token *newtok = _cpp_temp_token (pfile);
+
+             /* CPP_PRAGMA token lives in directive_result, which will
+                be overwritten on the next directive.  */
+             *newtok = *token;
+             token = newtok;
+             do
+               {
+                 if (*pragma_buff == NULL
+                     || BUFF_ROOM (*pragma_buff) < sizeof (cpp_token *))
+                   {
+                     _cpp_buff *next;
+                     if (*pragma_buff == NULL)
+                       *pragma_buff
+                         = _cpp_get_buff (pfile, 32 * sizeof (cpp_token *));
+                     else
+                       {
+                         next = *pragma_buff;
+                         *pragma_buff
+                           = _cpp_get_buff (pfile,
+                                            (BUFF_FRONT (*pragma_buff)
+                                             - (*pragma_buff)->base) * 2);
+                         (*pragma_buff)->next = next;
+                       }
+                   }
+                 *(const cpp_token **) BUFF_FRONT (*pragma_buff) = token;
+                 BUFF_FRONT (*pragma_buff) += sizeof (cpp_token *);
+                 if (token->type == CPP_PRAGMA_EOL)
+                   break;
+                 token = cpp_get_token (pfile);
+               }
+             while (token->type != CPP_EOF);
+
+             /* In deferred pragmas parsing_args and prevent_expansion
+                had been changed, reset it.  */
+             pfile->state.parsing_args = 2;
+             pfile->state.prevent_expansion = 1;
+
+             if (token->type == CPP_EOF)
+               break;
+             else
+               continue;
+           }
 
          arg->first[ntokens++] = token;
        }
@@ -663,9 +762,11 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node)
 /* Search for an opening parenthesis to the macro of NODE, in such a
    way that, if none is found, we don't lose the information in any
    intervening padding tokens.  If we find the parenthesis, collect
-   the arguments and return the buffer containing them.  */
+   the arguments and return the buffer containing them.  PRAGMA_BUFF
+   argument is the same as in collect_args.  */
 static _cpp_buff *
-funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node)
+funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node,
+                     _cpp_buff **pragma_buff)
 {
   const cpp_token *token, *padding = NULL;
 
@@ -682,7 +783,7 @@ funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node)
   if (token->type == CPP_OPEN_PAREN)
     {
       pfile->state.parsing_args = 2;
-      return collect_args (pfile, node);
+      return collect_args (pfile, node, pragma_buff);
     }
 
   /* CPP_EOF can be the end of macro arguments, or the end of the
@@ -694,7 +795,7 @@ funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node)
         too difficult.  We re-insert it in its own context.  */
       _cpp_backup_tokens (pfile, 1);
       if (padding)
-       push_token_context (pfile, NULL, padding, 1);
+       _cpp_push_token_context (pfile, NULL, padding, 1);
     }
 
   return NULL;
@@ -703,19 +804,31 @@ funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node)
 /* Push the context of a macro with hash entry NODE onto the context
    stack.  If we can successfully expand the macro, we push a context
    containing its yet-to-be-rescanned replacement list and return one.
-   Otherwise, we don't push a context and return zero.  */
+   If there were additionally any unexpanded deferred #pragma directives
+   among macro arguments, push another context containing the
+   pragma tokens before the yet-to-be-rescanned replacement list
+   and return two.  Otherwise, we don't push a context and return zero.  */
 static int
-enter_macro_context (cpp_reader *pfile, cpp_hashnode *node)
+enter_macro_context (cpp_reader *pfile, cpp_hashnode *node,
+                    const cpp_token *result)
 {
   /* The presence of a macro invalidates a file's controlling macro.  */
   pfile->mi_valid = false;
 
   pfile->state.angled_headers = false;
 
+  if ((node->flags & NODE_BUILTIN) && !(node->flags & NODE_USED))
+    {
+      node->flags |= NODE_USED;
+      if (pfile->cb.used_define)
+       pfile->cb.used_define (pfile, pfile->directive_line, node);
+    }
+
   /* Handle standard macros.  */
   if (! (node->flags & NODE_BUILTIN))
     {
       cpp_macro *macro = node->value.macro;
+      _cpp_buff *pragma_buff = NULL;
 
       if (macro->fun_like)
        {
@@ -724,7 +837,7 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node)
          pfile->state.prevent_expansion++;
          pfile->keep_tokens++;
          pfile->state.parsing_args = 1;
-         buff = funlike_invocation_p (pfile, node);
+         buff = funlike_invocation_p (pfile, node, &pragma_buff);
          pfile->state.parsing_args = 0;
          pfile->keep_tokens--;
          pfile->state.prevent_expansion--;
@@ -736,6 +849,9 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node)
  "function-like macro \"%s\" must be used with arguments in traditional C",
                           NODE_NAME (node));
 
+             if (pragma_buff)
+               _cpp_release_buff (pfile, pragma_buff);
+
              return 0;
            }
 
@@ -747,10 +863,36 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node)
       /* Disable the macro within its expansion.  */
       node->flags |= NODE_DISABLED;
 
+      if (!(node->flags & NODE_USED))
+       {
+         node->flags |= NODE_USED;
+         if (pfile->cb.used_define)
+           pfile->cb.used_define (pfile, pfile->directive_line, node);
+       }
+
       macro->used = 1;
 
       if (macro->paramc == 0)
-       push_token_context (pfile, node, macro->exp.tokens, macro->count);
+       _cpp_push_token_context (pfile, node, macro->exp.tokens, macro->count);
+
+      if (pragma_buff)
+       {
+         if (!pfile->state.in_directive)
+           _cpp_push_token_context (pfile, NULL,
+                                    padding_token (pfile, result), 1);
+         do
+           {
+             _cpp_buff *tail = pragma_buff->next;
+             pragma_buff->next = NULL;
+             push_ptoken_context (pfile, NULL, pragma_buff,
+                                  (const cpp_token **) pragma_buff->base,
+                                  ((const cpp_token **) BUFF_FRONT (pragma_buff)
+                                   - (const cpp_token **) pragma_buff->base));
+             pragma_buff = tail;
+           }
+         while (pragma_buff != NULL);
+         return 2;
+       }
 
       return 1;
     }
@@ -867,6 +1009,17 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, macro_arg
          if (src->flags & PASTE_LEFT)
            paste_flag = dest - 1;
        }
+      else if (CPP_PEDANTIC (pfile) && ! macro->syshdr
+              && ! CPP_OPTION (pfile, c99)
+              && ! cpp_in_system_header (pfile))
+       {
+         cpp_error (pfile, CPP_DL_PEDWARN,
+                    "invoking macro %s argument %d: "
+                    "empty macro arguments are undefined"
+                    " in ISO C90 and ISO C++98",
+                    NODE_NAME (node),
+                    src->val.arg_no);
+       }
 
       /* Avoid paste on RHS (even case count == 0).  */
       if (!pfile->state.in_directive && !(src->flags & PASTE_LEFT))
@@ -943,9 +1096,9 @@ push_ptoken_context (cpp_reader *pfile, cpp_hashnode *macro, _cpp_buff *buff,
 }
 
 /* Push a list of tokens.  */
-static void
-push_token_context (cpp_reader *pfile, cpp_hashnode *macro,
-                   const cpp_token *first, unsigned int count)
+void
+_cpp_push_token_context (cpp_reader *pfile, cpp_hashnode *macro,
+                        const cpp_token *first, unsigned int count)
 {
   cpp_context *context = next_context (pfile);
 
@@ -1051,6 +1204,8 @@ const cpp_token *
 cpp_get_token (cpp_reader *pfile)
 {
   const cpp_token *result;
+  bool can_set = pfile->set_invocation_location;
+  pfile->set_invocation_location = false;
 
   for (;;)
     {
@@ -1096,10 +1251,17 @@ cpp_get_token (cpp_reader *pfile)
 
       if (!(node->flags & NODE_DISABLED))
        {
-         if (!pfile->state.prevent_expansion
-             && enter_macro_context (pfile, node))
+         int ret;
+         /* If not in a macro context, and we're going to start an
+            expansion, record the location.  */
+         if (can_set && !context->macro)
+           pfile->invocation_location = result->src_loc;
+         if (pfile->state.prevent_expansion)
+           break;
+         ret = enter_macro_context (pfile, node, result);
+         if (ret)
            {
-             if (pfile->state.in_directive)
+             if (pfile->state.in_directive || ret == 2)
                continue;
              return padding_token (pfile, result);
            }
@@ -1121,6 +1283,27 @@ cpp_get_token (cpp_reader *pfile)
   return result;
 }
 
+/* Like cpp_get_token, but also returns a location separate from the
+   one provided by the returned token.  LOC is an out parameter; *LOC
+   is set to the location "as expected by the user".  This matters
+   when a token results from macro expansion -- the token's location
+   will indicate where the macro is defined, but *LOC will be the
+   location of the start of the expansion.  */
+const cpp_token *
+cpp_get_token_with_location (cpp_reader *pfile, source_location *loc)
+{
+  const cpp_token *result;
+
+  pfile->set_invocation_location = true;
+  result = cpp_get_token (pfile);
+  if (pfile->context->macro)
+    *loc = pfile->invocation_location;
+  else
+    *loc = result->src_loc;
+
+  return result;
+}
+
 /* Returns true if we're expanding an object-like macro that was
    defined in a system header.  Just checks the macro at the top of
    the stack.  Used for diagnostic suppression.  */
@@ -1155,7 +1338,7 @@ cpp_scan_nooutput (cpp_reader *pfile)
   pfile->state.prevent_expansion--;
 }
 
-/* Step back one (or more) tokens.  Can only step mack more than 1 if
+/* Step back one (or more) tokens.  Can only step back more than 1 if
    they are from the lexer, and not from macro expansion.  */
 void
 _cpp_backup_tokens (cpp_reader *pfile, unsigned int count)
@@ -1237,7 +1420,7 @@ _cpp_free_definition (cpp_hashnode *h)
   /* Macros and assertions no longer have anything to free.  */
   h->type = NT_VOID;
   /* Clear builtin flag in case of redefinition.  */
-  h->flags &= ~(NODE_BUILTIN | NODE_DISABLED);
+  h->flags &= ~(NODE_BUILTIN | NODE_DISABLED | NODE_USED);
 }
 
 /* Save parameter NODE to the parameter list of macro MACRO.  Returns
@@ -1372,10 +1555,12 @@ alloc_expansion_token (cpp_reader *pfile, cpp_macro *macro)
 static cpp_token *
 lex_expansion_token (cpp_reader *pfile, cpp_macro *macro)
 {
-  cpp_token *token;
+  cpp_token *token, *saved_cur_token;
 
+  saved_cur_token = pfile->cur_token;
   pfile->cur_token = alloc_expansion_token (pfile, macro);
   token = _cpp_lex_direct (pfile);
+  pfile->cur_token = saved_cur_token;
 
   /* Is this a parameter?  */
   if (token->type == CPP_NAME
@@ -1396,6 +1581,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).  */
@@ -1489,26 +1677,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);
     }
 
@@ -1564,18 +1760,12 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node)
     ok = _cpp_create_trad_definition (pfile, macro);
   else
     {
-      cpp_token *saved_cur_token = pfile->cur_token;
-
       ok = create_iso_definition (pfile, macro);
 
-      /* Restore lexer position because of games lex_expansion_token()
-        plays lexing the macro.  We set the type for SEEN_EOL() in
-        directives.c.
+      /* We set the type for SEEN_EOL() in directives.c.
 
         Longer term we should lex the whole line before coming here,
         and just copy the expansion.  */
-      saved_cur_token[-1].type = pfile->cur_token[-1].type;
-      pfile->cur_token = saved_cur_token;
 
       /* Stop the lexer accepting __VA_ARGS__.  */
       pfile->state.va_args_ok = 0;
@@ -1615,7 +1805,14 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node)
   /* Enter definition in hash table.  */
   node->type = NT_MACRO;
   node->value.macro = macro;
-  if (! ustrncmp (NODE_NAME (node), DSC ("__STDC_")))
+  if (! ustrncmp (NODE_NAME (node), DSC ("__STDC_"))
+      && ustrcmp (NODE_NAME (node), (const uchar *) "__STDC_FORMAT_MACROS")
+      /* __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS are mentioned
+        in the C standard, as something that one must use in C++.
+        However DR#593 indicates that these aren't actually mentioned
+        in the C++ standard.  We special-case them anyway.  */
+      && ustrcmp (NODE_NAME (node), (const uchar *) "__STDC_LIMIT_MACROS")
+      && ustrcmp (NODE_NAME (node), (const uchar *) "__STDC_CONSTANT_MACROS"))
     node->flags |= NODE_WARN;
 
   return ok;