aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2009-04-19 18:10:56 +0100
committerJoseph Myers <jsm28@gcc.gnu.org>2009-04-19 18:10:56 +0100
commitaa50850225d70521ace3948a8e5858425a918f6a (patch)
tree311d607f4a7b5f177b00f2193802a219b80ccc5e
parentb6fa5b01018ac42682f8d69fff9e48f50b87c910 (diff)
downloadgcc-aa50850225d70521ace3948a8e5858425a918f6a.zip
gcc-aa50850225d70521ace3948a8e5858425a918f6a.tar.gz
gcc-aa50850225d70521ace3948a8e5858425a918f6a.tar.bz2
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
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/cpp/paste16.c6
-rw-r--r--gcc/testsuite/gcc.dg/cpp/redef4.c499
-rw-r--r--libcpp/ChangeLog20
-rw-r--r--libcpp/include/cpp-id-data.h5
-rw-r--r--libcpp/include/cpplib.h6
-rw-r--r--libcpp/lex.c13
-rw-r--r--libcpp/macro.c73
8 files changed, 615 insertions, 12 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5454921..bb2fab6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-04-19 Joseph Myers <joseph@codesourcery.com>
+
+ PR preprocessor/20078
+ * gcc.dg/cpp/paste16.c, gcc.dg/cpp/redef4.c: New tests.
+
2009-04-19 Eric Botcazou <ebotcazou@adacore.com>
* 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 0000000..11aca2b
--- /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 0000000..b34635b
--- /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 c4316ca..74979a2 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,23 @@
+2009-04-19 Joseph Myers <joseph@codesourcery.com>
+
+ 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 <joseph@codesourcery.com>
* 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 afe4eda..029d424 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 434308b..3aeb035 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 0a3a6bc..63e291c 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 75c1c55..3685397 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 = &macro->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 = &macro->exp.tokens[i];