===================================================================
@@ -1256,6 +1256,10 @@ sanitize_cpp_opts (void)
cpp_opts->unsigned_char = !flag_signed_char;
cpp_opts->stdc_0_in_system_headers = STDC_0_IN_SYSTEM_HEADERS;
+ cpp_opts->warn_expansion_to_defined = cpp_warn_expansion_to_defined;
+ if (cpp_warn_expansion_to_defined == -1)
+ cpp_warn_expansion_to_defined = pedantic || extra_warnings;
+
/* Wlong-long is disabled by default. It is enabled by:
[-Wpedantic | -Wtraditional] -std=[gnu|c]++98 ; or
[-Wpedantic | -Wtraditional] -std=non-c99
===================================================================
@@ -506,6 +506,10 @@ Wdouble-promotion
C ObjC C++ ObjC++ Var(warn_double_promotion) Warning
Warn about implicit conversions from \"float\" to \"double\".
+Wexpansion-to-defined
+C ObjC C++ ObjC++ CppReason(CPP_W_EXPANSION_TO_DEFINED) Var(cpp_warn_expansion_to_defined) Init(-1) Warning
+Warn if an undefined macro is used in an #if directive.
+
Wimplicit-function-declaration
C ObjC Var(warn_implicit_function_declaration) Init(-1) Warning LangEnabledBy(C ObjC,Wimplicit)
Warn about implicit function declarations.
===================================================================
@@ -3342,7 +3342,8 @@ If the @code{defined} operator appears as a result
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{-pedantic}, since other compilers may handle it differently. The
+warning can also be enabled individually with @option{-Wexpansion-to-defined}.
@node Else
@subsection Else
===================================================================
@@ -120,6 +120,12 @@ Warn whenever an identifier which is not a macro i
@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
===================================================================
@@ -4914,6 +4914,11 @@ Warn when a declaration is found after a statement
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
===================================================================
@@ -577,16 +577,22 @@ extern int vsnprintf (char *, size_t, const char *
/* 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>
===================================================================
@@ -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
+
===================================================================
@@ -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
+
===================================================================
@@ -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
+
===================================================================
@@ -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
+
===================================================================
@@ -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-warning "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-warning "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-warning "may not be portable" } */
#error Macro expanding into defined operator test 1
#endif
@@ -63,7 +63,7 @@
#error Z is defined
#endif
-#if !is_Z_defined
+#if !is_Z_defined /* { dg-warning "may not be portable" } */
#error Macro expanding into defined operator test 2
#endif
===================================================================
@@ -947,9 +947,11 @@ parse_defined (cpp_reader *pfile)
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_warning (pfile, CPP_W_EXPANSION_TO_DEFINED,
+ "this use of \"defined\" may not be portable");
_cpp_mark_macro_used (node);
if (!(node->flags & NODE_USED))
===================================================================
@@ -410,6 +410,10 @@ struct cpp_options
/* 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 @@ enum {
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. */
===================================================================
@@ -375,10 +375,13 @@ extern void abort (void);
??? 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)