OSDN Git Service

PR preprocessor/34692
[pf3gnuchains/gcc-fork.git] / libcpp / macro.c
index 748635f..fd624b1 100644 (file)
@@ -1,7 +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,
-   2006 Free Software Foundation, Inc.
+   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
@@ -41,11 +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_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 *);
@@ -55,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.  */
@@ -263,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)
@@ -293,8 +303,7 @@ builtin_macro (cpp_reader *pfile, cpp_hashnode *node)
       if (pfile->state.in_directive)
        return 0;
 
-      _cpp_do__Pragma (pfile);
-      return 1;
+      return _cpp_do__Pragma (pfile);
     }
 
   buf = _cpp_builtin_macro_text (pfile, node);
@@ -445,7 +454,9 @@ paste_tokens (cpp_reader *pfile, const cpp_token **plhs, const cpp_token *rhs)
      false doesn't work, since we want to clear the PASTE_LEFT flag.  */
   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);
@@ -508,8 +519,10 @@ paste_all_tokens (cpp_reader *pfile, const cpp_token *lhs)
        rhs = *FIRST (context).ptoken++;
 
       if (rhs->type == CPP_PADDING)
-       abort ();
-
+       {
+         if (rhs->flags & PASTE_LEFT)
+           abort ();
+       }
       if (!paste_tokens (pfile, &lhs, rhs))
        break;
     }
@@ -565,9 +578,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;
@@ -635,6 +651,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;
        }
@@ -699,9 +760,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;
 
@@ -718,7 +781,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
@@ -739,9 +802,13 @@ 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;
@@ -752,6 +819,7 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node)
   if (! (node->flags & NODE_BUILTIN))
     {
       cpp_macro *macro = node->value.macro;
+      _cpp_buff *pragma_buff = NULL;
 
       if (macro->fun_like)
        {
@@ -760,7 +828,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--;
@@ -772,6 +840,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;
            }
 
@@ -788,6 +859,25 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node)
       if (macro->paramc == 0)
        _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;
     }
 
@@ -1087,6 +1177,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 (;;)
     {
@@ -1132,10 +1224,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);
            }
@@ -1157,6 +1256,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.  */
@@ -1434,6 +1554,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 +1650,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);
     }
 
@@ -1647,7 +1778,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;