2015-01-30 Dodji Seketeli 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. * gcc.dg/cpp/builtin-macro-1.c: New test case. --- libcpp/internal.h +++ 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 --- libcpp/macro.c +++ 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 @@ -2460,9 +2477,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; --- gcc/testsuite/gcc.dg/cpp/builtin-macro-1.c +++ 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; +}