From aa50850225d70521ace3948a8e5858425a918f6a Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Sun, 19 Apr 2009 18:10:56 +0100 Subject: [PATCH] re PR preprocessor/20078 (Gcc doesn't complain about non-benign macro definitions) libcpp: PR preprocessor/20078 * include/cpp-id-data.h (struct cpp_macro): Add extra_tokens field. * include/cpplib.h (SP_DIGRAPH, SP_PREV_WHITE): Define. (struct cpp_token): Change flags to unsigned short. * lex.c (_cpp_lex_direct): Initialize arg_no for CPP_PASTE tokens. (_cpp_equiv_tokens): Check arg_no for CPP_PASTE tokens. (cpp_token_val_index): Return CPP_TOKEN_FLD_ARG_NO for CPP_PASTE tokens. * macro.c (macro_real_token_count): New. (enter_macro_context, replace_args): Use macro_real_token_count. (create_iso_definition): Record whitespace surrounding and digraph spelling of # and ## tokens using SP_PREV_WHITE and SP_DIGRAPH. Set extra_tokens and save CPP_PASTE tokens with arg_no set for multiple consecutive ## tokens. (_cpp_create_definition): Initialize extra_tokens. (cpp_macro_definition): Use macro_real_token_count. gcc/testsuite: * gcc.dg/cpp/paste16.c, gcc.dg/cpp/redef4.c: New tests. From-SVN: r146352 --- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/gcc.dg/cpp/paste16.c | 6 + gcc/testsuite/gcc.dg/cpp/redef4.c | 499 +++++++++++++++++++++++++++++ libcpp/ChangeLog | 20 ++ libcpp/include/cpp-id-data.h | 5 + libcpp/include/cpplib.h | 6 +- libcpp/lex.c | 13 +- libcpp/macro.c | 73 ++++- 8 files changed, 615 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/cpp/paste16.c create mode 100644 gcc/testsuite/gcc.dg/cpp/redef4.c diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 54549213c1bb..bb2fab66e655 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-04-19 Joseph Myers + + PR preprocessor/20078 + * gcc.dg/cpp/paste16.c, gcc.dg/cpp/redef4.c: New tests. + 2009-04-19 Eric Botcazou * lib/gnat.exp (local_find_gnatmake): Pass --LINK to gnatlink. diff --git a/gcc/testsuite/gcc.dg/cpp/paste16.c b/gcc/testsuite/gcc.dg/cpp/paste16.c new file mode 100644 index 000000000000..11aca2b60d4a --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/paste16.c @@ -0,0 +1,6 @@ +/* Test multiple consecutive ## tokens. */ +/* { dg-do compile } */ +/* { dg-options "" } */ +#define cat(x,y) x##########y +int abcd; +int *p = &cat(ab,cd); diff --git a/gcc/testsuite/gcc.dg/cpp/redef4.c b/gcc/testsuite/gcc.dg/cpp/redef4.c new file mode 100644 index 000000000000..b34635b2e423 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/redef4.c @@ -0,0 +1,499 @@ +/* Test redefinitions differing only in the spelling of paste and + stringify tokens, whitespace around them, or the number of + consecutive paste tokens. */ +/* { dg-do preprocess } */ +/* { dg-options "" } */ + +#define str(x) #x /* { dg-message "previous definition" } */ +#define str(x) %: x /* { dg-warning "redefined" } */ +#undef str +#define str(x) #x /* { dg-message "previous definition" } */ +#define str(x) # x /* { dg-warning "redefined" } */ +#undef str +#define str(x) #x /* { dg-message "previous definition" } */ +#define str(x) %: x /* { dg-warning "redefined" } */ +#undef str +#define str(x) %:x /* { dg-message "previous definition" } */ +#define str(x) #x /* { dg-warning "redefined" } */ +#undef str +#define str(x) %:x /* { dg-message "previous definition" } */ +#define str(x) %: x /* { dg-warning "redefined" } */ +#undef str +#define str(x) %:x /* { dg-message "previous definition" } */ +#define str(x) # x /* { dg-warning "redefined" } */ +#undef str +#define str(x) %:x /* { dg-message "previous definition" } */ +#define str(x) %: x /* { dg-warning "redefined" } */ +#undef str +#define str(x) # x /* { dg-message "previous definition" } */ +#define str(x) #x /* { dg-warning "redefined" } */ +#undef str +#define str(x) # x /* { dg-message "previous definition" } */ +#define str(x) %: x /* { dg-warning "redefined" } */ +#undef str +#define str(x) # x /* { dg-message "previous definition" } */ +#define str(x) %: x /* { dg-warning "redefined" } */ +#undef str +#define str(x) %: x /* { dg-message "previous definition" } */ +#define str(x) #x /* { dg-warning "redefined" } */ +#undef str +#define str(x) %: x /* { dg-message "previous definition" } */ +#define str(x) # x /* { dg-warning "redefined" } */ +#undef str + +#define str(x) #x +#define str(x) #x +#undef str +#define str(x) # x +#define str(x) # x +#undef str +#define str(x) %: x +#define str(x) %: x +#undef str +#define str(x) %: x +#define str(x) %: x +#undef str + +#define astr(x) a#x /* { dg-message "previous definition" } */ +#define astr(x) a%: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a#x /* { dg-message "previous definition" } */ +#define astr(x) a# x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a#x /* { dg-message "previous definition" } */ +#define astr(x) a%: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a#x /* { dg-message "previous definition" } */ +#define astr(x) a #x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a#x /* { dg-message "previous definition" } */ +#define astr(x) a %:x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a#x /* { dg-message "previous definition" } */ +#define astr(x) a # x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a#x /* { dg-message "previous definition" } */ +#define astr(x) a %: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a%:x /* { dg-message "previous definition" } */ +#define astr(x) a#x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a%:x /* { dg-message "previous definition" } */ +#define astr(x) a%: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a%:x /* { dg-message "previous definition" } */ +#define astr(x) a# x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a%:x /* { dg-message "previous definition" } */ +#define astr(x) a%: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a%:x /* { dg-message "previous definition" } */ +#define astr(x) a #x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a%:x /* { dg-message "previous definition" } */ +#define astr(x) a %:x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a%:x /* { dg-message "previous definition" } */ +#define astr(x) a # x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a%:x /* { dg-message "previous definition" } */ +#define astr(x) a %: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a# x /* { dg-message "previous definition" } */ +#define astr(x) a#x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a# x /* { dg-message "previous definition" } */ +#define astr(x) a%: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a# x /* { dg-message "previous definition" } */ +#define astr(x) a%: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a# x /* { dg-message "previous definition" } */ +#define astr(x) a #x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a# x /* { dg-message "previous definition" } */ +#define astr(x) a %:x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a# x /* { dg-message "previous definition" } */ +#define astr(x) a # x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a# x /* { dg-message "previous definition" } */ +#define astr(x) a %: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a%: x /* { dg-message "previous definition" } */ +#define astr(x) a#x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a%: x /* { dg-message "previous definition" } */ +#define astr(x) a# x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a%: x /* { dg-message "previous definition" } */ +#define astr(x) a #x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a%: x /* { dg-message "previous definition" } */ +#define astr(x) a %:x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a%: x /* { dg-message "previous definition" } */ +#define astr(x) a # x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a%: x /* { dg-message "previous definition" } */ +#define astr(x) a %: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a #x /* { dg-message "previous definition" } */ +#define astr(x) a#x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a #x /* { dg-message "previous definition" } */ +#define astr(x) a%: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a #x /* { dg-message "previous definition" } */ +#define astr(x) a# x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a #x /* { dg-message "previous definition" } */ +#define astr(x) a%: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a #x /* { dg-message "previous definition" } */ +#define astr(x) a %:x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a #x /* { dg-message "previous definition" } */ +#define astr(x) a # x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a #x /* { dg-message "previous definition" } */ +#define astr(x) a %: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a %:x /* { dg-message "previous definition" } */ +#define astr(x) a#x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a %:x /* { dg-message "previous definition" } */ +#define astr(x) a%: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a %:x /* { dg-message "previous definition" } */ +#define astr(x) a# x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a %:x /* { dg-message "previous definition" } */ +#define astr(x) a%: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a %:x /* { dg-message "previous definition" } */ +#define astr(x) a #x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a %:x /* { dg-message "previous definition" } */ +#define astr(x) a # x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a %:x /* { dg-message "previous definition" } */ +#define astr(x) a %: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a # x /* { dg-message "previous definition" } */ +#define astr(x) a#x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a # x /* { dg-message "previous definition" } */ +#define astr(x) a%: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a # x /* { dg-message "previous definition" } */ +#define astr(x) a# x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a # x /* { dg-message "previous definition" } */ +#define astr(x) a%: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a # x /* { dg-message "previous definition" } */ +#define astr(x) a #x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a # x /* { dg-message "previous definition" } */ +#define astr(x) a %:x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a # x /* { dg-message "previous definition" } */ +#define astr(x) a %: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a %: x /* { dg-message "previous definition" } */ +#define astr(x) a#x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a %: x /* { dg-message "previous definition" } */ +#define astr(x) a%: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a %: x /* { dg-message "previous definition" } */ +#define astr(x) a# x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a %: x /* { dg-message "previous definition" } */ +#define astr(x) a%: x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a %: x /* { dg-message "previous definition" } */ +#define astr(x) a #x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a %: x /* { dg-message "previous definition" } */ +#define astr(x) a %:x /* { dg-warning "redefined" } */ +#undef astr +#define astr(x) a %: x /* { dg-message "previous definition" } */ +#define astr(x) a # x /* { dg-warning "redefined" } */ +#undef astr + +#define astr(x) a#x +#define astr(x) a#x +#undef astr +#define astr(x) a# x +#define astr(x) a# x +#undef astr +#define astr(x) a%: x +#define astr(x) a%: x +#undef astr +#define astr(x) a%: x +#define astr(x) a%: x +#undef astr +#define astr(x) a #x +#define astr(x) a #x +#undef astr +#define astr(x) a %:x +#define astr(x) a %:x +#undef astr +#define astr(x) a # x +#define astr(x) a # x +#undef astr +#define astr(x) a %: x +#define astr(x) a %: x +#undef astr + +#define cat(x,y) x##y /* { dg-message "previous definition" } */ +#define cat(x,y) x%:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x##y /* { dg-message "previous definition" } */ +#define cat(x,y) x## y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x##y /* { dg-message "previous definition" } */ +#define cat(x,y) x%:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x##y /* { dg-message "previous definition" } */ +#define cat(x,y) x ##y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x##y /* { dg-message "previous definition" } */ +#define cat(x,y) x %:%:y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x##y /* { dg-message "previous definition" } */ +#define cat(x,y) x ## y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x##y /* { dg-message "previous definition" } */ +#define cat(x,y) x %:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x%:%:y /* { dg-message "previous definition" } */ +#define cat(x,y) x##y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x%:%:y /* { dg-message "previous definition" } */ +#define cat(x,y) x%:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x%:%:y /* { dg-message "previous definition" } */ +#define cat(x,y) x## y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x%:%:y /* { dg-message "previous definition" } */ +#define cat(x,y) x%:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x%:%:y /* { dg-message "previous definition" } */ +#define cat(x,y) x ##y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x%:%:y /* { dg-message "previous definition" } */ +#define cat(x,y) x %:%:y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x%:%:y /* { dg-message "previous definition" } */ +#define cat(x,y) x ## y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x%:%:y /* { dg-message "previous definition" } */ +#define cat(x,y) x %:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x## y /* { dg-message "previous definition" } */ +#define cat(x,y) x##y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x## y /* { dg-message "previous definition" } */ +#define cat(x,y) x%:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x## y /* { dg-message "previous definition" } */ +#define cat(x,y) x%:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x## y /* { dg-message "previous definition" } */ +#define cat(x,y) x ##y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x## y /* { dg-message "previous definition" } */ +#define cat(x,y) x %:%:y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x## y /* { dg-message "previous definition" } */ +#define cat(x,y) x ## y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x## y /* { dg-message "previous definition" } */ +#define cat(x,y) x %:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x%:%: y /* { dg-message "previous definition" } */ +#define cat(x,y) x##y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x%:%: y /* { dg-message "previous definition" } */ +#define cat(x,y) x## y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x%:%: y /* { dg-message "previous definition" } */ +#define cat(x,y) x ##y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x%:%: y /* { dg-message "previous definition" } */ +#define cat(x,y) x %:%:y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x%:%: y /* { dg-message "previous definition" } */ +#define cat(x,y) x ## y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x%:%: y /* { dg-message "previous definition" } */ +#define cat(x,y) x %:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x ##y /* { dg-message "previous definition" } */ +#define cat(x,y) x##y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x ##y /* { dg-message "previous definition" } */ +#define cat(x,y) x%:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x ##y /* { dg-message "previous definition" } */ +#define cat(x,y) x## y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x ##y /* { dg-message "previous definition" } */ +#define cat(x,y) x%:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x ##y /* { dg-message "previous definition" } */ +#define cat(x,y) x %:%:y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x ##y /* { dg-message "previous definition" } */ +#define cat(x,y) x ## y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x ##y /* { dg-message "previous definition" } */ +#define cat(x,y) x %:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x %:%:y /* { dg-message "previous definition" } */ +#define cat(x,y) x##y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x %:%:y /* { dg-message "previous definition" } */ +#define cat(x,y) x%:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x %:%:y /* { dg-message "previous definition" } */ +#define cat(x,y) x## y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x %:%:y /* { dg-message "previous definition" } */ +#define cat(x,y) x%:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x %:%:y /* { dg-message "previous definition" } */ +#define cat(x,y) x ##y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x %:%:y /* { dg-message "previous definition" } */ +#define cat(x,y) x ## y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x %:%:y /* { dg-message "previous definition" } */ +#define cat(x,y) x %:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x ## y /* { dg-message "previous definition" } */ +#define cat(x,y) x##y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x ## y /* { dg-message "previous definition" } */ +#define cat(x,y) x%:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x ## y /* { dg-message "previous definition" } */ +#define cat(x,y) x## y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x ## y /* { dg-message "previous definition" } */ +#define cat(x,y) x%:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x ## y /* { dg-message "previous definition" } */ +#define cat(x,y) x ##y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x ## y /* { dg-message "previous definition" } */ +#define cat(x,y) x %:%:y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x ## y /* { dg-message "previous definition" } */ +#define cat(x,y) x %:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x %:%: y /* { dg-message "previous definition" } */ +#define cat(x,y) x##y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x %:%: y /* { dg-message "previous definition" } */ +#define cat(x,y) x%:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x %:%: y /* { dg-message "previous definition" } */ +#define cat(x,y) x## y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x %:%: y /* { dg-message "previous definition" } */ +#define cat(x,y) x%:%: y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x %:%: y /* { dg-message "previous definition" } */ +#define cat(x,y) x ##y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x %:%: y /* { dg-message "previous definition" } */ +#define cat(x,y) x %:%:y /* { dg-warning "redefined" } */ +#undef cat +#define cat(x,y) x %:%: y /* { dg-message "previous definition" } */ +#define cat(x,y) x ## y /* { dg-warning "redefined" } */ +#undef cat + +#define cat(x,y) x##y +#define cat(x,y) x##y +#undef cat +#define cat(x,y) x## y +#define cat(x,y) x## y +#undef cat +#define cat(x,y) x%:%: y +#define cat(x,y) x%:%: y +#undef cat +#define cat(x,y) x%:%: y +#define cat(x,y) x%:%: y +#undef cat +#define cat(x,y) x ##y +#define cat(x,y) x ##y +#undef cat +#define cat(x,y) x %:%:y +#define cat(x,y) x %:%:y +#undef cat +#define cat(x,y) x ## y +#define cat(x,y) x ## y +#undef cat +#define cat(x,y) x %:%: y +#define cat(x,y) x %:%: y +#undef cat + +#define cat3(x,y,z) x##y##z /* { dg-message "previous definition" } */ +#define cat3(x,y,z) x##y####z /* { dg-warning "redefined" } */ +#undef cat3 + +#define cat3(x,y,z) x##y####z /* { dg-message "previous definition" } */ +#define cat3(x,y,z) x####y##z /* { dg-warning "redefined" } */ +#undef cat3 + +#define cat3(x,y,z) x##y####z /* { dg-message "previous definition" } */ +#define cat3(x,y,z) x##y## ##z /* { dg-warning "redefined" } */ +#undef cat3 + +#define cat3(x,y,z) x##y####z /* { dg-message "previous definition" } */ +#define cat3(x,y,z) x##y##%:%:z /* { dg-warning "redefined" } */ +#undef cat3 + +#define cat3(x,y,z) x##y######## ####z /* { dg-message "previous definition" } */ +#define cat3(x,y,z) x##y############z /* { dg-warning "redefined" } */ +#undef cat3 + +#define cat3(x,y,z) x##y############z /* { dg-message "previous definition" } */ +#define cat3(x,y,z) x##y########%:%:##z /* { dg-warning "redefined" } */ +#undef cat3 + +#define cat3(x,y,z) x##y##z +#define cat3(x,y,z) x##y##z +#undef cat3 + +#define cat3(x,y,z) x##y####z +#define cat3(x,y,z) x##y####z +#undef cat3 + +#define cat3(x,y,z) x####y##z +#define cat3(x,y,z) x####y##z +#undef cat3 + +#define cat3(x,y,z) x##y## ##z +#define cat3(x,y,z) x##y## ##z +#undef cat3 + +#define cat3(x,y,z) x##y##%:%:z +#define cat3(x,y,z) x##y##%:%:z +#undef cat3 + +#define cat3(x,y,z) x##y######## ####z +#define cat3(x,y,z) x##y######## ####z +#undef cat3 + +#define cat3(x,y,z) x##y############z +#define cat3(x,y,z) x##y############z +#undef cat3 + +#define cat3(x,y,z) x##y########%:%:##z +#define cat3(x,y,z) x##y########%:%:##z +#undef cat3 diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index c4316caa3345..74979a21ee59 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,23 @@ +2009-04-19 Joseph Myers + + PR preprocessor/20078 + * include/cpp-id-data.h (struct cpp_macro): Add extra_tokens + field. + * include/cpplib.h (SP_DIGRAPH, SP_PREV_WHITE): Define. + (struct cpp_token): Change flags to unsigned short. + * lex.c (_cpp_lex_direct): Initialize arg_no for CPP_PASTE tokens. + (_cpp_equiv_tokens): Check arg_no for CPP_PASTE tokens. + (cpp_token_val_index): Return CPP_TOKEN_FLD_ARG_NO for CPP_PASTE + tokens. + * macro.c (macro_real_token_count): New. + (enter_macro_context, replace_args): Use macro_real_token_count. + (create_iso_definition): Record whitespace surrounding and digraph + spelling of # and ## tokens using SP_PREV_WHITE and SP_DIGRAPH. + Set extra_tokens and save CPP_PASTE tokens with arg_no set for + multiple consecutive ## tokens. + (_cpp_create_definition): Initialize extra_tokens. + (cpp_macro_definition): Use macro_real_token_count. + 2009-04-18 Joseph Myers * directives.c (parse_include): Pass true to check_eol. diff --git a/libcpp/include/cpp-id-data.h b/libcpp/include/cpp-id-data.h index afe4edad99e1..029d424d5119 100644 --- a/libcpp/include/cpp-id-data.h +++ b/libcpp/include/cpp-id-data.h @@ -75,4 +75,9 @@ struct cpp_macro GTY(()) /* Indicate which field of 'exp' is in use. */ unsigned int traditional : 1; + + /* Indicate whether the tokens include extra CPP_PASTE tokens at the + end to track invalid redefinitions with consecutive CPP_PASTE + tokens. */ + unsigned int extra_tokens : 1; }; diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index 434308b64da3..3aeb035f48f4 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -178,6 +178,10 @@ struct cpp_string GTY(()) #define BOL (1 << 6) /* Token at beginning of line. */ #define PURE_ZERO (1 << 7) /* Single 0 digit, used by the C++ frontend, set in c-lex.c. */ +#define SP_DIGRAPH (1 << 8) /* # or ## token was a digraph. */ +#define SP_PREV_WHITE (1 << 9) /* If whitespace before a ## + operator, or before this token + after a # operator. */ /* Specify which field, if any, of the cpp_token union is used. */ @@ -196,7 +200,7 @@ struct cpp_token GTY(()) { source_location src_loc; /* Location of first char of token. */ ENUM_BITFIELD(cpp_ttype) type : CHAR_BIT; /* token type */ - unsigned char flags; /* flags - see above */ + unsigned short flags; /* flags - see above */ union cpp_token_u { diff --git a/libcpp/lex.c b/libcpp/lex.c index 0a3a6bc3a921..63e291c64c0e 100644 --- a/libcpp/lex.c +++ b/libcpp/lex.c @@ -1244,7 +1244,7 @@ _cpp_lex_direct (cpp_reader *pfile) result->flags |= DIGRAPH; result->type = CPP_HASH; if (*buffer->cur == '%' && buffer->cur[1] == ':') - buffer->cur += 2, result->type = CPP_PASTE; + buffer->cur += 2, result->type = CPP_PASTE, result->val.arg_no = 0; } else if (*buffer->cur == '>') { @@ -1325,7 +1325,7 @@ _cpp_lex_direct (cpp_reader *pfile) case '=': IF_NEXT_IS ('=', CPP_EQ_EQ, CPP_EQ); break; case '!': IF_NEXT_IS ('=', CPP_NOT_EQ, CPP_NOT); break; case '^': IF_NEXT_IS ('=', CPP_XOR_EQ, CPP_XOR); break; - case '#': IF_NEXT_IS ('#', CPP_PASTE, CPP_HASH); break; + case '#': IF_NEXT_IS ('#', CPP_PASTE, CPP_HASH); result->val.arg_no = 0; break; case '?': result->type = CPP_QUERY; break; case '~': result->type = CPP_COMPL; break; @@ -1572,7 +1572,9 @@ _cpp_equiv_tokens (const cpp_token *a, const cpp_token *b) { default: /* Keep compiler happy. */ case SPELL_OPERATOR: - return 1; + /* arg_no is used to track where multiple consecutive ## + tokens were originally located. */ + return (a->type != CPP_PASTE || a->val.arg_no == b->val.arg_no); case SPELL_NONE: return (a->type != CPP_MACRO_ARG || a->val.arg_no == b->val.arg_no); case SPELL_IDENT: @@ -1886,6 +1888,11 @@ cpp_token_val_index (cpp_token *tok) return CPP_TOKEN_FLD_NODE; case SPELL_LITERAL: return CPP_TOKEN_FLD_STR; + case SPELL_OPERATOR: + if (tok->type == CPP_PASTE) + return CPP_TOKEN_FLD_ARG_NO; + else + return CPP_TOKEN_FLD_NONE; case SPELL_NONE: if (tok->type == CPP_MACRO_ARG) return CPP_TOKEN_FLD_ARG_NO; diff --git a/libcpp/macro.c b/libcpp/macro.c index 75c1c55e0225..36853971780a 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -802,6 +802,19 @@ funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node, return NULL; } +/* Return the real number of tokens in the expansion of MACRO. */ +static inline unsigned int +macro_real_token_count (const cpp_macro *macro) +{ + unsigned int i; + if (__builtin_expect (!macro->extra_tokens, true)) + return macro->count; + for (i = 0; i < macro->count; i++) + if (macro->exp.tokens[i].type == CPP_PASTE) + return i; + abort (); +} + /* 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. @@ -874,7 +887,8 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node, macro->used = 1; if (macro->paramc == 0) - _cpp_push_token_context (pfile, node, macro->exp.tokens, macro->count); + _cpp_push_token_context (pfile, node, macro->exp.tokens, + macro_real_token_count (macro)); if (pragma_buff) { @@ -914,13 +928,15 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, macro_arg const cpp_token **dest, **first; macro_arg *arg; _cpp_buff *buff; + unsigned int count; /* First, fully macro-expand arguments, calculating the number of tokens in the final expansion as we go. The ordering of the if statements below is subtle; we must handle stringification before pasting. */ - total = macro->count; - limit = macro->exp.tokens + macro->count; + count = macro_real_token_count (macro); + total = count; + limit = macro->exp.tokens + count; for (src = macro->exp.tokens; src < limit; src++) if (src->type == CPP_MACRO_ARG) @@ -1630,6 +1646,7 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) bool following_paste_op = false; const char *paste_op_error_msg = N_("'##' cannot appear at either end of a macro expansion"); + unsigned int num_extra_tokens = 0; /* Get the first token of the expansion (or the '(' of a function-like macro). */ @@ -1707,6 +1724,10 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) { if (token->type == CPP_MACRO_ARG) { + if (token->flags & PREV_WHITE) + token->flags |= SP_PREV_WHITE; + if (token[-1].flags & DIGRAPH) + token->flags |= SP_DIGRAPH; token->flags &= ~PREV_WHITE; token->flags |= STRINGIFY_ARG; token->flags |= token[-1].flags & PREV_WHITE; @@ -1746,8 +1767,21 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) return false; } - --macro->count; - token[-1].flags |= PASTE_LEFT; + if (token[-1].flags & PASTE_LEFT) + { + macro->extra_tokens = 1; + num_extra_tokens++; + token->val.arg_no = macro->count - 1; + } + else + { + --macro->count; + token[-1].flags |= PASTE_LEFT; + if (token->flags & DIGRAPH) + token[-1].flags |= SP_DIGRAPH; + if (token->flags & PREV_WHITE) + token[-1].flags |= SP_PREV_WHITE; + } } following_paste_op = (token->type == CPP_PASTE); @@ -1770,7 +1804,27 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) cpp_token *tokns = (cpp_token *) pfile->hash_table->alloc_subobject (sizeof (cpp_token) * macro->count); - memcpy (tokns, macro->exp.tokens, sizeof (cpp_token) * macro->count); + if (num_extra_tokens) + { + /* Place second and subsequent ## or %:%: tokens in + sequences of consecutive such tokens at the end of the + list to preserve information about where they appear, how + they are spelt and whether they are preceded by + whitespace without otherwise interfering with macro + expansion. */ + cpp_token *normal_dest = tokns; + cpp_token *extra_dest = tokns + macro->count - num_extra_tokens; + unsigned int i; + for (i = 0; i < macro->count; i++) + { + if (macro->exp.tokens[i].type == CPP_PASTE) + *extra_dest++ = macro->exp.tokens[i]; + else + *normal_dest++ = macro->exp.tokens[i]; + } + } + else + memcpy (tokns, macro->exp.tokens, sizeof (cpp_token) * macro->count); macro->exp.tokens = tokns; } else @@ -1799,6 +1853,7 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode *node) macro->used = !CPP_OPTION (pfile, warn_unused_macros); macro->count = 0; macro->fun_like = 0; + macro->extra_tokens = 0; /* To suppress some diagnostics. */ macro->syshdr = pfile->buffer && pfile->buffer->sysp != 0; @@ -1946,7 +2001,8 @@ cpp_macro_definition (cpp_reader *pfile, const cpp_hashnode *node) len += _cpp_replacement_text_len (macro); else { - for (i = 0; i < macro->count; i++) + unsigned int count = macro_real_token_count (macro); + for (i = 0; i < count; i++) { cpp_token *token = ¯o->exp.tokens[i]; @@ -2010,7 +2066,8 @@ cpp_macro_definition (cpp_reader *pfile, const cpp_hashnode *node) else if (macro->count) /* Expansion tokens. */ { - for (i = 0; i < macro->count; i++) + unsigned int count = macro_real_token_count (macro); + for (i = 0; i < count; i++) { cpp_token *token = ¯o->exp.tokens[i]; -- 2.39.2