Message ID | 1470837224-14510-1-git-send-email-pbonzini@redhat.com |
---|---|
State | New |
Headers | show |
On 10/08/2016 15:53, Paolo Bonzini wrote: > From: Paolo Bonzini <bonzini@gnu.org> > > clang recently added a new warning -Wexpansion-to-defined, which > warns when `defined' is used outside a #if expression (including the > case of a macro that is then used in a #if expression). > > While I disagree with their inclusion of the warning to -Wall, I think > it is a good addition overall. First, it is a logical extension of the > existing warning for breaking defined across a macro and its caller. > Second, it is good to make these warnings for `defined' available with > a command-line option other than -pedantic. > > This patch adds -Wexpansion-to-defined, and enables it automatically > for both -pedantic (as before) and -Wextra. It also changes the warning > from a warning to a pedwarn; this is mostly for documentation sake > since the EnabledBy machinery would turn -pedantic-errors into > -Werror=expansion-to-defined anyway. > > Bootstrapped and regression tested x86_64-pc-linux-gnu, ok? > > Paolo Ping? I would like to commit this now as "posted early enough during Stage 1 and not yet fully reviewed". Thanks, Paolo > libcpp: > 2016-08-09 Paolo Bonzini <bonzini@gnu.org> > > * include/cpplib.h (struct cpp_options): Add new member > warn_expansion_to_defined. > (CPP_W_EXPANSION_TO_DEFINED): New enum member. > * expr.c (parse_defined): Warn for all uses of "defined" > in macros, and tie warning to CPP_W_EXPANSION_TO_DEFINED. > Make it a pedwarning instead of a warning. > * system.h (HAVE_DESIGNATED_INITIALIZERS): Do not use > "defined" in macros. > > gcc: > 2016-08-09 Paolo Bonzini <bonzini@gnu.org> > > * system.h (HAVE_DESIGNATED_INITIALIZERS, > HAVE_DESIGNATED_UNION_INITIALIZERS): Do not use > "defined" in macros. > > gcc/c-family: > 2016-08-09 Paolo Bonzini <bonzini@gnu.org> > > * c.opt (Wexpansion-to-defined): New. > > gcc/doc: > 2016-08-09 Paolo Bonzini <bonzini@gnu.org> > > * cpp.texi (Defined): Mention -Wexpansion-to-defined. > * cppopts.texi (Invocation): Document -Wexpansion-to-defined. > * invoke.texi (Warning Options): Document -Wexpansion-to-defined. > > gcc/testsuite: > 2016-08-09 Paolo Bonzini <bonzini@gnu.org> > > * gcc.dg/cpp/defined.c: Mark newly introduced warnings and > adjust for warning->pedwarn change. > * gcc.dg/cpp/defined-Wexpansion-to-defined.c, > gcc.dg/cpp/defined-Wextra-Wno-expansion-to-defined.c, > gcc.dg/cpp/defined-Wextra.c, > gcc.dg/cpp/defined-Wno-expansion-to-defined.c: New testcases. > > Index: gcc/c-family/c.opt > =================================================================== > --- gcc/c-family/c.opt (revision 239276) > +++ gcc/c-family/c.opt (working copy) > @@ -506,6 +506,10 @@ > C ObjC C++ ObjC++ Var(warn_double_promotion) Warning > Warn about implicit conversions from \"float\" to \"double\". > > +Wexpansion-to-defined > +C ObjC C++ ObjC++ CPP(warn_expansion_to_defined) CppReason(CPP_W_EXPANSION_TO_DEFINED) Var(cpp_warn_expansion_to_defined) Init(0) Warning EnabledBy(Wextra || Wpedantic) > +Warn if \"defined\" is used outside #if. > + > Wimplicit-function-declaration > C ObjC Var(warn_implicit_function_declaration) Init(-1) Warning LangEnabledBy(C ObjC,Wimplicit) > Warn about implicit function declarations. > Index: gcc/doc/cpp.texi > =================================================================== > --- gcc/doc/cpp.texi (revision 239276) > +++ gcc/doc/cpp.texi (working copy) > @@ -3342,7 +3342,9 @@ > the C standard says the behavior is undefined. GNU cpp treats it as a > genuine @code{defined} operator and evaluates it normally. It will warn > wherever your code uses this feature if you use the command-line option > -@option{-pedantic}, since other compilers may handle it differently. > +@option{-Wpedantic}, since other compilers may handle it differently. The > +warning is also enabled by @option{-Wextra}, and can also be enabled > +individually with @option{-Wexpansion-to-defined}. > > @node Else > @subsection Else > Index: gcc/doc/cppopts.texi > =================================================================== > --- gcc/doc/cppopts.texi (revision 239276) > +++ gcc/doc/cppopts.texi (working copy) > @@ -120,6 +120,12 @@ > @samp{#if} directive, outside of @samp{defined}. Such identifiers are > replaced with zero. > > +@item -Wexpansion-to-defined > +@opindex Wexpansion-to-defined > +Warn whenever @samp{defined} is encountered in the expansion of a macro > +(including the case where the macro is expanded by an @samp{#if} directive). > +Such usage is not portable. > + > @item -Wunused-macros > @opindex Wunused-macros > Warn about macros defined in the main file that are unused. A macro > Index: gcc/doc/invoke.texi > =================================================================== > --- gcc/doc/invoke.texi (revision 239276) > +++ gcc/doc/invoke.texi (working copy) > @@ -4914,6 +4914,11 @@ > construct, known from C++, was introduced with ISO C99 and is by default > allowed in GCC@. It is not supported by ISO C90. @xref{Mixed Declarations}. > > +@item -Wexpansion-to-defined > +@opindex Wexpansion-to-defined > +Warn whenever @samp{defined} is encountered in the expansion of a macro. > +This warning is also enabled by @option{-Wpedantic} and @option{-Wextra}. > + > @item -Wundef > @opindex Wundef > @opindex Wno-undef > Index: gcc/system.h > =================================================================== > --- gcc/system.h (revision 239276) > +++ gcc/system.h (working copy) > @@ -577,16 +577,22 @@ > > /* 1 if we have C99 designated initializers. */ > #if !defined(HAVE_DESIGNATED_INITIALIZERS) > +#ifdef __cplusplus > +#define HAVE_DESIGNATED_INITIALIZERS 0 > +#else > #define HAVE_DESIGNATED_INITIALIZERS \ > - (((GCC_VERSION >= 2007) || (__STDC_VERSION__ >= 199901L)) \ > - && !defined(__cplusplus)) > + (((GCC_VERSION >= 2007) || (__STDC_VERSION__ >= 199901L)) > #endif > +#endif > > #if !defined(HAVE_DESIGNATED_UNION_INITIALIZERS) > +#ifdef __cplusplus > +#define HAVE_DESIGNATED_UNION_INITIALIZERS (GCC_VERSION >= 4007) > +#else > #define HAVE_DESIGNATED_UNION_INITIALIZERS \ > - (((GCC_VERSION >= 2007) || (__STDC_VERSION__ >= 199901L)) \ > - && (!defined(__cplusplus) || (GCC_VERSION >= 4007))) > + (((GCC_VERSION >= 2007) || (__STDC_VERSION__ >= 199901L)) > #endif > +#endif > > #if HAVE_SYS_STAT_H > # include <sys/stat.h> > Index: gcc/testsuite/gcc.dg/cpp/defined-Wno-expansion-to-defined.c > =================================================================== > --- gcc/testsuite/gcc.dg/cpp/defined-Wno-expansion-to-defined.c (revision 0) > +++ gcc/testsuite/gcc.dg/cpp/defined-Wno-expansion-to-defined.c (working copy) > @@ -0,0 +1,30 @@ > +/* Copyright (C) 2000 Free Software Foundation, Inc. */ > + > +/* { dg-do preprocess } */ > +/* { dg-options "-ansi -pedantic-errors -Wno-expansion-to-defined" } */ > + > +/* Use of defined in different contexts. */ > + > +/* Source: Neil Booth, 29 Oct 2000, Zack Weinberg 11 Dec 2000. */ > + > +#define Z > + > +#define bad0 defined Z > +#if !bad0 /* { dg-bogus "may not be portable" } */ > +#error Z is defined > +#endif > + > +#define bad1 defined > +#if !bad1 Z /* { dg-bogus "may not be portable" } */ > +#error Z is defined > +#endif > + > +#if !bad1 (Z) /* { dg-bogus "may not be portable" } */ > +#error Z is defined > +#endif > + > +#define bad2 defined (Z > +#if !bad2) /* { dg-bogus "may not be portable" } */ > +#error Z is defined > +#endif > + > Index: gcc/testsuite/gcc.dg/cpp/defined-Wexpansion-to-defined.c > =================================================================== > --- gcc/testsuite/gcc.dg/cpp/defined-Wexpansion-to-defined.c (revision 0) > +++ gcc/testsuite/gcc.dg/cpp/defined-Wexpansion-to-defined.c (working copy) > @@ -0,0 +1,30 @@ > +/* Copyright (C) 2000 Free Software Foundation, Inc. */ > + > +/* { dg-do preprocess } */ > +/* { dg-options "-Wexpansion-to-defined" } */ > + > +/* Use of defined in different contexts. */ > + > +/* Source: Neil Booth, 29 Oct 2000, Zack Weinberg 11 Dec 2000. */ > + > +#define Z > + > +#define bad0 defined Z > +#if !bad0 /* { dg-warning "may not be portable" } */ > +#error Z is defined > +#endif > + > +#define bad1 defined > +#if !bad1 Z /* { dg-warning "may not be portable" } */ > +#error Z is defined > +#endif > + > +#if !bad1 (Z) /* { dg-warning "may not be portable" } */ > +#error Z is defined > +#endif > + > +#define bad2 defined (Z > +#if !bad2) /* { dg-warning "may not be portable" } */ > +#error Z is defined > +#endif > + > Index: gcc/testsuite/gcc.dg/cpp/defined-Wextra-Wno-expansion-to-defined.c > =================================================================== > --- gcc/testsuite/gcc.dg/cpp/defined-Wextra-Wno-expansion-to-defined.c (revision 0) > +++ gcc/testsuite/gcc.dg/cpp/defined-Wextra-Wno-expansion-to-defined.c (working copy) > @@ -0,0 +1,30 @@ > +/* Copyright (C) 2000 Free Software Foundation, Inc. */ > + > +/* { dg-do preprocess } */ > +/* { dg-options "-Wextra -Wno-expansion-to-defined" } */ > + > +/* Use of defined in different contexts. */ > + > +/* Source: Neil Booth, 29 Oct 2000, Zack Weinberg 11 Dec 2000. */ > + > +#define Z > + > +#define bad0 defined Z > +#if !bad0 /* { dg-bogus "may not be portable" } */ > +#error Z is defined > +#endif > + > +#define bad1 defined > +#if !bad1 Z /* { dg-bogus "may not be portable" } */ > +#error Z is defined > +#endif > + > +#if !bad1 (Z) /* { dg-bogus "may not be portable" } */ > +#error Z is defined > +#endif > + > +#define bad2 defined (Z > +#if !bad2) /* { dg-bogus "may not be portable" } */ > +#error Z is defined > +#endif > + > Index: gcc/testsuite/gcc.dg/cpp/defined-Wextra.c > =================================================================== > --- gcc/testsuite/gcc.dg/cpp/defined-Wextra.c (revision 0) > +++ gcc/testsuite/gcc.dg/cpp/defined-Wextra.c (working copy) > @@ -0,0 +1,30 @@ > +/* Copyright (C) 2000 Free Software Foundation, Inc. */ > + > +/* { dg-do preprocess } */ > +/* { dg-options "-Wextra" } */ > + > +/* Use of defined in different contexts. */ > + > +/* Source: Neil Booth, 29 Oct 2000, Zack Weinberg 11 Dec 2000. */ > + > +#define Z > + > +#define bad0 defined Z > +#if !bad0 /* { dg-warning "may not be portable" } */ > +#error Z is defined > +#endif > + > +#define bad1 defined > +#if !bad1 Z /* { dg-warning "may not be portable" } */ > +#error Z is defined > +#endif > + > +#if !bad1 (Z) /* { dg-warning "may not be portable" } */ > +#error Z is defined > +#endif > + > +#define bad2 defined (Z > +#if !bad2) /* { dg-warning "may not be portable" } */ > +#error Z is defined > +#endif > + > Index: gcc/testsuite/gcc.dg/cpp/defined.c > =================================================================== > --- gcc/testsuite/gcc.dg/cpp/defined.c (revision 239276) > +++ gcc/testsuite/gcc.dg/cpp/defined.c (working copy) > @@ -21,7 +21,7 @@ > > /* The behavior of "defined" when it comes from a macro expansion is > now documented. */ > -#if is_Z_defined > +#if is_Z_defined /* { dg-error "may not be portable" } */ > #error Macro expanding into defined operator test 1 > #endif > > @@ -31,7 +31,7 @@ > #error Z is defined > #endif > > -#if !is_Z_defined > +#if !is_Z_defined /* { dg-error "may not be portable" } */ > #error Macro expanding into defined operator test 2 > #endif > > @@ -53,7 +53,7 @@ > > /* The behavior of "defined" when it comes from a macro expansion is > now documented. */ > -#if is_Z_defined > +#if is_Z_defined /* { dg-error "may not be portable" } */ > #error Macro expanding into defined operator test 1 > #endif > > @@ -63,23 +63,23 @@ > #error Z is defined > #endif > > -#if !is_Z_defined > +#if !is_Z_defined /* { dg-error "may not be portable" } */ > #error Macro expanding into defined operator test 2 > #endif > > /* Use of defined in different contexts. */ > > #define bad1 defined > -#if !bad1 Z /* { dg-warning "may not be portable" } */ > +#if !bad1 Z /* { dg-error "may not be portable" } */ > #error Z is defined > #endif > > -#if !bad1 (Z) /* { dg-warning "may not be portable" } */ > +#if !bad1 (Z) /* { dg-error "may not be portable" } */ > #error Z is defined > #endif > > #define bad2 defined (Z > -#if !bad2) /* { dg-warning "may not be portable" } */ > +#if !bad2) /* { dg-error "may not be portable" } */ > #error Z is defined > #endif > > Index: libcpp/expr.c > =================================================================== > --- libcpp/expr.c (revision 239276) > +++ libcpp/expr.c (working copy) > @@ -947,9 +947,11 @@ > > if (node) > { > - if (pfile->context != initial_context && CPP_PEDANTIC (pfile)) > - cpp_error (pfile, CPP_DL_WARNING, > - "this use of \"defined\" may not be portable"); > + if ((pfile->context != initial_context > + || initial_context != &pfile->base_context) > + && CPP_OPTION (pfile, warn_expansion_to_defined)) > + cpp_pedwarning (pfile, CPP_W_EXPANSION_TO_DEFINED, > + "this use of \"defined\" may not be portable"); > > _cpp_mark_macro_used (node); > if (!(node->flags & NODE_USED)) > Index: libcpp/include/cpplib.h > =================================================================== > --- libcpp/include/cpplib.h (revision 239276) > +++ libcpp/include/cpplib.h (working copy) > @@ -410,6 +410,10 @@ > /* Nonzero means warn if undefined identifiers are evaluated in an #if. */ > unsigned char warn_undef; > > + /* Nonzero means warn if "defined" is encountered in a place other than > + an #if. */ > + unsigned char warn_expansion_to_defined; > + > /* Nonzero means warn of unused macros from the main file. */ > unsigned char warn_unused_macros; > > @@ -1025,7 +1029,8 @@ > CPP_W_DATE_TIME, > CPP_W_PEDANTIC, > CPP_W_C90_C99_COMPAT, > - CPP_W_CXX11_COMPAT > + CPP_W_CXX11_COMPAT, > + CPP_W_EXPANSION_TO_DEFINED > }; > > /* Output a diagnostic of some kind. */ > Index: libcpp/system.h > =================================================================== > --- libcpp/system.h (revision 239276) > +++ libcpp/system.h (working copy) > @@ -375,10 +375,13 @@ > ??? C99 designated initializers are not supported by most C++ > compilers, including G++. -- gdr, 2005-05-18 */ > #if !defined(HAVE_DESIGNATED_INITIALIZERS) > +#ifdef __cplusplus > +#define HAVE_DESIGNATED_INITIALIZERS 0 > +#else > #define HAVE_DESIGNATED_INITIALIZERS \ > - (!defined(__cplusplus) \ > - && ((GCC_VERSION >= 2007) || (__STDC_VERSION__ >= 199901L))) > + ((GCC_VERSION >= 2007) || (__STDC_VERSION__ >= 199901L)) > #endif > +#endif > > #ifndef offsetof > #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *) 0)->MEMBER) >
It's not obvious to me whether this belongs in -Wextra. After all, this is a perfectly reasonable and useful GNU C feature, or at least some cases of it are (like "#define FOO (BAR || defined something)"). Is the argument that there are too many details of it that differ between implementations, as discussed in section 3.2 of <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4220.pdf>?
> It's not obvious to me whether this belongs in -Wextra. After all, this > is a perfectly reasonable and useful GNU C feature, or at least some cases > of it are (like "#define FOO (BAR || defined something)"). Is the > argument that there are too many details of it that differ between > implementations, as discussed in section 3.2 of > <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4220.pdf>? Yes, and in general it fits the group of "often annoying warnings, that people may nevertheless appreciate" that are already in -Wextra, for example -Wunused-parameter, -Wmissing-field-initializers or -Wshift-negative-value. Thanks, Paolo
On Tue, 22 Nov 2016, Paolo Bonzini wrote: > > It's not obvious to me whether this belongs in -Wextra. After all, this > > is a perfectly reasonable and useful GNU C feature, or at least some cases > > of it are (like "#define FOO (BAR || defined something)"). Is the > > argument that there are too many details of it that differ between > > implementations, as discussed in section 3.2 of > > <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4220.pdf>? > > Yes, and in general it fits the group of "often annoying warnings, that > people may nevertheless appreciate" that are already in -Wextra, for > example -Wunused-parameter, -Wmissing-field-initializers or > -Wshift-negative-value. Thanks. The patch is OK, but we'll need to see how disruptive it is and consider whether evidence from large-scale builds indicates moving it out of -Wextra.
Index: gcc/c-family/c.opt =================================================================== --- gcc/c-family/c.opt (revision 239276) +++ gcc/c-family/c.opt (working copy) @@ -506,6 +506,10 @@ C ObjC C++ ObjC++ Var(warn_double_promotion) Warning Warn about implicit conversions from \"float\" to \"double\". +Wexpansion-to-defined +C ObjC C++ ObjC++ CPP(warn_expansion_to_defined) CppReason(CPP_W_EXPANSION_TO_DEFINED) Var(cpp_warn_expansion_to_defined) Init(0) Warning EnabledBy(Wextra || Wpedantic) +Warn if \"defined\" is used outside #if. + Wimplicit-function-declaration C ObjC Var(warn_implicit_function_declaration) Init(-1) Warning LangEnabledBy(C ObjC,Wimplicit) Warn about implicit function declarations. Index: gcc/doc/cpp.texi =================================================================== --- gcc/doc/cpp.texi (revision 239276) +++ gcc/doc/cpp.texi (working copy) @@ -3342,7 +3342,9 @@ the C standard says the behavior is undefined. GNU cpp treats it as a genuine @code{defined} operator and evaluates it normally. It will warn wherever your code uses this feature if you use the command-line option -@option{-pedantic}, since other compilers may handle it differently. +@option{-Wpedantic}, since other compilers may handle it differently. The +warning is also enabled by @option{-Wextra}, and can also be enabled +individually with @option{-Wexpansion-to-defined}. @node Else @subsection Else Index: gcc/doc/cppopts.texi =================================================================== --- gcc/doc/cppopts.texi (revision 239276) +++ gcc/doc/cppopts.texi (working copy) @@ -120,6 +120,12 @@ @samp{#if} directive, outside of @samp{defined}. Such identifiers are replaced with zero. +@item -Wexpansion-to-defined +@opindex Wexpansion-to-defined +Warn whenever @samp{defined} is encountered in the expansion of a macro +(including the case where the macro is expanded by an @samp{#if} directive). +Such usage is not portable. + @item -Wunused-macros @opindex Wunused-macros Warn about macros defined in the main file that are unused. A macro Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 239276) +++ gcc/doc/invoke.texi (working copy) @@ -4914,6 +4914,11 @@ construct, known from C++, was introduced with ISO C99 and is by default allowed in GCC@. It is not supported by ISO C90. @xref{Mixed Declarations}. +@item -Wexpansion-to-defined +@opindex Wexpansion-to-defined +Warn whenever @samp{defined} is encountered in the expansion of a macro. +This warning is also enabled by @option{-Wpedantic} and @option{-Wextra}. + @item -Wundef @opindex Wundef @opindex Wno-undef Index: gcc/system.h =================================================================== --- gcc/system.h (revision 239276) +++ gcc/system.h (working copy) @@ -577,16 +577,22 @@ /* 1 if we have C99 designated initializers. */ #if !defined(HAVE_DESIGNATED_INITIALIZERS) +#ifdef __cplusplus +#define HAVE_DESIGNATED_INITIALIZERS 0 +#else #define HAVE_DESIGNATED_INITIALIZERS \ - (((GCC_VERSION >= 2007) || (__STDC_VERSION__ >= 199901L)) \ - && !defined(__cplusplus)) + (((GCC_VERSION >= 2007) || (__STDC_VERSION__ >= 199901L)) #endif +#endif #if !defined(HAVE_DESIGNATED_UNION_INITIALIZERS) +#ifdef __cplusplus +#define HAVE_DESIGNATED_UNION_INITIALIZERS (GCC_VERSION >= 4007) +#else #define HAVE_DESIGNATED_UNION_INITIALIZERS \ - (((GCC_VERSION >= 2007) || (__STDC_VERSION__ >= 199901L)) \ - && (!defined(__cplusplus) || (GCC_VERSION >= 4007))) + (((GCC_VERSION >= 2007) || (__STDC_VERSION__ >= 199901L)) #endif +#endif #if HAVE_SYS_STAT_H # include <sys/stat.h> Index: gcc/testsuite/gcc.dg/cpp/defined-Wno-expansion-to-defined.c =================================================================== --- gcc/testsuite/gcc.dg/cpp/defined-Wno-expansion-to-defined.c (revision 0) +++ gcc/testsuite/gcc.dg/cpp/defined-Wno-expansion-to-defined.c (working copy) @@ -0,0 +1,30 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. */ + +/* { dg-do preprocess } */ +/* { dg-options "-ansi -pedantic-errors -Wno-expansion-to-defined" } */ + +/* Use of defined in different contexts. */ + +/* Source: Neil Booth, 29 Oct 2000, Zack Weinberg 11 Dec 2000. */ + +#define Z + +#define bad0 defined Z +#if !bad0 /* { dg-bogus "may not be portable" } */ +#error Z is defined +#endif + +#define bad1 defined +#if !bad1 Z /* { dg-bogus "may not be portable" } */ +#error Z is defined +#endif + +#if !bad1 (Z) /* { dg-bogus "may not be portable" } */ +#error Z is defined +#endif + +#define bad2 defined (Z +#if !bad2) /* { dg-bogus "may not be portable" } */ +#error Z is defined +#endif + Index: gcc/testsuite/gcc.dg/cpp/defined-Wexpansion-to-defined.c =================================================================== --- gcc/testsuite/gcc.dg/cpp/defined-Wexpansion-to-defined.c (revision 0) +++ gcc/testsuite/gcc.dg/cpp/defined-Wexpansion-to-defined.c (working copy) @@ -0,0 +1,30 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. */ + +/* { dg-do preprocess } */ +/* { dg-options "-Wexpansion-to-defined" } */ + +/* Use of defined in different contexts. */ + +/* Source: Neil Booth, 29 Oct 2000, Zack Weinberg 11 Dec 2000. */ + +#define Z + +#define bad0 defined Z +#if !bad0 /* { dg-warning "may not be portable" } */ +#error Z is defined +#endif + +#define bad1 defined +#if !bad1 Z /* { dg-warning "may not be portable" } */ +#error Z is defined +#endif + +#if !bad1 (Z) /* { dg-warning "may not be portable" } */ +#error Z is defined +#endif + +#define bad2 defined (Z +#if !bad2) /* { dg-warning "may not be portable" } */ +#error Z is defined +#endif + Index: gcc/testsuite/gcc.dg/cpp/defined-Wextra-Wno-expansion-to-defined.c =================================================================== --- gcc/testsuite/gcc.dg/cpp/defined-Wextra-Wno-expansion-to-defined.c (revision 0) +++ gcc/testsuite/gcc.dg/cpp/defined-Wextra-Wno-expansion-to-defined.c (working copy) @@ -0,0 +1,30 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. */ + +/* { dg-do preprocess } */ +/* { dg-options "-Wextra -Wno-expansion-to-defined" } */ + +/* Use of defined in different contexts. */ + +/* Source: Neil Booth, 29 Oct 2000, Zack Weinberg 11 Dec 2000. */ + +#define Z + +#define bad0 defined Z +#if !bad0 /* { dg-bogus "may not be portable" } */ +#error Z is defined +#endif + +#define bad1 defined +#if !bad1 Z /* { dg-bogus "may not be portable" } */ +#error Z is defined +#endif + +#if !bad1 (Z) /* { dg-bogus "may not be portable" } */ +#error Z is defined +#endif + +#define bad2 defined (Z +#if !bad2) /* { dg-bogus "may not be portable" } */ +#error Z is defined +#endif + Index: gcc/testsuite/gcc.dg/cpp/defined-Wextra.c =================================================================== --- gcc/testsuite/gcc.dg/cpp/defined-Wextra.c (revision 0) +++ gcc/testsuite/gcc.dg/cpp/defined-Wextra.c (working copy) @@ -0,0 +1,30 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. */ + +/* { dg-do preprocess } */ +/* { dg-options "-Wextra" } */ + +/* Use of defined in different contexts. */ + +/* Source: Neil Booth, 29 Oct 2000, Zack Weinberg 11 Dec 2000. */ + +#define Z + +#define bad0 defined Z +#if !bad0 /* { dg-warning "may not be portable" } */ +#error Z is defined +#endif + +#define bad1 defined +#if !bad1 Z /* { dg-warning "may not be portable" } */ +#error Z is defined +#endif + +#if !bad1 (Z) /* { dg-warning "may not be portable" } */ +#error Z is defined +#endif + +#define bad2 defined (Z +#if !bad2) /* { dg-warning "may not be portable" } */ +#error Z is defined +#endif + Index: gcc/testsuite/gcc.dg/cpp/defined.c =================================================================== --- gcc/testsuite/gcc.dg/cpp/defined.c (revision 239276) +++ gcc/testsuite/gcc.dg/cpp/defined.c (working copy) @@ -21,7 +21,7 @@ /* The behavior of "defined" when it comes from a macro expansion is now documented. */ -#if is_Z_defined +#if is_Z_defined /* { dg-error "may not be portable" } */ #error Macro expanding into defined operator test 1 #endif @@ -31,7 +31,7 @@ #error Z is defined #endif -#if !is_Z_defined +#if !is_Z_defined /* { dg-error "may not be portable" } */ #error Macro expanding into defined operator test 2 #endif @@ -53,7 +53,7 @@ /* The behavior of "defined" when it comes from a macro expansion is now documented. */ -#if is_Z_defined +#if is_Z_defined /* { dg-error "may not be portable" } */ #error Macro expanding into defined operator test 1 #endif @@ -63,23 +63,23 @@ #error Z is defined #endif -#if !is_Z_defined +#if !is_Z_defined /* { dg-error "may not be portable" } */ #error Macro expanding into defined operator test 2 #endif /* Use of defined in different contexts. */ #define bad1 defined -#if !bad1 Z /* { dg-warning "may not be portable" } */ +#if !bad1 Z /* { dg-error "may not be portable" } */ #error Z is defined #endif -#if !bad1 (Z) /* { dg-warning "may not be portable" } */ +#if !bad1 (Z) /* { dg-error "may not be portable" } */ #error Z is defined #endif #define bad2 defined (Z -#if !bad2) /* { dg-warning "may not be portable" } */ +#if !bad2) /* { dg-error "may not be portable" } */ #error Z is defined #endif Index: libcpp/expr.c =================================================================== --- libcpp/expr.c (revision 239276) +++ libcpp/expr.c (working copy) @@ -947,9 +947,11 @@ if (node) { - if (pfile->context != initial_context && CPP_PEDANTIC (pfile)) - cpp_error (pfile, CPP_DL_WARNING, - "this use of \"defined\" may not be portable"); + if ((pfile->context != initial_context + || initial_context != &pfile->base_context) + && CPP_OPTION (pfile, warn_expansion_to_defined)) + cpp_pedwarning (pfile, CPP_W_EXPANSION_TO_DEFINED, + "this use of \"defined\" may not be portable"); _cpp_mark_macro_used (node); if (!(node->flags & NODE_USED)) Index: libcpp/include/cpplib.h =================================================================== --- libcpp/include/cpplib.h (revision 239276) +++ libcpp/include/cpplib.h (working copy) @@ -410,6 +410,10 @@ /* Nonzero means warn if undefined identifiers are evaluated in an #if. */ unsigned char warn_undef; + /* Nonzero means warn if "defined" is encountered in a place other than + an #if. */ + unsigned char warn_expansion_to_defined; + /* Nonzero means warn of unused macros from the main file. */ unsigned char warn_unused_macros; @@ -1025,7 +1029,8 @@ CPP_W_DATE_TIME, CPP_W_PEDANTIC, CPP_W_C90_C99_COMPAT, - CPP_W_CXX11_COMPAT + CPP_W_CXX11_COMPAT, + CPP_W_EXPANSION_TO_DEFINED }; /* Output a diagnostic of some kind. */ Index: libcpp/system.h =================================================================== --- libcpp/system.h (revision 239276) +++ libcpp/system.h (working copy) @@ -375,10 +375,13 @@ ??? C99 designated initializers are not supported by most C++ compilers, including G++. -- gdr, 2005-05-18 */ #if !defined(HAVE_DESIGNATED_INITIALIZERS) +#ifdef __cplusplus +#define HAVE_DESIGNATED_INITIALIZERS 0 +#else #define HAVE_DESIGNATED_INITIALIZERS \ - (!defined(__cplusplus) \ - && ((GCC_VERSION >= 2007) || (__STDC_VERSION__ >= 199901L))) + ((GCC_VERSION >= 2007) || (__STDC_VERSION__ >= 199901L)) #endif +#endif #ifndef offsetof #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *) 0)->MEMBER)
From: Paolo Bonzini <bonzini@gnu.org> clang recently added a new warning -Wexpansion-to-defined, which warns when `defined' is used outside a #if expression (including the case of a macro that is then used in a #if expression). While I disagree with their inclusion of the warning to -Wall, I think it is a good addition overall. First, it is a logical extension of the existing warning for breaking defined across a macro and its caller. Second, it is good to make these warnings for `defined' available with a command-line option other than -pedantic. This patch adds -Wexpansion-to-defined, and enables it automatically for both -pedantic (as before) and -Wextra. It also changes the warning from a warning to a pedwarn; this is mostly for documentation sake since the EnabledBy machinery would turn -pedantic-errors into -Werror=expansion-to-defined anyway. Bootstrapped and regression tested x86_64-pc-linux-gnu, ok? Paolo libcpp: 2016-08-09 Paolo Bonzini <bonzini@gnu.org> * include/cpplib.h (struct cpp_options): Add new member warn_expansion_to_defined. (CPP_W_EXPANSION_TO_DEFINED): New enum member. * expr.c (parse_defined): Warn for all uses of "defined" in macros, and tie warning to CPP_W_EXPANSION_TO_DEFINED. Make it a pedwarning instead of a warning. * system.h (HAVE_DESIGNATED_INITIALIZERS): Do not use "defined" in macros. gcc: 2016-08-09 Paolo Bonzini <bonzini@gnu.org> * system.h (HAVE_DESIGNATED_INITIALIZERS, HAVE_DESIGNATED_UNION_INITIALIZERS): Do not use "defined" in macros. gcc/c-family: 2016-08-09 Paolo Bonzini <bonzini@gnu.org> * c.opt (Wexpansion-to-defined): New. gcc/doc: 2016-08-09 Paolo Bonzini <bonzini@gnu.org> * cpp.texi (Defined): Mention -Wexpansion-to-defined. * cppopts.texi (Invocation): Document -Wexpansion-to-defined. * invoke.texi (Warning Options): Document -Wexpansion-to-defined. gcc/testsuite: 2016-08-09 Paolo Bonzini <bonzini@gnu.org> * gcc.dg/cpp/defined.c: Mark newly introduced warnings and adjust for warning->pedwarn change. * gcc.dg/cpp/defined-Wexpansion-to-defined.c, gcc.dg/cpp/defined-Wextra-Wno-expansion-to-defined.c, gcc.dg/cpp/defined-Wextra.c, gcc.dg/cpp/defined-Wno-expansion-to-defined.c: New testcases.