From f8abc9ba2d15ac7ee06ce9c135732276203ece1d Mon Sep 17 00:00:00 2001 From: Dodji Seketeli Date: Tue, 3 Feb 2015 10:26:46 +0100 Subject: [PATCH] PR preprocessor/64803 - __LINE__ inside macro is not constant Consider the example code mentionned in this PR: $ cat -n test.c 1 #define C(a, b) a ## b 2 #define L(x) C(L, x) 3 #define M(a) goto L(__LINE__); __LINE__; L(__LINE__): 4 M(a /* --> this is the line of the expansion point of M. */ 5 ); /* --> this is the line of the end of the invocation of M. */ $ "cc1 -quiet -E test.c" yields: goto L5; 5; L4: ; Notice how we have a 'L4' there, where it should be L5. That is the issue. My understanding is that during the *second* expansion of __LINE__ (the one between the two L(__LINE__)), builtin_macro() is called by enter_macro_context() with the location of the expansion point of M (which is at line 4). Then _cpp_builtin_macro_text() expands __LINE__ into the line number of the location of the last token that has been lexed, which is the location of the closing parenthesis of the invocation of M, at line 5. So that invocation of __LINE__ is expanded into 5. Now let's see why the last invocation of __LINE__ is expanded into 4. In builtin_macro(), we have this code at some point: /* Set pfile->cur_token as required by _cpp_lex_direct. */ pfile->cur_token = _cpp_temp_token (pfile); cpp_token *token = _cpp_lex_direct (pfile); /* We should point to the expansion point of the builtin macro. */ token->src_loc = loc; The first two statements insert a new token in the stream of lexed token and pfile->cur_token[-1], is the "new" last token that has been lexed. But the location of pfile->cur_token[-1] is the same location as the location of the "previous" pfile->cur_token[-1], by courtesy of _cpp_temp_token(). So normally, in subsequent invocations of builtin_macro(), the location of pfile->cur_token[-1] should always be the location of the closing parenthesis of the invocation of M at line 5. Except that that code in master now has the statement "token->src_loc = loc;" on the next line. That statement actually sets the location of pfile->cur_token[-1] to 'loc'. Which is the location of the expansion point of M, which is on line 4. So in the subsequent call to builtin_macro() (for the last expansion of __LINE__ in L(__LINE__)), for _cpp_builtin_macro_text(), pfile->cur_token[-1].src_loc is going to have a line number of 4. I think the core issue here is that the location that is passed to builtin_macro() from enter_macro_context() is not correct when we are in presence of a top-most function-like macro invocation; in that case, that location should be the location of the closing parenthesis of the macro invocation. Otherwise, if we are in presence of a a top-most object-like macro invocation then the location passed down to builtin_macro should be the location of the expansion point of the macro. That way, in the particular case of the input code above, the location received by builtin_macro() will always have line number 5. Boostrapped 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 From-SVN: r220367 --- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.dg/cpp/builtin-macro-1.c | 28 +++++++++++++++++++ libcpp/ChangeLog | 12 +++++++++ libcpp/internal.h | 5 ++++ libcpp/macro.c | 31 +++++++++++++++++++--- 5 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/cpp/builtin-macro-1.c diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2039b4c4697..c85fa087d60 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-02-03 + + PR preprocessor/64803 + * gcc.dg/cpp/builtin-macro-1.c: New test case. + 2015-02-02 Jan Hubicka * g++.dg/ipa/devirt-37.C: Disable early inlining. 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 00000000000..90c2883b471 --- /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 + +#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/ChangeLog b/libcpp/ChangeLog index 5dd64468a90..325f7060963 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,15 @@ +2015-02-03 + + PR preprocessor/64803 + * 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. + 2015-01-30 Szabolcs Nagy * lex.c (search_line_fast): Change __ARM_NEON__ to __ARM_NEON. diff --git a/libcpp/internal.h b/libcpp/internal.h index 1a7402079ce..96ccc19e447 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 95713450c27..1e0a0b560ba 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; -- 2.30.2