cppmacro.c (funlike_invocation_p): Move some logic to caller in enter_macro_context.
authorNeil Booth <neil@daikokuya.demon.co.uk>
Mon, 8 Oct 2001 06:15:14 +0000 (06:15 +0000)
committerNeil Booth <neil@gcc.gnu.org>
Mon, 8 Oct 2001 06:15:14 +0000 (06:15 +0000)
* cppmacro.c (funlike_invocation_p): Move some logic to caller
in enter_macro_context.  Create a padding token in its own context
if necessary when the search for '(' fails.
(enter_macro_context): Update.

* gcc.dg/cpp/spacing1.c: Update test.

From-SVN: r46070

gcc/ChangeLog
gcc/cppmacro.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/cpp/spacing1.c

index f7804a2a0bc5b3d12a05b8fc92c6def575c79864..559df72d18ffd5f9d967f934b9eebdfcd0851abd 100644 (file)
@@ -1,3 +1,10 @@
+2001-10-08  Neil Booth  <neil@daikokuya.demon.co.uk>
+
+       * cppmacro.c (funlike_invocation_p): Move some logic to caller
+       in enter_macro_context.  Create a padding token in its own context
+       if necessary when the search for '(' fails.
+       (enter_macro_context): Update.
+
 2001-10-07  Joseph S. Myers  <jsm28@cam.ac.uk>
 
        * ChangeLog.2, c-decl.c, config/i386/i386.md, doc/gcc.texi, gcc.c,
index f9fb0e1ffa008e8b36f3848d596394f7537f87be..221682e97d774841aa03fbb69b7102381699b0ef 100644 (file)
@@ -75,8 +75,8 @@ static const cpp_token *stringify_arg PARAMS ((cpp_reader *, macro_arg *));
 static void paste_all_tokens PARAMS ((cpp_reader *, const cpp_token *));
 static bool paste_tokens PARAMS ((cpp_reader *, const cpp_token **,
                                  const cpp_token *));
-static int funlike_invocation_p PARAMS ((cpp_reader *, cpp_hashnode *));
 static void replace_args PARAMS ((cpp_reader *, cpp_hashnode *, macro_arg *));
+static _cpp_buff *funlike_invocation_p PARAMS ((cpp_reader *, cpp_hashnode *));
 
 /* #define directive parsing and handling.  */
 
@@ -616,46 +616,41 @@ collect_args (pfile, node)
   return NULL;
 }
 
