[PATCH v3] cpp/c: Add -Wexpansion-to-defined

Paolo Bonzini bonzini@gnu.org
Mon Nov 21 17:39:00 GMT 2016



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)
> 



More information about the Gcc-patches mailing list