Hi! The following testcase is diagnosed as errorneous, because the preprocessor mishandles
#define c(x) x vector c; and #define int(x) x vector int n; The thing is if a function-like macro is not followed by (, then it is kept as is, but the builtin conditional macro handling expects it always expands as something and calls cpp_get_token on it. For non-function-like macros or function-like macros followed by ( that is not a problem, that cpp_get_token call just eats the macro token and pushes instead the replacement tokens, but for function-like macro not followed by ( it results in the token being dropped on the floor. So, in the above mentioned cases we preprocess it as vector ; and vector n; and when compiling, error on the first one, and (due to previous typedef int vector;) handle it at int n; rather than __attribute__((__vector)) int n; Fixed by peeking at the next token after the macro token (or more, if there are CPP_PADDING tokens) and if it is not followed by CPP_OPEN_PAREN, not calling cpp_get_token. Unfortunately, cpp_macro structure is opaque outside of libcpp, so I had to add a helper function into libcpp. Bootstrapped/regtested on powerpc64{,le}-linux, ok for trunk? 2016-03-18 Jakub Jelinek <ja...@redhat.com> PR target/70296 * include/cpplib.h (cpp_fun_like_macro_p): New prototype. * macro.c (cpp_fun_like_macro_p): New function. * config/rs6000/rs6000-c.c (rs6000_macro_to_expand): If IDENT is function-like macro, peek following token(s) if it is followed by CPP_OPEN_PAREN token with optional padding in between, and if not, don't treat it like a macro. * gcc.target/powerpc/altivec-36.c: New test. --- libcpp/include/cpplib.h.jj 2016-01-04 15:14:09.000000000 +0100 +++ libcpp/include/cpplib.h 2016-03-18 15:03:52.321198042 +0100 @@ -813,6 +813,7 @@ extern int cpp_avoid_paste (cpp_reader * extern const cpp_token *cpp_get_token (cpp_reader *); extern const cpp_token *cpp_get_token_with_location (cpp_reader *, source_location *); +extern bool cpp_fun_like_macro_p (cpp_hashnode *); extern const unsigned char *cpp_macro_definition (cpp_reader *, cpp_hashnode *); extern void _cpp_backup_tokens (cpp_reader *, unsigned int); --- libcpp/macro.c.jj 2016-01-27 20:30:20.000000000 +0100 +++ libcpp/macro.c 2016-03-18 15:06:03.245428598 +0100 @@ -3301,6 +3301,15 @@ check_trad_stringification (cpp_reader * } } +/* Returns true of NODE is a function-like macro. */ +bool +cpp_fun_like_macro_p (cpp_hashnode *node) +{ + return (node->type == NT_MACRO + && (node->flags & (NODE_BUILTIN | NODE_MACRO_ARG)) == 0 + && node->value.macro->fun_like); +} + /* Returns the name, arguments and expansion of a macro, in a format suitable to be read back in again, and therefore also for DWARF 2 debugging info. e.g. "PASTE(X, Y) X ## Y", or "MACNAME EXPANSION". --- gcc/config/rs6000/rs6000-c.c.jj 2016-01-04 14:55:57.000000000 +0100 +++ gcc/config/rs6000/rs6000-c.c 2016-03-18 15:05:37.695773902 +0100 @@ -216,7 +216,21 @@ rs6000_macro_to_expand (cpp_reader *pfil else if (ident && (ident != C_CPP_HASHNODE (__vector_keyword))) { enum rid rid_code = (enum rid)(ident->rid_code); - if (ident->type == NT_MACRO) + enum node_type itype = ident->type; + /* If there is a function-like macro, check if it is going to be + invoked with or without arguments. Without following ( treat + it like non-macro, otherwise the following cpp_get_token eats + what should be preserved. */ + if (itype == NT_MACRO && cpp_fun_like_macro_p (ident)) + { + int idx2 = idx; + do + tok = cpp_peek_token (pfile, idx2++); + while (tok->type == CPP_PADDING); + if (tok->type != CPP_OPEN_PAREN) + itype = NT_VOID; + } + if (itype == NT_MACRO) { do (void) cpp_get_token (pfile); --- gcc/testsuite/gcc.target/powerpc/altivec-36.c.jj 2016-03-18 15:24:19.065621943 +0100 +++ gcc/testsuite/gcc.target/powerpc/altivec-36.c 2016-03-18 15:30:23.000000000 +0100 @@ -0,0 +1,46 @@ +/* PR target/70296 */ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_altivec_ok } */ +/* { dg-options "-maltivec -std=gnu11" } */ + +#define c(x) x +#define f(x) +#define i int +#define k +typedef int vector; +typedef vector int V; +vector int a; +vector b; +vector c(int) d; +vector c(e); +vector c; +vector f(int) int g; +vector f(int) h; +vector i j; +vector k int l; +vector k m; +#define int(x) x +vector int n; +vector int(int) o; +vector int(r); +#undef int + +void +foo () +{ + V *p; + p = &a; + p = &d; + p = &g; + p = &j; + p = &l; + p = &n; + p = &o; + int *q; + q = &b; + q = &e; + q = &c; + q = &h; + q = &m; + q = &r; +} Jakub