-static int
+/* 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.  */
+static _cpp_buff *
 funlike_invocation_p (pfile, node)
      cpp_reader *pfile;
      cpp_hashnode *node;
 {
-  const cpp_token *maybe_paren;
-  _cpp_buff *buff = NULL;
+  const cpp_token *token, *padding = NULL;
 
-  pfile->state.prevent_expansion++;
-  pfile->keep_tokens++;
-
-  pfile->state.parsing_args = 1;
-  do
-    maybe_paren = cpp_get_token (pfile);
-  while (maybe_paren->type == CPP_PADDING);
-  pfile->state.parsing_args = 2;
-
-  if (maybe_paren->type == CPP_OPEN_PAREN)
-    buff = collect_args (pfile, node);
-  else
+  for (;;)
     {
-      _cpp_backup_tokens (pfile, 1);
-      if (CPP_WTRADITIONAL (pfile) && ! node->value.macro->syshdr)
-       cpp_warning (pfile,
- "function-like macro \"%s\" must be used with arguments in traditional C",
-                    NODE_NAME (node));
+      token = cpp_get_token (pfile);
+      if (token->type != CPP_PADDING)
+       break;
+      if (padding == NULL
+         || (!(padding->flags & PREV_WHITE) && token->val.source == NULL))
+       padding = token;
     }
 
-  pfile->state.parsing_args = 0;
-  pfile->keep_tokens--;
-  pfile->state.prevent_expansion--;
-
-  if (buff)
+  if (token->type == CPP_OPEN_PAREN)
     {
-      if (node->value.macro->paramc > 0)
-       replace_args (pfile, node, (macro_arg *) buff->base);
-      _cpp_release_buff (pfile, buff);
+      pfile->state.parsing_args = 2;
+      return collect_args (pfile, node);
     }
 
-  return buff != 0;
+  /* Back up.  We may have skipped padding, in which case backing up
+     more than one token when expanding macros is in general too
+     difficult.  We re-insert it in its own context.  */
+  _cpp_backup_tokens (pfile, 1);
+  if (padding)
+    push_token_context (pfile, NULL, padding, 1);
+
+  return NULL;
 }
 
 /* Push the context of a macro onto the context stack.  TOKEN is the
@@ -675,8 +670,32 @@ enter_macro_context (pfile, node)
     {
       cpp_macro *macro = node->value.macro;
 
-      if (macro->fun_like && !funlike_invocation_p (pfile, node))
-       return 0;
+      if (macro->fun_like)
+       {
+         _cpp_buff *buff;
+
+         pfile->state.prevent_expansion++;
+         pfile->keep_tokens++;
+         pfile->state.parsing_args = 1;
+         buff = funlike_invocation_p (pfile, node);
+         pfile->state.parsing_args = 0;
+         pfile->keep_tokens--;
+         pfile->state.prevent_expansion--;
+
+         if (buff == NULL)
+           {
+             if (CPP_WTRADITIONAL (pfile) && ! node->value.macro->syshdr)
+               cpp_warning (pfile,
+ "function-like macro \"%s\" must be used with arguments in traditional C",
+                            NODE_NAME (node));
+
+             return 0;
+           }
+
+         if (node->value.macro->paramc > 0)
+           replace_args (pfile, node, (macro_arg *) buff->base);
+         _cpp_release_buff (pfile, buff);
+       }
 
       /* Disable the macro within its expansion.  */
       node->flags |= NODE_DISABLED;
index 3fdd1e67ada6d041b539b93ac4038916c454cedd..a314286409d3fe88123eab5893e0110ae2e26bfb 100644 (file)
@@ -1,3 +1,7 @@
+2001-10-08  Neil Booth  <neil@daikokuya.demon.co.uk>
+
+       * gcc.dg/cpp/spacing1.c: Update test.
+
 2001-10-07  Joseph S. Myers  <jsm28@cam.ac.uk>
 
        * gcc.c-torture/unsorted/unsorted.exp, lib/file-format.exp: Fix
index 9a3933b7308f18c35345de08af33cb075f1b5346..ad1af4e91c71392d514c36e529f91fa0e3b0239d 100644 (file)
 #define f(x) x
 #define glue(x, y) x ## y
 #define EMPTY
+/* These are based on PR 4492, we mustn't lose padding tokens when
+   scanning ahead for a '(' and failing to find it.  */
+#define A(x) B x
+#define B(x)
+#define C A
+#define D() A
 
 /* The correct output is shown here.  Note the spaces, and the way
    everything after the invocation of f appears on the same line.
 
  44 ;
+B Q B Q A Q A:
 f
 bar
 g "1 2" bam baz
@@ -26,6 +33,7 @@ g "1 2" bam baz
 */
 
 glue (EMPTY 4, 4) EMPTY;
+A(Q) C(Q) D()Q D():
 f
 bar
 f (g) str
@@ -37,10 +45,11 @@ f (g) str
 
 /*
    { dg-final { if ![file exists spacing1.i] { return }                   } }
-   { dg-final { if \{ [grep spacing1.i " 44 ;"] != "" \}  \{              } }
+   { dg-final { if \{ [grep spacing1.i " 44 ;"] != "" \}              \{  } }
+   { dg-final { if \{ [grep spacing1.i "B Q B Q A Q A:"] != "" \}     \{  } }
    { dg-final { if \{ [grep spacing1.i "f.*bar"] == "" \} \{              } }
    { dg-final { if \{ [grep spacing1.i "^bar"] != "" \}   \{              } }
    { dg-final { if \{ [grep spacing1.i "g \"1 2\" bam baz"] != "" \} \{   } }
-   { dg-final { return \} \} \} \}                                        } }
+   { dg-final { return \} \} \} \} \}                                     } }
    { dg-final { fail "spacing1.c: spacing and new-line preservation"      } }
 */