diff mbox

cpp/c: Add -Wexpansion-to-defined

Message ID 1470758390-42725-1-git-send-email-bonzini@gnu.org
State New
Headers show

Commit Message

Paolo Bonzini Aug. 9, 2016, 3:59 p.m. UTC
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.

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.
        * 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-opts (sanitize_cpp_opts): Compute default value
        for -Wexpansion-to-defined.
        * 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.
        * 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.

Comments

Manuel López-Ibáñez Aug. 9, 2016, 6:30 p.m. UTC | #1
On 09/08/16 16:59, Paolo Bonzini wrote:
> Index: gcc/c-family/c-opts.c
> ===================================================================
> --- gcc/c-family/c-opts.c	(revision 239276)
> +++ gcc/c-family/c-opts.c	(working copy)
> @@ -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;
> +

Instead of the above, plase use LangEnabledBy() or EnabledBy() in c.opt. See 
Wendif-labels and other examples. Then, you do not need Init(-1).

>    /* Wlong-long is disabled by default. It is enabled by:
>        [-Wpedantic | -Wtraditional] -std=[gnu|c]++98 ; or
>        [-Wpedantic | -Wtraditional] -std=non-c99
> Index: gcc/c-family/c.opt
> ===================================================================
> --- gcc/c-family/c.opt	(revision 239276)
> +++ gcc/c-family/c.opt	(working copy)
> @@ -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.
> +

You are also missing CPP(warn_expansion_to_defined) so that the cpp and gcc 
sides are in sync even when using pragmas.

Cheers,

	Manuel.
Eric Gallager Aug. 9, 2016, 6:44 p.m. UTC | #2
Hi, I'm just a lurker, but...

On 8/9/16, Paolo Bonzini <bonzini@gnu.org> wrote:
> Index: gcc/c-family/c.opt
> ===================================================================
> --- gcc/c-family/c.opt	(revision 239276)
> +++ gcc/c-family/c.opt	(working copy)
> @@ -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.
> +

Isn't "Warn if an undefined macro is used in an #if directive" the
same description that -Wundef uses in c.opt? Did you copy and paste
and forget to update that part?

Eric
Paolo Bonzini Aug. 9, 2016, 9:21 p.m. UTC | #3
On 09/08/2016 20:30, Manuel López-Ibáñez wrote:
>>
>>
>> +  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;
>> +
> 
> Instead of the above, plase use LangEnabledBy() or EnabledBy() in c.opt.
> See Wendif-labels and other examples. Then, you do not need Init(-1).

This causes this to produce an error if -pedantic-errors is provided,
because -pedantic-errors does

      control_warning_option (OPT_Wpedantic, DK_ERROR, NULL, value,
			      loc, lang_mask,
			      handlers, opts, opts_set,
                              dc);

and this enables -Wexpansion-to-defined at DK_ERROR level.  Bug or fix?

Paolo
Paolo Bonzini Aug. 9, 2016, 9:32 p.m. UTC | #4
On 09/08/2016 20:44, Eric Gallager wrote:
> Hi, I'm just a lurker, but...
> 
> On 8/9/16, Paolo Bonzini <bonzini@gnu.org> wrote:
>> Index: gcc/c-family/c.opt
>> ===================================================================
>> --- gcc/c-family/c.opt	(revision 239276)
>> +++ gcc/c-family/c.opt	(working copy)
>> @@ -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.
>> +
> 
> Isn't "Warn if an undefined macro is used in an #if directive" the
> same description that -Wundef uses in c.opt? Did you copy and paste
> and forget to update that part?

Yes, of course.  Thanks!

Paolo
Manuel López-Ibáñez Aug. 10, 2016, 12:48 a.m. UTC | #5
On 9 August 2016 at 22:21, Paolo Bonzini <bonzini@gnu.org> wrote:
>
>
> On 09/08/2016 20:30, Manuel López-Ibáñez wrote:
>>>
>>>
>>> +  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;
>>> +
>>
>> Instead of the above, plase use LangEnabledBy() or EnabledBy() in c.opt.
>> See Wendif-labels and other examples. Then, you do not need Init(-1).
>
> This causes this to produce an error if -pedantic-errors is provided,
> because -pedantic-errors does
>
>       control_warning_option (OPT_Wpedantic, DK_ERROR, NULL, value,
>                               loc, lang_mask,
>                               handlers, opts, opts_set,
>                               dc);
>
> and this enables -Wexpansion-to-defined at DK_ERROR level.  Bug or fix?

TL;DR If the warning is enabled by -Wpedantic, it should be an error
with -Werror=pedantic and it should use cpp_pedwarning. Whether it
should be enabled by -Wpedantic is more difficult to say.

-pedantic is equivalent to -Wpedantic. If -Wx is enabled by -Wy, then
-Werror=y implies -Werror=x. Every warning enabled by -Wpedantic works
in the same way and I don't see why this one should be different.

Moreover, I think that this was a latent bug in libcpp: the code
should have used cpp_pedwarning instead of cpp_warning. This is
https://gcc.gnu.org/PR66505
Quoting https://gcc.gnu.org/wiki/DiagnosticsGuidelines#Types_of_diagnostics
: "The same rules apply to libcpp, which uses cpp_pedwarning (instead
of pedwarn), CPP_PEDANTIC (pfile) (instead of pedantic) and
CPP_W_PEDANTIC (instead of OPT_Wpedantic). In particular, you may use
cpp_pedwarning without CPP_W_PEDANTIC, but you may not use
CPP_W_PEDANTIC without cpp_pedwarning and you may not use CPP_PEDANTIC
(pfile) without CPP_W_PEDANTIC."

Cheers,

Manuel.
Paolo Bonzini Aug. 10, 2016, 8:45 a.m. UTC | #6
On 10/08/2016 02:48, Manuel López-Ibáñez wrote:
> TL;DR If the warning is enabled by -Wpedantic, it should be an error
> with -Werror=pedantic and it should use cpp_pedwarning. Whether it
> should be enabled by -Wpedantic is more difficult to say.
> 
> -pedantic is equivalent to -Wpedantic. If -Wx is enabled by -Wy, then
> -Werror=y implies -Werror=x. Every warning enabled by -Wpedantic works
> in the same way and I don't see why this one should be different.
> 
> Moreover, I think that this was a latent bug in libcpp: the code
> should have used cpp_pedwarning instead of cpp_warning. This is
> https://gcc.gnu.org/PR66505
> Quoting https://gcc.gnu.org/wiki/DiagnosticsGuidelines#Types_of_diagnostics
> : "The same rules apply to libcpp, which uses cpp_pedwarning (instead
> of pedwarn), CPP_PEDANTIC (pfile) (instead of pedantic) and
> CPP_W_PEDANTIC (instead of OPT_Wpedantic). In particular, you may use
> cpp_pedwarning without CPP_W_PEDANTIC, but you may not use
> CPP_W_PEDANTIC without cpp_pedwarning and you may not use CPP_PEDANTIC
> (pfile) without CPP_W_PEDANTIC."

But pedwarns are for errors mandated by the standard; this one is not.
Let's just move it from -Wpedantic to -Wextra.

Paolo
diff mbox

Patch

Index: gcc/c-family/c-opts.c
===================================================================
--- gcc/c-family/c-opts.c	(revision 239276)
+++ gcc/c-family/c-opts.c	(working copy)
@@ -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 
Index: gcc/c-family/c.opt
===================================================================
--- gcc/c-family/c.opt	(revision 239276)
+++ gcc/c-family/c.opt	(working copy)
@@ -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.
Index: gcc/doc/cpp.texi
===================================================================
--- gcc/doc/cpp.texi	(revision 239276)
+++ gcc/doc/cpp.texi	(working copy)
@@ -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
Index: gcc/doc/cppopts.texi
===================================================================
--- gcc/doc/cppopts.texi	(revision 239276)
+++ gcc/doc/cppopts.texi	(working copy)
@@ -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
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 239276)
+++ gcc/doc/invoke.texi	(working copy)
@@ -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
Index: gcc/system.h
===================================================================
--- gcc/system.h	(revision 239276)
+++ gcc/system.h	(working copy)
@@ -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>
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-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.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-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
 
Index: libcpp/expr.c
===================================================================
--- libcpp/expr.c	(revision 239276)
+++ libcpp/expr.c	(working copy)
@@ -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))
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h	(revision 239276)
+++ libcpp/include/cpplib.h	(working copy)
@@ -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.  */
Index: libcpp/system.h
===================================================================
--- libcpp/system.h	(revision 239276)
+++ libcpp/system.h	(working copy)
@@ -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)