Glenn Morris schrieb am Mo., 12. Juni 2017 um 23:46 Uhr: > Philipp Stephani wrote: > > >> +#ifdef __has_attribute > >> +#if __has_attribute(__nonnull__) > >> # define EMACS_ATTRIBUTE_NONNULL(...) > >> __attribute__((__nonnull__(__VA_ARGS__))) > >> -#else > >> +#endif > >> +#endif > >> +#ifndef EMACS_ATTRIBUTE_NONNULL > >> # define EMACS_ATTRIBUTE_NONNULL(...) > >> #endif > > Applied as 69899d4. > Thanks! > > > Probably yes, thanks. (I don't know why the && expression doesn't work.) > > I could not find a good reference, but see eg > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36453#c3 > > I've looked it up in the (C++) standard, and the explanation makes sense. What happens is that the preprocessor first replaces the 'define' forms and expands macros, then replaces all leftover identifiers (including C keywords) with 0. So #if defined __has_attribute && __has_attribute ((__nonnull__)) first gets translated to #if 0 && 0 ((0)) which is then evaluated, but it's a syntax error, which fails even if the LHS of && is false.