Jakub Jelinek <ja...@redhat.com> writes:

> On Mon, Feb 02, 2015 at 03:41:50PM +0100, Dodji Seketeli wrote:
>> libcpp/ChangeLog:
>> 
>>      * internal.h (cpp_reader::top_most_macro_node): New data member.
>>      * macro.c (enter_macro_context): Pass the location of the end of
>>      the top-most invocation of the function-like macro, or the
>>      location of the expansion point of the top-most object-like macro.
>>      (cpp_get_token_1): Store the top-most macro node in the new
>>      pfile->top_most_macro_node data member.
>>      (_cpp_pop_context): Clear the new cpp_reader::top_most_macro_node
>>      data member.
>> 
>> gcc/testsuite/ChangeLog:
>> 
>>      * gcc.dg/cpp/builtin-macro-1.c: New test case.
>
> Ok, thanks.

Thanks.  The patch that finally passed bootstrap is the one below.  It's
slightly different in the condition I use to detect that we are popping
the context of the top-most macro expansion stored in
pfile->top_most_macro_node in _cpp_pop_context().  I now use:

+      if (macro == pfile->top_most_macro_node && context->prev == NULL)

And the context->prev == NULL means, "this is the first macro expansion
context on the the stack".  I have also corrected a typo by
s/poping/popping/.  I don't know what I was thinking before.

Bootstrapped and tested on x86_64-unknown-linux-gnu against trunk.

libcpp/ChangeLog:

        * internal.h (cpp_reader::top_most_macro_node): New data member.
        * macro.c (enter_macro_context): Pass the location of the end of
        the top-most invocation of the function-like macro, or the
        location of the expansion point of the top-most object-like macro.
        (cpp_get_token_1): Store the top-most macro node in the new
        pfile->top_most_macro_node data member.
        (_cpp_pop_context): Clear the new cpp_reader::top_most_macro_node
        data member.

gcc/testsuite/ChangeLog:

        * gcc.dg/cpp/builtin-macro-1.c: New test case.

Signed-off-by: Dodji Seketeli <do...@redhat.com>
---
 gcc/testsuite/gcc.dg/cpp/builtin-macro-1.c | 28 +++++++++++++++++++++++++++
 libcpp/internal.h                          |  5 +++++
 libcpp/macro.c                             | 31 +++++++++++++++++++++++++++---
 3 files changed, 61 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/cpp/builtin-macro-1.c

diff --git a/gcc/testsuite/gcc.dg/cpp/builtin-macro-1.c 
b/gcc/testsuite/gcc.dg/cpp/builtin-macro-1.c
new file mode 100644
index 0000000..90c2883
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/builtin-macro-1.c
@@ -0,0 +1,28 @@
+/* Origin PR preprocessor/64803
+
+   This test ensures that the value the __LINE__ macro expands to is
+   constant and corresponds to the line of the closing parenthesis of
+   the top-most function-like macro expansion it's part of.
+
+   { dg-do run }
+   { do-options -no-integrated-cpp }  */
+
+#include <assert.h>
+
+#define C(a, b) a ## b
+#define L(x) C(L, x)
+#define M(a) int L(__LINE__) = __LINE__; assert(L(__LINE__) == __LINE__);
+
+int
+main()
+{
+  M(a
+    );
+
+  assert(L20 == 20);           /* 20 is the line number of the
+                                  closing parenthesis of the
+                                  invocation of the M macro.  Please
+                                  adjust in case the layout of this
+                                  file changes.  */
+  return 0;
+}
diff --git a/libcpp/internal.h b/libcpp/internal.h
index 1a74020..96ccc19 100644
--- a/libcpp/internal.h
+++ b/libcpp/internal.h
@@ -421,6 +421,11 @@ struct cpp_reader
      macro invocation.  */
   source_location invocation_location;
 
+  /* This is the node representing the macro being expanded at
+     top-level.  The value of this data member is valid iff
+     in_macro_expansion_p() returns TRUE.  */
+  cpp_hashnode *top_most_macro_node;
+
   /* Nonzero if we are about to expand a macro.  Note that if we are
      really expanding a macro, the function macro_of_context returns
      the macro being expanded and this flag is set to false.  Client
diff --git a/libcpp/macro.c b/libcpp/macro.c
index 9571345..1e0a0b5 100644
--- a/libcpp/macro.c
+++ b/libcpp/macro.c
@@ -1228,7 +1228,24 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode 
*node,
 
   pfile->about_to_expand_macro_p = false;
   /* Handle built-in macros and the _Pragma operator.  */
-  return builtin_macro (pfile, node, location);
+  {
+    source_location loc;
+    if (/* The top-level macro invocation that triggered the expansion
+          we are looking at is with a standard macro ...*/
+       !(pfile->top_most_macro_node->flags & NODE_BUILTIN)
+       /* ... and it's a function-like macro invocation.  */
+       && pfile->top_most_macro_node->value.macro->fun_like)
+      /* Then the location of the end of the macro invocation is the
+        location of the closing parenthesis.  */
+      loc = pfile->cur_token[-1].src_loc;
+    else
+      /* Otherwise, the location of the end of the macro invocation is
+        the location of the expansion point of that top-level macro
+        invocation.  */
+      loc = location;
+
+    return builtin_macro (pfile, node, loc);
+  }
 }
 
 /* De-allocate the memory used by BUFF which is an array of instances
@@ -2296,6 +2313,10 @@ _cpp_pop_context (cpp_reader *pfile)
             macro expansion.  */
          && macro_of_context (context->prev) != macro)
        macro->flags &= ~NODE_DISABLED;
+
+      if (macro == pfile->top_most_macro_node && context->prev == NULL)
+       /* We are popping the context of the top-most macro node.  */
+       pfile->top_most_macro_node = NULL;
     }
 
   if (context->buff)
@@ -2460,9 +2481,13 @@ cpp_get_token_1 (cpp_reader *pfile, source_location 
*location)
        {
          int ret = 0;
          /* If not in a macro context, and we're going to start an
-            expansion, record the location.  */
+            expansion, record the location and the top level macro
+            about to be expanded.  */
          if (!in_macro_expansion_p (pfile))
-           pfile->invocation_location = result->src_loc;
+           {
+             pfile->invocation_location = result->src_loc;
+             pfile->top_most_macro_node = node;
+           }
          if (pfile->state.prevent_expansion)
            break;
 
-- 
                Dodji

Reply via email to