[PATCH][RFA] Enabling -W[no-]error=... for cpplib warnings

View: New views
12 Messages — Rating Filter:   Alert me  

[PATCH][RFA] Enabling -W[no-]error=... for cpplib warnings

by Simon Baldwin-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

This patch brings several preprocessor warnings under the control of the
-Werror= gcc flag.  At present, gcc does not associate preprocessor warnings
with gcc command line options, and so such warnings cannot be controlled
individually with -Werror=.

With the patch in place, preprocessor warnings can now be set separately as
errors with -Werror=, disabled as errors with -Wno-error=, and will report
their corresponding gcc diagnostic flag with -fdiagnostics-show-option when
requested.

The patch also adds a new gcc option -W[no-]warning-directive so that the
output of #warning operates symmetrically to other gcc warnings, and in
particular so that the combination "-Werror -Wno-error=warning-directive"
allows all warnings except for #warning directives to be treated as errors.

Confirmed C/C++ dejagnu testsuite parity with the unpatched gcc, and verified
bootstrap of C/C++ on x86_64.

Okay for mainline?


gcc/ChangeLog:
2009-10-30  Simon Baldwin  <simonb@...>

        * diagnostic.h (diagnostic_override_option_index): New macro to
        set a diagnostic's option_index.
        * c-tree.h (c_cpp_error): Add warning reason argument.
        * opts.c (_warning_as_error_callback): New.
        (register_warning_as_error_callback): Store callback for
        warnings enabled via enable_warning_as_error.
        (enable_warning_as_error): Call callback, minor code tidy.
        * opts.h (register_warning_as_error_callback): Declare.
        * c-opts.c (warning_as_error_callback): New, set cpp_opts flag in
        response to -Werror=.
        (c_common_init_options): Register warning_as_error_callback in opts.c.
        * common.opt: Add -Wno-warning-directive option.
        * c-common.c (struct reason_option_codes_t): Map cpp warning
        reason codes to gcc option indexes.
        * (c_option_controlling_cpp_error): New function, lookup the gcc
        option index for a cpp warning reason code.
        * (c_cpp_error): Add warning reason argument, call
        c_option_controlling_cpp_error for diagnostic_override_option_index.
        * doc/invoke.texi: Document -Wno-warning-directive.

libcpp/ChangeLog:
2009-10-30  Simon Baldwin  <simonb@...>

        * directives.c (do_diagnostic): Add warning reason argument,
        call appropriate error reporting function for code.
        (directive_diagnostics): Call specific warning functions with
        warning reason where appropriate.
        (do_error, do_warning, do_pragma_dependency): Add warning reason
        argument to do_diagnostic calls.
        * macro.c (_cpp_warn_if_unused_macro, enter_macro_context,
        _cpp_create_definition): Call specific warning functions with
        warning reason where appropriate.
        * include/cpplib.h (struct cpp_callbacks): Add warning reason code
        to error callback.
        (CPP_DL_WARNING, CPP_DL_WARNING_SYSHDR, CPP_DL_PEDWARN, CPP_DL_ERROR,
        CPP_DL_ICE, CPP_DL_NOTE, CPP_DL_FATAL): Replace macros with enums.
        (CPP_W_NONE, CPP_W_DEPRECATED, CPP_W_COMMENTS,
        CPP_W_MISSING_INCLUDE_DIRS, CPP_W_TRIGRAPHS, CPP_W_MULTICHAR,
        CPP_W_TRADITIONAL, CPP_W_LONG_LONG, CPP_W_ENDIF_LABELS,
        CPP_W_NUM_SIGN_CHANGE, CPP_W_VARIADIC_MACROS,
        CPP_W_BUILTIN_MACRO_REDEFINED, CPP_W_DOLLARS, CPP_W_UNDEF,
        CPP_W_UNUSED_MACROS, CPP_W_CXX_OPERATOR_NAMES, CPP_W_NORMALIZE,
        CPP_W_INVALID_PCH, CPP_W_WARNING_DIRECTIVE): New enums for cpp
        warning reason codes.
        (cpp_warning, cpp_pedwarning, cpp_warning_syshdr,
        cpp_warning_with_line, cpp_pedwarning_with_line,
        cpp_warning_with_line_syshdr): New specific error reporting functions.
        * pch.c (cpp_valid_state): Call specific warning functions with
        warning reason where appropriate.
        * errors.c (cpp_diagnostic, cpp_diagnostic_with_line): New central
        diagnostic handlers.
        (cpp_warning, cpp_pedwarning, cpp_warning_syshdr,
        cpp_warning_with_line, cpp_pedwarning_with_line,
        cpp_warning_with_line_syshdr): New specific error reporting functions.
        * expr.c (cpp_classify_number, eval_token, num_unary_op): Call
        specific warning functions with warning reason where appropriate.
        * lex.c (_cpp_process_line_notes, _cpp_skip_block_comment,
        warn_about_normalization, lex_identifier, _cpp_lex_direct): Ditto.
        * charset.c (_cpp_valid_ucn, convert_hex, convert_escape,
        narrow_str_to_charconst): Ditto.

gcc/testsuite/ChangeLog:
2009-10-30  Simon Baldwin  <simonb@...>

        * gcc.dg/cpp/warn-undef-2.c: New.
        * gcc.dg/cpp/warn-traditional-2.c: New.
        * gcc.dg/cpp/warn-comments-2.c: New.
        * gcc.dg/cpp/warning-directive-1.c: New.
        * gcc.dg/cpp/warn-long-long.c: New.
        * gcc.dg/cpp/warn-traditional.c: New.
        * gcc.dg/cpp/warn-variadic-2.c: New.
        * gcc.dg/cpp/warn-undef.c: New.
        * gcc.dg/cpp/warn-normalized-1.c: New.
        * gcc.dg/cpp/warning-directive-2.c: New.
        * gcc.dg/cpp/warn-long-long-2.c: New.
        * gcc.dg/cpp/warn-variadic.c: New.
        * gcc.dg/cpp/warn-normalized-2.c: New.
        * gcc.dg/cpp/warning-directive-3.c: New.
        * gcc.dg/cpp/warn-deprecated-2.c: New.
        * gcc.dg/cpp/warn-trigraphs-1.c: New.
        * gcc.dg/cpp/warn-multichar-2.c: New.
        * gcc.dg/cpp/warn-normalized-3.c: New.
        * gcc.dg/cpp/warning-directive-4.c: New.
        * gcc.dg/cpp/warn-unused-macros.c: New.
        * gcc.dg/cpp/warn-trigraphs-2.c: New.
        * gcc.dg/cpp/warn-cxx-compat-2.c: New.
        * gcc.dg/cpp/warn-cxx-compat.c: New.
        * gcc.dg/cpp/warn-redefined.c: New.
        * gcc.dg/cpp/warn-trigraphs-3.c: New.
        * gcc.dg/cpp/warn-unused-macros-2.c: New.
        * gcc.dg/cpp/warn-deprecated.c: New.
        * gcc.dg/cpp/warn-trigraphs-4.c: New.
        * gcc.dg/cpp/warn-redefined-2.c: New.
        * gcc.dg/cpp/warn-comments.c: New.
        * gcc.dg/cpp/warn-multichar.c: New.


Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi (revision 153497)
+++ gcc/doc/invoke.texi (working copy)
@@ -270,7 +270,7 @@ Objective-C and Objective-C++ Dialects}.
 -Wmissing-parameter-type  -Wmissing-prototypes  -Wnested-externs @gol
 -Wold-style-declaration  -Wold-style-definition @gol
 -Wstrict-prototypes  -Wtraditional  -Wtraditional-conversion @gol
--Wdeclaration-after-statement -Wpointer-sign}
+-Wdeclaration-after-statement -Wpointer-sign  -Wwarning-directive}
 
 @item Debugging Options
 @xref{Debugging Options,,Options for Debugging Your Program or GCC}.
@@ -4325,6 +4325,10 @@ a suffix.  When used together with @opti
 warn about such constants in system header files.  This can be useful
 when preparing code to use with the @code{FLOAT_CONST_DECIMAL64} pragma
 from the decimal floating-point extension to C99.
+
+@item -Wno-warning-directive @r{(C and Objective-C only)}
+
+Suppress warning messages emitted by @code{#warning} directives.
 @end table
 
 @node Debugging Options
Index: gcc/diagnostic.h
===================================================================
--- gcc/diagnostic.h (revision 153497)
+++ gcc/diagnostic.h (working copy)
@@ -190,6 +190,11 @@ extern diagnostic_context *global_dc;
    diagnostic.  */
 #define diagnostic_override_column(DI, COL) (DI)->override_column = (COL)
 
+/* Override the option index to be used for reporting a
+   diagnostic.  */
+#define diagnostic_override_option_index(DI, OPTIDX) \
+    (DI)->option_index = (OPTIDX)
+
 /* Diagnostic related functions.  */
 extern void diagnostic_initialize (diagnostic_context *);
 extern void diagnostic_report_current_module (diagnostic_context *);
Index: gcc/testsuite/gcc.dg/cpp/warn-undef-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-undef-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-undef-2.c (revision 0)
@@ -0,0 +1,5 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=undef" }
+
+#if x  // { dg-error "\"x\" is not defined .-Wundef." }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-traditional-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-traditional-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-traditional-2.c (revision 0)
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=traditional -Wno-deprecated -Wno-long-long" }
+
+#assert x(x)         // { dg-error "suggest hiding #assert from traditional C with an indented # .-Wtraditional." }
+
+ #define X X         // { dg-error "traditional C ignores #define with the # indented .-Wtraditional." }
+
+#if 0
+#elif 1              // { dg-error "suggest not using #elif in traditional C .-Wtraditional." }
+#endif
+
+#define f(X) X
+int f;               // { dg-error "function-like macro \"f\" must be used with arguments in traditional C .-Wtraditional." }
+
+#if 0U               // { dg-error "traditional C rejects the \"U\" suffix .-Wtraditional." }
+#endif
+
+#if +1               // { dg-error " traditional C rejects the unary plus operator .-Wtraditional." }
+#endif
+
+char *x = "\x0";     // { dg-error "the meaning of '.x' is different in traditional C .-Wtraditional." }
+char *y = "\a";      // { dg-error "the meaning of '.a' is different in traditional C .-Wtraditional." }
+char *z = "\u0F43";  // { dg-error "the meaning of '.u' is different in traditional C .-Wtraditional." }
Index: gcc/testsuite/gcc.dg/cpp/warn-comments-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-comments-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-comments-2.c (revision 0)
@@ -0,0 +1,7 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=comments" }
+
+/* /* */  // { dg-error "\"\.\*\" within comment .-Wcomments." }
+
+// \
+          // { dg-error "multi-line comment .-Wcomments." "multi-line" { target *-*-* } 6 }
Index: gcc/testsuite/gcc.dg/cpp/warning-directive-1.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warning-directive-1.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warning-directive-1.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option" }
+
+#warning "Printed"  // { dg-warning "\"Printed\" .-Wwarning-directive." }
Index: gcc/testsuite/gcc.dg/cpp/warn-long-long.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-long-long.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-long-long.c (revision 0)
@@ -0,0 +1,6 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wtraditional -Wlong-long" }
+
+#if 0LL  // { dg-warning "traditional C rejects the \"LL\" suffix .-Wlong-long." }
+         // { dg-warning "use of C99 long long integer constant .-Wlong-long." "use long long" { target *-*-* } 4 }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-traditional.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-traditional.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-traditional.c (revision 0)
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wtraditional -Wno-deprecated -Wno-long-long" }
+
+#assert x(x)         // { dg-warning "suggest hiding #assert from traditional C with an indented # .-Wtraditional." }
+
+ #define X X         // { dg-warning "traditional C ignores #define with the # indented .-Wtraditional." }
+
+#if 0
+#elif 1              // { dg-warning "suggest not using #elif in traditional C .-Wtraditional." }
+#endif
+
+#define f(X) X
+int f;               // { dg-warning "function-like macro \"f\" must be used with arguments in traditional C .-Wtraditional." }
+
+#if 0U               // { dg-warning "traditional C rejects the \"U\" suffix .-Wtraditional." }
+#endif
+
+#if +1               // { dg-warning " traditional C rejects the unary plus operator .-Wtraditional." }
+#endif
+
+char *x = "\x0";     // { dg-warning "the meaning of '.x' is different in traditional C .-Wtraditional." }
+char *y = "\a";      // { dg-warning "the meaning of '.a' is different in traditional C .-Wtraditional." }
+char *z = "\u0F43";  // { dg-warning "the meaning of '.u' is different in traditional C .-Wtraditional." }
Index: gcc/testsuite/gcc.dg/cpp/warn-variadic-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-variadic-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-variadic-2.c (revision 0)
@@ -0,0 +1,6 @@
+/* { dg-do preprocess } */
+/* { dg-options "-ansi -fdiagnostics-show-option -pedantic -Werror=variadic-macros" } */
+
+#define F(...) X   /* { dg-error "anonymous variadic macros were introduced in C99 .-Wvariadic-macros." } */
+
+#define G(X...) X  /* { dg-error "ISO C does not permit named variadic macros .-Wvariadic-macros." } */
Index: gcc/testsuite/gcc.dg/cpp/warn-undef.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-undef.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-undef.c (revision 0)
@@ -0,0 +1,5 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wundef" }
+
+#if x  // { dg-warning "\"x\" is not defined .-Wundef." }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-normalized-1.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-normalized-1.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-normalized-1.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -fextended-identifiers -Wnormalized=nfc" }
+
+\u0F43  // { dg-warning "`.U00000f43' is not in NFC .-Wnormalized=." }
Index: gcc/testsuite/gcc.dg/cpp/warning-directive-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warning-directive-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warning-directive-2.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=warning-directive" }
+
+#warning "Printed"  // { dg-error "\"Printed\" .-Wwarning-directive." }
Index: gcc/testsuite/gcc.dg/cpp/warn-long-long-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-long-long-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-long-long-2.c (revision 0)
@@ -0,0 +1,6 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wtraditional -Werror=long-long" }
+
+#if 0LL  // { dg-error "traditional C rejects the \"LL\" suffix .-Wlong-long." }
+         // { dg-error "use of C99 long long integer constant .-Wlong-long." "use long long" { target *-*-* } 4 }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-variadic.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-variadic.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-variadic.c (revision 0)
@@ -0,0 +1,6 @@
+/* { dg-do preprocess } */
+/* { dg-options "-ansi -fdiagnostics-show-option -pedantic -Wvariadic-macros" } */
+
+#define F(...) X   /* { dg-warning "anonymous variadic macros were introduced in C99 .-Wvariadic-macros." } */
+
+#define G(X...) X  /* { dg-warning "ISO C does not permit named variadic macros .-Wvariadic-macros." } */
Index: gcc/testsuite/gcc.dg/cpp/warn-normalized-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-normalized-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-normalized-2.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -fextended-identifiers -Wnormalized=nfkc" }
+
+\u00AA  // { dg-warning "`.U000000aa' is not in NFKC .-Wnormalized=." }
Index: gcc/testsuite/gcc.dg/cpp/warning-directive-3.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warning-directive-3.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warning-directive-3.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror -Wno-error=warning-directive" }
+
+#warning "Printed"  // { dg-warning "\"Printed\" .-Wwarning-directive." }
Index: gcc/testsuite/gcc.dg/cpp/warn-deprecated-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-deprecated-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-deprecated-2.c (revision 0)
@@ -0,0 +1,7 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=deprecated" }
+
+#assert x(x)  // { dg-error "#assert is a deprecated GCC extension .-Wdeprecated." }
+
+#if #x(x)     // { dg-error "assertions are a deprecated extension .-Wdeprecated." }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-trigraphs-1.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-trigraphs-1.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-trigraphs-1.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -trigraphs -Wtrigraphs" }
+
+??=  // { dg-warning "trigraph \\?\\?= converted to # .-Wtrigraphs." }
Index: gcc/testsuite/gcc.dg/cpp/warn-multichar-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-multichar-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-multichar-2.c (revision 0)
@@ -0,0 +1,5 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=multichar" }
+
+#if 'abc'  // { dg-error "multi-character character constant .-Wmultichar." }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-normalized-3.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-normalized-3.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-normalized-3.c (revision 0)
@@ -0,0 +1,5 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -fextended-identifiers -Werror=normalized=" }
+
+        // { dg-prune-output ".*-Werror=normalized=: Set -Wnormalized=nfc.*" }
+\u0F43  // { dg-error "`.U00000f43' is not in NFC .-Wnormalized=." }
Index: gcc/testsuite/gcc.dg/cpp/warning-directive-4.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warning-directive-4.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warning-directive-4.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wno-warning-directive" }
+
+#warning "Not printed"  // { dg-bogus "." }
Index: gcc/testsuite/gcc.dg/cpp/warn-unused-macros.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-unused-macros.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-unused-macros.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wunused-macros" }
+
+#define X X  // { dg-warning "macro \"X\" is not used .-Wunused-macros." }
Index: gcc/testsuite/gcc.dg/cpp/warn-trigraphs-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-trigraphs-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-trigraphs-2.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wtrigraphs" }
+
+??=  // { dg-warning "trigraph \\?\\?= ignored, use -trigraphs to enable .-Wtrigraphs." }
Index: gcc/testsuite/gcc.dg/cpp/warn-cxx-compat-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-cxx-compat-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-cxx-compat-2.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=c++-compat" }
+
+#define not !  // { dg-error "identifier \"not\" is a special operator name in C\\+\\+ .-Wc\\+\\+-compat." }
Index: gcc/testsuite/gcc.dg/cpp/warn-cxx-compat.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-cxx-compat.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-cxx-compat.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wc++-compat" }
+
+#define not !  // { dg-warning "identifier \"not\" is a special operator name in C\\+\\+ .-Wc\\+\\+-compat." }
Index: gcc/testsuite/gcc.dg/cpp/warn-redefined.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-redefined.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-redefined.c (revision 0)
@@ -0,0 +1,18 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wbuiltin-macro-redefined" }
+
+#ifndef __TIME__
+#error "__TIME__ builtin is not defined"
+// { dg-bogus "__TIME__ builtin is not defined" "no-time" { target *-*-* } 5 }
+#endif
+
+#define __TIME__ "X"  // { dg-warning "\"__TIME__\" redefined .-Wbuiltin-macro-redefined." }
+
+#define __TIME__ "Y"  // { dg-bogus "-Wbuiltin-macro-redefined" }
+                      // { dg-warning "\"__TIME__\" redefined" "not-builtin-1" { target *-*-* } 11 }
+                      // { dg-message "previous definition" "previous-1" { target *-*-* } 9 }
+
+#define X "X"
+#define X "Y"         // { dg-bogus "-Wbuiltin-macro-redefined" }
+                      // { dg-warning "\"X\" redefined" "not-builtin-2" { target *-*-* } 16 }
+                      // { dg-message "previous definition" "previous-2" { target *-*-* } 15 }
Index: gcc/testsuite/gcc.dg/cpp/warn-trigraphs-3.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-trigraphs-3.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-trigraphs-3.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -trigraphs -Werror=trigraphs" }
+
+??=  // { dg-error "trigraph \\?\\?= converted to # .-Wtrigraphs." }
Index: gcc/testsuite/gcc.dg/cpp/warn-unused-macros-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-unused-macros-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-unused-macros-2.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=unused-macros" }
+
+#define X X  // { dg-error "macro \"X\" is not used .-Wunused-macros." }
Index: gcc/testsuite/gcc.dg/cpp/warn-deprecated.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-deprecated.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-deprecated.c (revision 0)
@@ -0,0 +1,7 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wdeprecated" }
+
+#assert x(x)  // { dg-warning "#assert is a deprecated GCC extension .-Wdeprecated." }
+
+#if #x(x)     // { dg-warning "assertions are a deprecated extension .-Wdeprecated." }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-trigraphs-4.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-trigraphs-4.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-trigraphs-4.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=trigraphs" }
+
+??=  // { dg-error "trigraph \\?\\?= ignored, use -trigraphs to enable .-Wtrigraphs." }
Index: gcc/testsuite/gcc.dg/cpp/warn-redefined-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-redefined-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-redefined-2.c (revision 0)
@@ -0,0 +1,18 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=builtin-macro-redefined" }
+
+#ifndef __TIME__
+#error "__TIME__ builtin is not defined"
+// { dg-bogus "__TIME__ builtin is not defined" "no-time" { target *-*-* } 5 }
+#endif
+
+#define __TIME__ "X"  // { dg-error "\"__TIME__\" redefined .-Wbuiltin-macro-redefined." }
+
+#define __TIME__ "Y"  // { dg-bogus "-Wbuiltin-macro-redefined" }
+                      // { dg-warning "\"__TIME__\" redefined" "not-builtin-1" { target *-*-* } 11 }
+                      // { dg-message "previous definition" "previous-1" { target *-*-* } 9 }
+
+#define X "X"
+#define X "Y"         // { dg-bogus "-Wbuiltin-macro-redefined" }
+                      // { dg-warning "\"X\" redefined" "not-builtin-2" { target *-*-* } 16 }
+                      // { dg-message "previous definition" "previous-2" { target *-*-* } 15 }
Index: gcc/testsuite/gcc.dg/cpp/warn-comments.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-comments.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-comments.c (revision 0)
@@ -0,0 +1,7 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wcomments" }
+
+/* /* */  // { dg-warning "\"\.\*\" within comment .-Wcomments." }
+
+// \
+          // { dg-warning "multi-line comment .-Wcomments." "multi-line" { target *-*-* } 6 }
Index: gcc/testsuite/gcc.dg/cpp/warn-multichar.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-multichar.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-multichar.c (revision 0)
@@ -0,0 +1,5 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wmultichar" }
+
+#if 'abc'  // { dg-warning "multi-character character constant .-Wmultichar." }
+#endif
Index: gcc/c-tree.h
===================================================================
--- gcc/c-tree.h (revision 153497)
+++ gcc/c-tree.h (working copy)
@@ -604,8 +604,8 @@ extern void c_write_global_declarations
 extern void pedwarn_c90 (location_t, int opt, const char *, ...) ATTRIBUTE_GCC_CDIAG(3,4);
 extern void pedwarn_c99 (location_t, int opt, const char *, ...) ATTRIBUTE_GCC_CDIAG(3,4);
 
-extern bool c_cpp_error (cpp_reader *, int, location_t, unsigned int,
+extern bool c_cpp_error (cpp_reader *, int, int, location_t, unsigned int,
  const char *, va_list *)
-     ATTRIBUTE_GCC_CDIAG(5,0);
+     ATTRIBUTE_GCC_CDIAG(6,0);
 
 #endif /* ! GCC_C_TREE_H */
Index: gcc/opts.c
===================================================================
--- gcc/opts.c (revision 153497)
+++ gcc/opts.c (working copy)
@@ -2360,6 +2360,19 @@ set_option (const struct cl_option *opti
     }
 }
 
+
+/* Callback function, called when -Werror= enables a warning.  */
+
+static void (*warning_as_error_callback) (int) = NULL;
+
+/* Register a callback for enable_warning_as_error calls.  */
+
+void
+register_warning_as_error_callback (void (*callback) (int))
+{
+  warning_as_error_callback = callback;
+}
+
 /* Enable a warning option as an error.  This is used by -Werror= and
    also by legacy Werror-implicit-function-declaration.  */
 
@@ -2379,14 +2392,20 @@ enable_warning_as_error (const char *arg
     }
   else
     {
-      diagnostic_t kind = value ? DK_ERROR : DK_WARNING;
+      const diagnostic_t kind = value ? DK_ERROR : DK_WARNING;
+
       diagnostic_classify_diagnostic (global_dc, option_index, kind);
-      
-      /* -Werror=foo implies -Wfoo.  */
-      if (cl_options[option_index].var_type == CLVC_BOOLEAN
-  && cl_options[option_index].flag_var
-  && kind == DK_ERROR)
- *(int *) cl_options[option_index].flag_var = 1;
+      if (kind == DK_ERROR)
+        {
+  const struct cl_option * const option = cl_options + option_index;
+
+  /* -Werror=foo implies -Wfoo.  */
+  if (option->var_type == CLVC_BOOLEAN && option->flag_var)
+    *(int *) option->flag_var = 1;
+
+  if (warning_as_error_callback)
+    warning_as_error_callback (option_index);
+ }
     }
   free (new_option);
 }
Index: gcc/opts.h
===================================================================
--- gcc/opts.h (revision 153497)
+++ gcc/opts.h (working copy)
@@ -105,6 +105,7 @@ extern int option_enabled (int opt_idx);
 extern bool get_option_state (int, struct cl_option_state *);
 extern void set_option (const struct cl_option *, int, const char *);
 
+extern void register_warning_as_error_callback (void (*callback) (int));
 extern void enable_warning_as_error (const char *arg, int value,
      unsigned int lang_mask);
 extern void print_ignored_options (void);
Index: gcc/c-opts.c
===================================================================
--- gcc/c-opts.c (revision 153497)
+++ gcc/c-opts.c (working copy)
@@ -196,6 +196,90 @@ defer_opt (enum opt_code code, const cha
   deferred_count++;
 }
 
+/* -Werror= may set a warning option to enable a warning that is emitted
+   by the preprocessor.  Set any corresponding flag in cpp_opts.  */
+
+static void
+warning_as_error_callback (int option_index)
+{
+  switch (option_index)
+    {
+      default:
+ /* Ignore options not associated with the preprocessor.  */
+ break;
+
+      case OPT_Wdeprecated:
+ cpp_opts->warn_deprecated = 1;
+ break;
+
+      case OPT_Wcomment:
+      case OPT_Wcomments:
+ cpp_opts->warn_comments = 1;
+ break;
+
+      case OPT_Wtrigraphs:
+ cpp_opts->warn_trigraphs = 1;
+ break;
+
+      case OPT_Wmultichar:
+ cpp_opts->warn_multichar = 1;
+ break;
+
+      case OPT_Wtraditional:
+ cpp_opts->warn_traditional = 1;
+ break;
+
+      case OPT_Wlong_long:
+ cpp_opts->warn_long_long = 1;
+ break;
+
+      case OPT_Wendif_labels:
+ cpp_opts->warn_endif_labels = 1;
+ break;
+
+      case OPT_Wvariadic_macros:
+ /* Set the local flag that is used later to update cpp_opts.  */
+ warn_variadic_macros = 1;
+ break;
+
+      case OPT_Wbuiltin_macro_redefined:
+ cpp_opts->warn_builtin_macro_redefined = 1;
+ break;
+
+      case OPT_Wundef:
+ cpp_opts->warn_undef = 1;
+ break;
+
+      case OPT_Wunused_macros:
+ /* Set the local flag that is used later to update cpp_opts.  */
+ warn_unused_macros = 1;
+ break;
+
+      case OPT_Wc___compat:
+ /* Add warnings in the same way as c_common_handle_option below.  */
+ if (warn_enum_compare == -1)
+  warn_enum_compare = 1;
+ if (warn_jump_misses_init == -1)
+  warn_jump_misses_init = 1;
+ cpp_opts->warn_cxx_operator_names = 1;
+ break;
+
+      case OPT_Wnormalized_:
+ inform (input_location, "-Werror=normalized=: Set -Wnormalized=nfc");
+ cpp_opts->warn_normalize = normalized_C;
+ break;
+
+      case OPT_Winvalid_pch:
+ cpp_opts->warn_invalid_pch = 1;
+ break;
+
+      case OPT_Wwarning_directive:
+ /* Handled by standard diagnostics using the option's associated
+   boolean variable.  */
+ break;
+    }
+}
+
 /* Common initialization before parsing options.  */
 unsigned int
 c_common_init_options (unsigned int argc, const char **argv)
@@ -204,6 +288,9 @@ c_common_init_options (unsigned int argc
   unsigned int i, result;
   struct cpp_callbacks *cb;
 
+  /* Register callback for warnings enabled by -Werror=.  */
+  register_warning_as_error_callback (warning_as_error_callback);
+
   /* This is conditionalized only because that is the way the front
      ends used to do it.  Maybe this should be unconditional?  */
   if (c_dialect_cxx ())
Index: gcc/common.opt
===================================================================
--- gcc/common.opt (revision 153497)
+++ gcc/common.opt (working copy)
@@ -228,6 +228,10 @@ Wunused-variable
 Common Var(warn_unused_variable) Init(-1) Warning
 Warn when a variable is unused
 
+Wwarning-directive
+Common Var(warn_warning_directive) Init(1) Warning
+Warn when a #warning directive is encountered
+
 Wcoverage-mismatch
 Common RejectNegative Var(warn_coverage_mismatch) Warning
 Warn instead of error in case profiles in -fprofile-use do not match
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c (revision 153497)
+++ gcc/c-common.c (working copy)
@@ -8224,6 +8224,49 @@ c_parse_error (const char *gmsgid, enum
 #undef catenate_messages
 }
 
+/* Mapping for cpp message reasons to the options that enable them.  */
+
+struct reason_option_codes_t
+{
+  const int reason; /* cpplib message reason.  */
+  const int option_code; /* gcc option that controls this message.  */
+};
+
+static const struct reason_option_codes_t option_codes[] = {
+  {CPP_W_DEPRECATED, OPT_Wdeprecated},
+  {CPP_W_COMMENTS, OPT_Wcomments},
+  {CPP_W_TRIGRAPHS, OPT_Wtrigraphs},
+  {CPP_W_MULTICHAR, OPT_Wmultichar},
+  {CPP_W_TRADITIONAL, OPT_Wtraditional},
+  {CPP_W_LONG_LONG, OPT_Wlong_long},
+  {CPP_W_ENDIF_LABELS, OPT_Wendif_labels},
+  {CPP_W_VARIADIC_MACROS, OPT_Wvariadic_macros},
+  {CPP_W_BUILTIN_MACRO_REDEFINED, OPT_Wbuiltin_macro_redefined},
+  {CPP_W_UNDEF, OPT_Wundef},
+  {CPP_W_UNUSED_MACROS, OPT_Wunused_macros},
+  {CPP_W_CXX_OPERATOR_NAMES, OPT_Wc___compat},
+  {CPP_W_NORMALIZE, OPT_Wnormalized_},
+  {CPP_W_INVALID_PCH, OPT_Winvalid_pch},
+  {CPP_W_WARNING_DIRECTIVE, OPT_Wwarning_directive},
+  {CPP_W_NONE, 0}
+};
+
+/* Return the gcc option code associated with the reason for a cpp
+   message, or 0 if none.  */
+
+static int
+c_option_controlling_cpp_error (int reason)
+{
+  const struct reason_option_codes_t *entry;
+
+  for (entry = option_codes; entry->reason != CPP_W_NONE; entry++)
+    {
+      if (entry->reason == reason)
+ return entry->option_code;
+    }
+  return 0;
+}
+
 /* Callback from cpp_error for PFILE to print diagnostics from the
    preprocessor.  The diagnostic is of type LEVEL, at location
    LOCATION unless this is after lexing and the compiler's location
@@ -8233,7 +8276,7 @@ c_parse_error (const char *gmsgid, enum
    otherwise.  */
 
 bool
-c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level,
+c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason,
      location_t location, unsigned int column_override,
      const char *msg, va_list *ap)
 {
@@ -8280,6 +8323,8 @@ c_cpp_error (cpp_reader *pfile ATTRIBUTE
   location, dlevel);
   if (column_override)
     diagnostic_override_column (&diagnostic, column_override);
+  diagnostic_override_option_index (&diagnostic,
+                                    c_option_controlling_cpp_error (reason));
   ret = report_diagnostic (&diagnostic);
   if (level == CPP_DL_WARNING_SYSHDR)
     warn_system_headers = save_warn_system_headers;
Index: libcpp/directives.c
===================================================================
--- libcpp/directives.c (revision 153497)
+++ libcpp/directives.c (working copy)
@@ -104,7 +104,7 @@ static const char *parse_include (cpp_re
 static void push_conditional (cpp_reader *, int, int, const cpp_hashnode *);
 static unsigned int read_flag (cpp_reader *, unsigned int);
 static bool strtolinenum (const uchar *, size_t, linenum_type *, bool *);
-static void do_diagnostic (cpp_reader *, int, int);
+static void do_diagnostic (cpp_reader *, int, int, int);
 static cpp_hashnode *lex_macro_node (cpp_reader *, bool);
 static int undefine_macros (cpp_reader *, cpp_hashnode *, void *);
 static void do_include_common (cpp_reader *, enum include_type);
@@ -353,8 +353,8 @@ directive_diagnostics (cpp_reader *pfile
       else if (((dir->flags & DEPRECATED) != 0
  || (dir == &dtable[T_IMPORT] && !CPP_OPTION (pfile, objc)))
        && CPP_OPTION (pfile, warn_deprecated))
- cpp_error (pfile, CPP_DL_WARNING, "#%s is a deprecated GCC extension",
-   dir->name);
+ cpp_warning (pfile, CPP_W_DEPRECATED,
+                     "#%s is a deprecated GCC extension", dir->name);
     }
 
   /* Traditionally, a directive is ignored unless its # is in
@@ -366,16 +366,16 @@ directive_diagnostics (cpp_reader *pfile
   if (CPP_WTRADITIONAL (pfile))
     {
       if (dir == &dtable[T_ELIF])
- cpp_error (pfile, CPP_DL_WARNING,
-   "suggest not using #elif in traditional C");
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+     "suggest not using #elif in traditional C");
       else if (indented && dir->origin == KANDR)
- cpp_error (pfile, CPP_DL_WARNING,
-   "traditional C ignores #%s with the # indented",
-   dir->name);
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+     "traditional C ignores #%s with the # indented",
+     dir->name);
       else if (!indented && dir->origin != KANDR)
- cpp_error (pfile, CPP_DL_WARNING,
-   "suggest hiding #%s from traditional C with an indented #",
-   dir->name);
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+     "suggest hiding #%s from traditional C with an indented #",
+     dir->name);
     }
 }
 
@@ -1043,7 +1043,7 @@ _cpp_do_file_change (cpp_reader *pfile,
 /* Report a warning or error detected by the program we are
    processing.  Use the directive's tokens in the error message.  */
 static void
-do_diagnostic (cpp_reader *pfile, int code, int print_dir)
+do_diagnostic (cpp_reader *pfile, int code, int reason, int print_dir)
 {
   const unsigned char *dir_name;
   unsigned char *line;
@@ -1057,21 +1057,26 @@ do_diagnostic (cpp_reader *pfile, int co
   line = cpp_output_line_to_string (pfile, dir_name);
   pfile->state.prevent_expansion--;
 
-  cpp_error_with_line (pfile, code, src_loc, 0, "%s", line);
+  if (code == CPP_DL_WARNING_SYSHDR && reason)
+    cpp_warning_with_line_syshdr (pfile, reason, src_loc, 0, "%s", line);
+  else if (code == CPP_DL_WARNING && reason)
+    cpp_warning_with_line (pfile, reason, src_loc, 0, "%s", line);
+  else
+    cpp_error_with_line (pfile, code, src_loc, 0, "%s", line);
   free (line);
 }
 
 static void
 do_error (cpp_reader *pfile)
 {
-  do_diagnostic (pfile, CPP_DL_ERROR, 1);
+  do_diagnostic (pfile, CPP_DL_ERROR, 0, 1);
 }
 
 static void
 do_warning (cpp_reader *pfile)
 {
   /* We want #warning diagnostics to be emitted in system headers too.  */
-  do_diagnostic (pfile, CPP_DL_WARNING_SYSHDR, 1);
+  do_diagnostic (pfile, CPP_DL_WARNING_SYSHDR, CPP_W_WARNING_DIRECTIVE, 1);
 }
 
 /* Report program identification.  */
@@ -1501,7 +1506,7 @@ do_pragma_dependency (cpp_reader *pfile)
       if (cpp_get_token (pfile)->type != CPP_EOF)
  {
   _cpp_backup_tokens (pfile, 1);
-  do_diagnostic (pfile, CPP_DL_WARNING, 0);
+  do_diagnostic (pfile, CPP_DL_WARNING, 0, 0);
  }
     }
 
Index: libcpp/macro.c
===================================================================
--- libcpp/macro.c (revision 153497)
+++ libcpp/macro.c (working copy)
@@ -83,8 +83,8 @@ _cpp_warn_if_unused_macro (cpp_reader *p
 
       if (!macro->used
   && MAIN_FILE_P (linemap_lookup (pfile->line_table, macro->line)))
- cpp_error_with_line (pfile, CPP_DL_WARNING, macro->line, 0,
-     "macro \"%s\" is not used", NODE_NAME (node));
+ cpp_warning_with_line (pfile, CPP_W_UNUSED_MACROS, macro->line, 0,
+       "macro \"%s\" is not used", NODE_NAME (node));
     }
 
   return 1;
@@ -860,9 +860,9 @@ enter_macro_context (cpp_reader *pfile,
   if (buff == NULL)
     {
       if (CPP_WTRADITIONAL (pfile) && ! node->value.macro->syshdr)
- cpp_error (pfile, CPP_DL_WARNING,
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
  "function-like macro \"%s\" must be used with arguments in traditional C",
-   NODE_NAME (node));
+     NODE_NAME (node));
 
       if (pragma_buff)
  _cpp_release_buff (pfile, pragma_buff);
@@ -1582,13 +1582,14 @@ parse_params (cpp_reader *pfile, cpp_mac
       if (! CPP_OPTION (pfile, c99)
   && CPP_OPTION (pfile, pedantic)
   && CPP_OPTION (pfile, warn_variadic_macros))
- cpp_error (pfile, CPP_DL_PEDWARN,
-   "anonymous variadic macros were introduced in C99");
+ cpp_pedwarning
+                  (pfile, CPP_W_VARIADIC_MACROS,
+   "anonymous variadic macros were introduced in C99");
     }
   else if (CPP_OPTION (pfile, pedantic)
    && CPP_OPTION (pfile, warn_variadic_macros))
-    cpp_error (pfile, CPP_DL_PEDWARN,
-       "ISO C does not permit named variadic macros");
+    cpp_pedwarning (pfile, CPP_W_VARIADIC_MACROS,
+            "ISO C does not permit named variadic macros");
 
   /* We're at the end, and just expect a closing parenthesis.  */
   token = _cpp_lex_token (pfile);
@@ -1891,10 +1892,14 @@ _cpp_create_definition (cpp_reader *pfil
 
       if (warn_of_redefinition (pfile, node, macro))
  {
+          const int reason = (node->flags & NODE_BUILTIN)
+                             ? CPP_W_BUILTIN_MACRO_REDEFINED : CPP_W_NONE;
   bool warned;
-  warned = cpp_error_with_line (pfile, CPP_DL_PEDWARN,
- pfile->directive_line, 0,
- "\"%s\" redefined", NODE_NAME (node));
+
+  warned = cpp_pedwarning_with_line (pfile, reason,
+     pfile->directive_line, 0,
+     "\"%s\" redefined",
+                                             NODE_NAME (node));
 
   if (warned && node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
     cpp_error_with_line (pfile, CPP_DL_NOTE,
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h (revision 153497)
+++ libcpp/include/cpplib.h (working copy)
@@ -497,9 +497,9 @@ struct cpp_callbacks
 
   /* Called to emit a diagnostic.  This callback receives the
      translated message.  */
-  bool (*error) (cpp_reader *, int, source_location, unsigned int,
+  bool (*error) (cpp_reader *, int, int, source_location, unsigned int,
  const char *, va_list *)
-       ATTRIBUTE_FPTR_PRINTF(5,0);
+       ATTRIBUTE_FPTR_PRINTF(6,0);
 
   /* Callbacks for when a macro is expanded, or tested (whether
      defined or not at the time) in #ifdef, #ifndef or "defined".  */
@@ -826,25 +826,57 @@ cpp_num cpp_num_sign_extend (cpp_num, si
    position in the translation unit with it, use cpp_error_with_line
    with a line number of zero.  */
 
-/* Warning, an error with -Werror.  */
-#define CPP_DL_WARNING 0x00
-/* Same as CPP_DL_WARNING, except it is not suppressed in system headers.  */
-#define CPP_DL_WARNING_SYSHDR 0x01
-/* Warning, an error with -pedantic-errors or -Werror.  */
-#define CPP_DL_PEDWARN 0x02
-/* An error.  */
-#define CPP_DL_ERROR 0x03
-/* An internal consistency check failed.  Prints "internal error: ",
-   otherwise the same as CPP_DL_ERROR.  */
-#define CPP_DL_ICE 0x04
-/* An informative note following a warning.  */
-#define CPP_DL_NOTE 0x05
-/* A fatal error.  */
-#define CPP_DL_FATAL 0x06
+enum {
+  /* Warning, an error with -Werror.  */
+  CPP_DL_WARNING = 0,
+  /* Same as CPP_DL_WARNING, except it is not suppressed in system headers.  */
+  CPP_DL_WARNING_SYSHDR,
+  /* Warning, an error with -pedantic-errors or -Werror.  */
+  CPP_DL_PEDWARN,
+  /* An error.  */
+  CPP_DL_ERROR,
+  /* An internal consistency check failed.  Prints "internal error: ",
+     otherwise the same as CPP_DL_ERROR.  */
+  CPP_DL_ICE,
+  /* An informative note following a warning.  */
+  CPP_DL_NOTE,
+  /* A fatal error.  */
+  CPP_DL_FATAL
+};
+
+/* Warning reason codes. Use a reason code of zero for unclassified warnings
+   and errors that are not warnings.  */
+enum {
+  CPP_W_NONE = 0,
+  CPP_W_DEPRECATED,
+  CPP_W_COMMENTS,
+  CPP_W_MISSING_INCLUDE_DIRS,
+  CPP_W_TRIGRAPHS,
+  CPP_W_MULTICHAR,
+  CPP_W_TRADITIONAL,
+  CPP_W_LONG_LONG,
+  CPP_W_ENDIF_LABELS,
+  CPP_W_NUM_SIGN_CHANGE,
+  CPP_W_VARIADIC_MACROS,
+  CPP_W_BUILTIN_MACRO_REDEFINED,
+  CPP_W_DOLLARS,
+  CPP_W_UNDEF,
+  CPP_W_UNUSED_MACROS,
+  CPP_W_CXX_OPERATOR_NAMES,
+  CPP_W_NORMALIZE,
+  CPP_W_INVALID_PCH,
+  CPP_W_WARNING_DIRECTIVE
+};
 
 /* Output a diagnostic of some kind.  */
 extern bool cpp_error (cpp_reader *, int, const char *msgid, ...)
   ATTRIBUTE_PRINTF_3;
+extern bool cpp_warning (cpp_reader *, int, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_3;
+extern bool cpp_pedwarning (cpp_reader *, int, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_3;
+extern bool cpp_warning_syshdr (cpp_reader *, int, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_3;
 
 /* Output a diagnostic with "MSGID: " preceding the
    error string of errno.  No location is printed.  */
@@ -853,8 +885,18 @@ extern bool cpp_errno (cpp_reader *, int
 /* Same as cpp_error, except additionally specifies a position as a
    (translation unit) physical line and physical column.  If the line is
    zero, then no location is printed.  */
-extern bool cpp_error_with_line (cpp_reader *, int, source_location, unsigned,
- const char *msgid, ...) ATTRIBUTE_PRINTF_5;
+extern bool cpp_error_with_line (cpp_reader *, int, source_location,
+                                 unsigned, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_5;
+extern bool cpp_warning_with_line (cpp_reader *, int, source_location,
+                                   unsigned, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_5;
+extern bool cpp_pedwarning_with_line (cpp_reader *, int, source_location,
+                                      unsigned, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_5;
+extern bool cpp_warning_with_line_syshdr (cpp_reader *, int, source_location,
+                                          unsigned, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_5;
 
 /* In lex.c */
 extern int cpp_ideq (const cpp_token *, const char *);
Index: libcpp/pch.c
===================================================================
--- libcpp/pch.c (revision 153497)
+++ libcpp/pch.c (working copy)
@@ -480,9 +480,9 @@ cpp_valid_state (cpp_reader *r, const ch
   || h->flags & NODE_POISONED)
  {
   if (CPP_OPTION (r, warn_invalid_pch))
-    cpp_error (r, CPP_DL_WARNING_SYSHDR,
-       "%s: not used because `%.*s' is poisoned",
-       name, m.name_length, namebuf);
+    cpp_warning_syshdr (r, CPP_W_INVALID_PCH,
+                "%s: not used because `%.*s' is poisoned",
+                name, m.name_length, namebuf);
   goto fail;
  }
 
@@ -502,9 +502,9 @@ cpp_valid_state (cpp_reader *r, const ch
     continue;
 
   if (CPP_OPTION (r, warn_invalid_pch))
-    cpp_error (r, CPP_DL_WARNING_SYSHDR,
-       "%s: not used because `%.*s' not defined",
-       name, m.name_length, namebuf);
+    cpp_warning_syshdr (r, CPP_W_INVALID_PCH,
+                "%s: not used because `%.*s' not defined",
+                name, m.name_length, namebuf);
   goto fail;
  }
 
@@ -514,7 +514,7 @@ cpp_valid_state (cpp_reader *r, const ch
   || memcmp (namebuf, newdefn, m.definition_length) != 0)
  {
   if (CPP_OPTION (r, warn_invalid_pch))
-    cpp_error (r, CPP_DL_WARNING_SYSHDR,
+    cpp_warning_syshdr (r, CPP_W_INVALID_PCH,
        "%s: not used because `%.*s' defined as `%s' not `%.*s'",
        name, m.name_length, namebuf, newdefn + m.name_length,
        m.definition_length - m.name_length,
@@ -555,9 +555,9 @@ cpp_valid_state (cpp_reader *r, const ch
       else
  {
   if (CPP_OPTION (r, warn_invalid_pch))
-    cpp_error (r, CPP_DL_WARNING_SYSHDR,
-       "%s: not used because `%s' is defined",
-       name, first);
+    cpp_warning_syshdr (r, CPP_W_INVALID_PCH,
+                "%s: not used because `%s' is defined",
+                name, first);
   goto fail;
  }
     }
@@ -575,9 +575,9 @@ cpp_valid_state (cpp_reader *r, const ch
   if (counter && r->counter)
     {
       if (CPP_OPTION (r, warn_invalid_pch))
- cpp_error (r, CPP_DL_WARNING_SYSHDR,
-   "%s: not used because `__COUNTER__' is invalid",
-   name);
+ cpp_warning_syshdr (r, CPP_W_INVALID_PCH,
+            "%s: not used because `__COUNTER__' is invalid",
+            name);
  goto fail;
     }
 
Index: libcpp/errors.c
===================================================================
--- libcpp/errors.c (revision 153497)
+++ libcpp/errors.c (working copy)
@@ -28,16 +28,16 @@ along with this program; see the file CO
 #include "cpplib.h"
 #include "internal.h"
 
-/* Print an error at the location of the previously lexed token.  */
-bool
-cpp_error (cpp_reader * pfile, int level, const char *msgid, ...)
+/* Print a diagnostic at the location of the previously lexed token.  */
+
+ATTRIBUTE_FPTR_PRINTF(4,0)
+static bool
+cpp_diagnostic (cpp_reader * pfile, int level, int reason,
+                const char *msgid, va_list *ap)
 {
   source_location src_loc;
-  va_list ap;
   bool ret;
 
-  va_start (ap, msgid);
-
   if (CPP_OPTION (pfile, traditional))
     {
       if (pfile->state.in_directive)
@@ -61,13 +61,95 @@ cpp_error (cpp_reader * pfile, int level
 
   if (!pfile->cb.error)
     abort ();
-  ret = pfile->cb.error (pfile, level, src_loc, 0, _(msgid), &ap);
+  ret = pfile->cb.error (pfile, level, reason, src_loc, 0, _(msgid), ap);
+
+  return ret;
+}
+
+/* Print a warning or error, depending on the value of LEVEL.  */
+
+bool
+cpp_error (cpp_reader * pfile, int level, const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic (pfile, level, CPP_W_NONE, msgid, &ap);
 
   va_end (ap);
   return ret;
 }
 
-/* Print an error at a specific location.  */
+/* Print a warning.  The warning reason may be given in REASON.  */
+
+bool
+cpp_warning (cpp_reader * pfile, int reason, const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic (pfile, CPP_DL_WARNING, reason, msgid, &ap);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a pedantic warning.  The warning reason may be given in REASON.  */
+
+bool
+cpp_pedwarning (cpp_reader * pfile, int reason, const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic (pfile, CPP_DL_PEDWARN, reason, msgid, &ap);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a warning, including system headers.  The warning reason may be
+   given in REASON.  */
+
+bool
+cpp_warning_syshdr (cpp_reader * pfile, int reason, const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic (pfile, CPP_DL_WARNING_SYSHDR, reason, msgid, &ap);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a diagnostic at a specific location.  */
+
+ATTRIBUTE_FPTR_PRINTF(6,0)
+static bool
+cpp_diagnostic_with_line (cpp_reader * pfile, int level, int reason,
+          source_location src_loc, unsigned int column,
+          const char *msgid, va_list *ap)
+{
+  bool ret;
+  
+  if (!pfile->cb.error)
+    abort ();
+  ret = pfile->cb.error (pfile, level, reason, src_loc, column, _(msgid), ap);
+
+  return ret;
+}
+
+/* Print a warning or error, depending on the value of LEVEL.  */
+
 bool
 cpp_error_with_line (cpp_reader *pfile, int level,
      source_location src_loc, unsigned int column,
@@ -75,17 +157,77 @@ cpp_error_with_line (cpp_reader *pfile,
 {
   va_list ap;
   bool ret;
-  
+
   va_start (ap, msgid);
 
-  if (!pfile->cb.error)
-    abort ();
-  ret = pfile->cb.error (pfile, level, src_loc, column, _(msgid), &ap);
+  ret = cpp_diagnostic_with_line (pfile, level, CPP_W_NONE, src_loc,
+                                  column, msgid, &ap);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a warning.  The warning reason may be given in REASON.  */
+
+bool
+cpp_warning_with_line (cpp_reader *pfile, int reason,
+       source_location src_loc, unsigned int column,
+       const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic_with_line (pfile, CPP_DL_WARNING, reason, src_loc,
+                                  column, msgid, &ap);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a pedantic warning.  The warning reason may be given in REASON.  */
+
+bool
+cpp_pedwarning_with_line (cpp_reader *pfile, int reason,
+          source_location src_loc, unsigned int column,
+          const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic_with_line (pfile, CPP_DL_PEDWARN, reason, src_loc,
+                                  column, msgid, &ap);
 
   va_end (ap);
   return ret;
 }
 
+/* Print a warning, including system headers.  The warning reason may be
+   given in REASON.  */
+
+bool
+cpp_warning_with_line_syshdr (cpp_reader *pfile, int reason,
+              source_location src_loc, unsigned int column,
+              const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic_with_line (pfile, CPP_DL_WARNING_SYSHDR, reason, src_loc,
+                                  column, msgid, &ap);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a warning or error, depending on the value of LEVEL.  Include
+   information from errno.  */
+
 bool
 cpp_errno (cpp_reader *pfile, int level, const char *msgid)
 {
Index: libcpp/expr.c
===================================================================
--- libcpp/expr.c (revision 153497)
+++ libcpp/expr.c (working copy)
@@ -365,9 +365,9 @@ cpp_classify_number (cpp_reader *pfile,
       if (limit != str
   && CPP_WTRADITIONAL (pfile)
   && ! cpp_sys_macro_p (pfile))
- cpp_error (pfile, CPP_DL_WARNING,
-   "traditional C rejects the \"%.*s\" suffix",
-   (int) (limit - str), str);
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+     "traditional C rejects the \"%.*s\" suffix",
+     (int) (limit - str), str);
 
       /* A suffix for double is a GCC extension via decimal float support.
  If the suffix also specifies an imaginary value we'll catch that
@@ -411,21 +411,27 @@ cpp_classify_number (cpp_reader *pfile,
       if (CPP_WTRADITIONAL (pfile) && ! cpp_sys_macro_p (pfile))
  {
   int u_or_i = (result & (CPP_N_UNSIGNED|CPP_N_IMAGINARY));
-  int large = (result & CPP_N_WIDTH) == CPP_N_LARGE;
+  int large = (result & CPP_N_WIDTH) == CPP_N_LARGE
+       && CPP_OPTION (pfile, warn_long_long);
 
-  if (u_or_i || (large && CPP_OPTION (pfile, warn_long_long)))
-    cpp_error (pfile, CPP_DL_WARNING,
-       "traditional C rejects the \"%.*s\" suffix",
-       (int) (limit - str), str);
+  if (u_or_i || large)
+    cpp_warning (pfile, large ? CPP_W_LONG_LONG : CPP_W_TRADITIONAL,
+         "traditional C rejects the \"%.*s\" suffix",
+         (int) (limit - str), str);
  }
 
       if ((result & CPP_N_WIDTH) == CPP_N_LARGE
   && CPP_OPTION (pfile, warn_long_long))
- cpp_error (pfile,
-   CPP_OPTION (pfile, c99) ? CPP_DL_WARNING : CPP_DL_PEDWARN,
-   CPP_OPTION (pfile, cplusplus)
-   ? "use of C++0x long long integer constant"
-   : "use of C99 long long integer constant");
+        {
+          const char *message = CPP_OPTION (pfile, cplusplus)
+                ? "use of C++0x long long integer constant"
+                : "use of C99 long long integer constant";
+
+  if (CPP_OPTION (pfile, c99))
+            cpp_warning (pfile, CPP_W_LONG_LONG, message);
+          else
+            cpp_pedwarning (pfile, CPP_W_LONG_LONG, message);
+        }
 
       result |= CPP_N_INTEGER;
     }
@@ -786,8 +792,8 @@ eval_token (cpp_reader *pfile, const cpp
   result.high = 0;
   result.low = 0;
   if (CPP_OPTION (pfile, warn_undef) && !pfile->state.skip_eval)
-    cpp_error (pfile, CPP_DL_WARNING, "\"%s\" is not defined",
-       NODE_NAME (token->val.node.node));
+    cpp_warning (pfile, CPP_W_UNDEF, "\"%s\" is not defined",
+         NODE_NAME (token->val.node.node));
  }
       break;
 
@@ -800,8 +806,8 @@ eval_token (cpp_reader *pfile, const cpp
     cpp_error (pfile, CPP_DL_PEDWARN,
        "assertions are a GCC extension");
   else if (CPP_OPTION (pfile, warn_deprecated))
-    cpp_error (pfile, CPP_DL_WARNING,
-       "assertions are a deprecated extension");
+    cpp_warning (pfile, CPP_W_DEPRECATED,
+         "assertions are a deprecated extension");
  }
       _cpp_test_assertion (pfile, &temp);
       result.high = 0;
@@ -1496,8 +1502,8 @@ num_unary_op (cpp_reader *pfile, cpp_num
     {
     case CPP_UPLUS:
       if (CPP_WTRADITIONAL (pfile) && !pfile->state.skip_eval)
- cpp_error (pfile, CPP_DL_WARNING,
-   "traditional C rejects the unary plus operator");
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+     "traditional C rejects the unary plus operator");
       num.overflow = false;
       break;
 
Index: libcpp/lex.c
===================================================================
--- libcpp/lex.c (revision 153497)
+++ libcpp/lex.c (working copy)
@@ -301,14 +301,16 @@ _cpp_process_line_notes (cpp_reader *pfi
       && (!in_comment || warn_in_comment (pfile, note)))
     {
       if (CPP_OPTION (pfile, trigraphs))
- cpp_error_with_line (pfile, CPP_DL_WARNING, pfile->line_table->highest_line, col,
-     "trigraph ??%c converted to %c",
-     note->type,
-     (int) _cpp_trigraph_map[note->type]);
+ cpp_warning_with_line (pfile, CPP_W_TRIGRAPHS,
+                                       pfile->line_table->highest_line, col,
+       "trigraph ??%c converted to %c",
+       note->type,
+       (int) _cpp_trigraph_map[note->type]);
       else
  {
-  cpp_error_with_line
-    (pfile, CPP_DL_WARNING, pfile->line_table->highest_line, col,
+  cpp_warning_with_line
+    (pfile, CPP_W_TRIGRAPHS,
+                     pfile->line_table->highest_line, col,
      "trigraph ??%c ignored, use -trigraphs to enable",
      note->type);
  }
@@ -353,9 +355,10 @@ _cpp_skip_block_comment (cpp_reader *pfi
       && cur[0] == '*' && cur[1] != '/')
     {
       buffer->cur = cur;
-      cpp_error_with_line (pfile, CPP_DL_WARNING,
-   pfile->line_table->highest_line, CPP_BUF_COL (buffer),
-   "\"/*\" within comment");
+      cpp_warning_with_line (pfile, CPP_W_COMMENTS,
+     pfile->line_table->highest_line,
+     CPP_BUF_COL (buffer),
+     "\"/*\" within comment");
     }
  }
       else if (c == '\n')
@@ -458,11 +461,11 @@ warn_about_normalization (cpp_reader *pf
 
       sz = cpp_spell_token (pfile, token, buf, false) - buf;
       if (NORMALIZE_STATE_RESULT (s) == normalized_C)
- cpp_error_with_line (pfile, CPP_DL_WARNING, token->src_loc, 0,
-     "`%.*s' is not in NFKC", (int) sz, buf);
+ cpp_warning_with_line (pfile, CPP_W_NORMALIZE, token->src_loc, 0,
+       "`%.*s' is not in NFKC", (int) sz, buf);
       else
- cpp_error_with_line (pfile, CPP_DL_WARNING, token->src_loc, 0,
-     "`%.*s' is not in NFC", (int) sz, buf);
+ cpp_warning_with_line (pfile, CPP_W_NORMALIZE, token->src_loc, 0,
+       "`%.*s' is not in NFC", (int) sz, buf);
     }
 }
 
@@ -563,9 +566,9 @@ lex_identifier (cpp_reader *pfile, const
 
       /* For -Wc++-compat, warn about use of C++ named operators.  */
       if (result->flags & NODE_WARN_OPERATOR)
- cpp_error (pfile, CPP_DL_WARNING,
-   "identifier \"%s\" is a special operator name in C++",
-   NODE_NAME (result));
+ cpp_warning (pfile, CPP_W_CXX_OPERATOR_NAMES,
+     "identifier \"%s\" is a special operator name in C++",
+     NODE_NAME (result));
     }
 
   return result;
@@ -1373,7 +1376,7 @@ _cpp_lex_direct (cpp_reader *pfile)
     }
 
   if (skip_line_comment (pfile) && CPP_OPTION (pfile, warn_comments))
-    cpp_error (pfile, CPP_DL_WARNING, "multi-line comment");
+    cpp_warning (pfile, CPP_W_COMMENTS, "multi-line comment");
  }
       else if (c == '=')
  {
Index: libcpp/charset.c
===================================================================
--- libcpp/charset.c (revision 153497)
+++ libcpp/charset.c (working copy)
@@ -993,9 +993,9 @@ _cpp_valid_ucn (cpp_reader *pfile, const
     cpp_error (pfile, CPP_DL_WARNING,
        "universal character names are only valid in C++ and C99");
   else if (CPP_WTRADITIONAL (pfile) && identifier_pos == 0)
-    cpp_error (pfile, CPP_DL_WARNING,
-       "the meaning of '\\%c' is different in traditional C",
-       (int) str[-1]);
+    cpp_warning (pfile, CPP_W_TRADITIONAL,
+         "the meaning of '\\%c' is different in traditional C",
+         (int) str[-1]);
 
   if (str[-1] == 'u')
     length = 4;
@@ -1174,8 +1174,8 @@ convert_hex (cpp_reader *pfile, const uc
   size_t mask = width_to_mask (width);
 
   if (CPP_WTRADITIONAL (pfile))
-    cpp_error (pfile, CPP_DL_WARNING,
-       "the meaning of '\\x' is different in traditional C");
+    cpp_warning (pfile, CPP_W_TRADITIONAL,
+         "the meaning of '\\x' is different in traditional C");
 
   from++;  /* Skip 'x'.  */
   while (from < limit)
@@ -1302,8 +1302,8 @@ convert_escape (cpp_reader *pfile, const
 
     case 'a':
       if (CPP_WTRADITIONAL (pfile))
- cpp_error (pfile, CPP_DL_WARNING,
-   "the meaning of '\\a' is different in traditional C");
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+     "the meaning of '\\a' is different in traditional C");
       c = charconsts[0];
       break;
 
@@ -1522,7 +1522,7 @@ narrow_str_to_charconst (cpp_reader *pfi
  "character constant too long for its type");
     }
   else if (i > 1 && CPP_OPTION (pfile, warn_multichar))
-    cpp_error (pfile, CPP_DL_WARNING, "multi-character character constant");
+    cpp_warning (pfile, CPP_W_MULTICHAR, "multi-character character constant");
 
   /* Multichar constants are of type int and therefore signed.  */
   if (i > 1)

Re: [PATCH][RFA] Enabling -W[no-]error=... for cpplib warnings

by Joseph S. Myers :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Fri, 30 Oct 2009, Simon Baldwin wrote:

> Confirmed C/C++ dejagnu testsuite parity with the unpatched gcc, and verified
> bootstrap of C/C++ on x86_64.

C and C++ isn't enough for this patch.  Fortran uses libcpp and has an
error callback I expect you'll need to update.

> +@item -Wno-warning-directive @r{(C and Objective-C only)}

Why C and ObjC only?  Surely it should apply to C++ and ObjC++ (and
Fortran)?  And there should be at least one C++ testcase.

You're adding a lot of new diagnostic functions.  You need to update the
xgettext call in libcpp/Makefile.in to know about which arguments of these
functions should be extracted for translation (and for any changed
argument positions in existing functions), and verify that rebuilding
cpplib.pot doesn't lose any messages in it; cpplib doesn't have the
automatic identification of *msgid arguments that the gcc/ directory does.

> - cpp_error (pfile,
> -   CPP_OPTION (pfile, c99) ? CPP_DL_WARNING : CPP_DL_PEDWARN,
> -   CPP_OPTION (pfile, cplusplus)
> -   ? "use of C++0x long long integer constant"
> -   : "use of C99 long long integer constant");
> +        {
> +          const char *message = CPP_OPTION (pfile, cplusplus)
> +                ? "use of C++0x long long integer constant"
> +                : "use of C99 long long integer constant";
> +
> +  if (CPP_OPTION (pfile, c99))
> +            cpp_warning (pfile, CPP_W_LONG_LONG, message);
> +          else
> +            cpp_pedwarning (pfile, CPP_W_LONG_LONG, message);

This would mean an i18n regression; at least the first of the two messages
in the call to cpp_error gets extracted now, even if the second doesn't.  
Wrap both string constants in N_() so they get extracted for translation.

--
Joseph S. Myers
joseph@...

Re: [PATCH][RFA] Enabling -W[no-]error=... for cpplib warnings

by Simon Baldwin-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Thank you for the review -- inlined responses below.

I've attached a revised and corrected version of the patch to the
mail; bootstrap C/C++/Fortran and appropriate suite re-done.  Please
take a second look.  Thanks.


2009/10/30 Joseph S. Myers <joseph@...>
>
> On Fri, 30 Oct 2009, Simon Baldwin wrote:
>
> > Confirmed C/C++ dejagnu testsuite parity with the unpatched gcc, and verified
> > bootstrap of C/C++ on x86_64.
>
> C and C++ isn't enough for this patch.  Fortran uses libcpp and has an
> error callback I expect you'll need to update.

Thanks for the note.

I've added Fortran support for -Wno-warning-directives.  Fortran
doesn't have the, er... rich support for -W flags in C and C++ so it
doesn't seem to make sense to try to add all the others at this point.


> > +@item -Wno-warning-directive @r{(C and Objective-C only)}
>
> Why C and ObjC only?  Surely it should apply to C++ and ObjC++ (and
> Fortran)?  And there should be at least one C++ testcase.

Revised the documentation to include the C++es and Fortran, added
smoke-test testcases for C++ and Fortran.


> You're adding a lot of new diagnostic functions.  You need to update the
> xgettext call in libcpp/Makefile.in to know about which arguments of these
> functions should be extracted for translation (and for any changed
> argument positions in existing functions), and verify that rebuilding
> cpplib.pot doesn't lose any messages in it; cpplib doesn't have the
> automatic identification of *msgid arguments that the gcc/ directory does.

Thanks for the pointer here; I'd missed this.  libcpp/Makefile.in
revised for the new diagnostic functions, and N_() added in where
required.

I've rebuilt cpplib.pot and verified both that no messages were
dropped, and that "use of C99 long long integer constant", which was
missing from translations before this patch, is now picked up by N_().


>
> > -     cpp_error (pfile,
> > -                CPP_OPTION (pfile, c99) ? CPP_DL_WARNING : CPP_DL_PEDWARN,
> > -                CPP_OPTION (pfile, cplusplus)
> > -                ? "use of C++0x long long integer constant"
> > -                : "use of C99 long long integer constant");
> > +        {
> > +          const char *message = CPP_OPTION (pfile, cplusplus)
> > +                             ? "use of C++0x long long integer constant"
> > +                             : "use of C99 long long integer constant";
> > +
> > +       if (CPP_OPTION (pfile, c99))
> > +            cpp_warning (pfile, CPP_W_LONG_LONG, message);
> > +          else
> > +            cpp_pedwarning (pfile, CPP_W_LONG_LONG, message);
>
> This would mean an i18n regression; at least the first of the two messages
> in the call to cpp_error gets extracted now, even if the second doesn't.
> Wrap both string constants in N_() so they get extracted for translation.
Thanks.  Done -- see above.

--
Google UK Limited | Registered Office: Belgrave House, 76 Buckingham
Palace Road, London SW1W 9TQ | Registered in England Number: 3977902

[cpp_warnings.patch]

This patch brings several preprocessor warnings under the control of the
-Werror= gcc flag.  At present, gcc does not associate preprocessor warnings
with gcc command line options, and so such warnings cannot be controlled
individually with -Werror=.

With the patch in place, preprocessor warnings can now be set separately as
errors with -Werror=, disabled as errors with -Wno-error=, and will report
their corresponding gcc diagnostic flag with -fdiagnostics-show-option when
requested.

The patch also adds a new gcc option -W[no-]warning-directive so that the
output of #warning operates symmetrically to other gcc warnings, and in
particular so that the combination "-Werror -Wno-error=warning-directive"
allows all warnings except for #warning directives to be treated as errors.

Confirmed C, C++ and Fortran dejagnu testsuite parity with the unpatched gcc,
and verified bootstrap of C/C++/Fortran on x86_64.


gcc/ChangeLog:
2009-11-02  Simon Baldwin  <simonb@...>

        * diagnostic.h (diagnostic_override_option_index): New macro to
        set a diagnostic's option_index.
        * c-tree.h (c_cpp_error): Add warning reason argument.
        * opts.c (_warning_as_error_callback): New.
        (register_warning_as_error_callback): Store callback for
        warnings enabled via enable_warning_as_error.
        (enable_warning_as_error): Call callback, minor code tidy.
        * opts.h (register_warning_as_error_callback): Declare.
        * c-opts.c (warning_as_error_callback): New, set cpp_opts flag in
        response to -Werror=.
        (c_common_init_options): Register warning_as_error_callback in opts.c.
        * common.opt: Add -Wno-warning-directive option.
        * c-common.c (struct reason_option_codes_t): Map cpp warning
        reason codes to gcc option indexes.
        * (c_option_controlling_cpp_error): New function, lookup the gcc
        option index for a cpp warning reason code.
        * (c_cpp_error): Add warning reason argument, call
        c_option_controlling_cpp_error for diagnostic_override_option_index.
        * doc/invoke.texi: Document -Wno-warning-directive.

gcc/fortran/ChangeLog:
2009-11-02  Simon Baldwin  <simonb@...>

        * cpp.c (cb_cpp_error): Add warning reason argument, set a value
        for diagnostic_override_option_index if CPP_W_WARNING_DIRECTIVE.

libcpp/ChangeLog:
2009-11-02  Simon Baldwin  <simonb@...>

        * directives.c (do_diagnostic): Add warning reason argument,
        call appropriate error reporting function for code.
        (directive_diagnostics): Call specific warning functions with
        warning reason where appropriate.
        (do_error, do_warning, do_pragma_dependency): Add warning reason
        argument to do_diagnostic calls.
        * macro.c (_cpp_warn_if_unused_macro, enter_macro_context,
        _cpp_create_definition): Call specific warning functions with
        warning reason where appropriate.
        * Makefile.in: Add new diagnostic functions to gettext translations.
        * include/cpplib.h (struct cpp_callbacks): Add warning reason code
        to error callback.
        (CPP_DL_WARNING, CPP_DL_WARNING_SYSHDR, CPP_DL_PEDWARN, CPP_DL_ERROR,
        CPP_DL_ICE, CPP_DL_NOTE, CPP_DL_FATAL): Replace macros with enums.
        (CPP_W_NONE, CPP_W_DEPRECATED, CPP_W_COMMENTS,
        CPP_W_MISSING_INCLUDE_DIRS, CPP_W_TRIGRAPHS, CPP_W_MULTICHAR,
        CPP_W_TRADITIONAL, CPP_W_LONG_LONG, CPP_W_ENDIF_LABELS,
        CPP_W_NUM_SIGN_CHANGE, CPP_W_VARIADIC_MACROS,
        CPP_W_BUILTIN_MACRO_REDEFINED, CPP_W_DOLLARS, CPP_W_UNDEF,
        CPP_W_UNUSED_MACROS, CPP_W_CXX_OPERATOR_NAMES, CPP_W_NORMALIZE,
        CPP_W_INVALID_PCH, CPP_W_WARNING_DIRECTIVE): New enums for cpp
        warning reason codes.
        (cpp_warning, cpp_pedwarning, cpp_warning_syshdr,
        cpp_warning_with_line, cpp_pedwarning_with_line,
        cpp_warning_with_line_syshdr): New specific error reporting functions.
        * pch.c (cpp_valid_state): Call specific warning functions with
        warning reason where appropriate.
        * errors.c (cpp_diagnostic, cpp_diagnostic_with_line): New central
        diagnostic handlers.
        (cpp_warning, cpp_pedwarning, cpp_warning_syshdr,
        cpp_warning_with_line, cpp_pedwarning_with_line,
        cpp_warning_with_line_syshdr): New specific error reporting functions.
        * expr.c (cpp_classify_number, eval_token, num_unary_op): Call
        specific warning functions with warning reason where appropriate.
        * lex.c (_cpp_process_line_notes, _cpp_skip_block_comment,
        warn_about_normalization, lex_identifier, _cpp_lex_direct): Ditto.
        * charset.c (_cpp_valid_ucn, convert_hex, convert_escape,
        narrow_str_to_charconst): Ditto.

gcc/testsuite/ChangeLog:
2009-11-02  Simon Baldwin  <simonb@...>

        * gcc.dg/cpp/warn-undef-2.c: New.
        * gcc.dg/cpp/warn-traditional-2.c: New.
        * gcc.dg/cpp/warn-comments-2.c: New.
        * gcc.dg/cpp/warning-directive-1.c: New.
        * gcc.dg/cpp/warn-long-long.c: New.
        * gcc.dg/cpp/warn-traditional.c: New.
        * gcc.dg/cpp/warn-variadic-2.c: New.
        * gcc.dg/cpp/warn-undef.c: New.
        * gcc.dg/cpp/warn-normalized-1.c: New.
        * gcc.dg/cpp/warning-directive-2.c: New.
        * gcc.dg/cpp/warn-long-long-2.c: New.
        * gcc.dg/cpp/warn-variadic.c: New.
        * gcc.dg/cpp/warn-normalized-2.c: New.
        * gcc.dg/cpp/warning-directive-3.c: New.
        * gcc.dg/cpp/warn-deprecated-2.c: New.
        * gcc.dg/cpp/warn-trigraphs-1.c: New.
        * gcc.dg/cpp/warn-multichar-2.c: New.
        * gcc.dg/cpp/warn-normalized-3.c: New.
        * gcc.dg/cpp/warning-directive-4.c: New.
        * gcc.dg/cpp/warn-unused-macros.c: New.
        * gcc.dg/cpp/warn-trigraphs-2.c: New.
        * gcc.dg/cpp/warn-cxx-compat-2.c: New.
        * gcc.dg/cpp/warn-cxx-compat.c: New.
        * gcc.dg/cpp/warn-redefined.c: New.
        * gcc.dg/cpp/warn-trigraphs-3.c: New.
        * gcc.dg/cpp/warn-unused-macros-2.c: New.
        * gcc.dg/cpp/warn-deprecated.c: New.
        * gcc.dg/cpp/warn-trigraphs-4.c: New.
        * gcc.dg/cpp/warn-redefined-2.c: New.
        * gcc.dg/cpp/warn-comments.c: New.
        * gcc.dg/cpp/warn-multichar.c: New.
        * g++.dg/cpp/warning-directive-1.C: New.
        * g++.dg/cpp/warning-directive-2.C: New.
        * g++.dg/cpp/warning-directive-3.C: New.
        * g++.dg/cpp/warning-directive-4.C: New.
        * gfortran.dg/warning-directive-1.F90: New.
        * gfortran.dg/warning-directive-3.F90: New.
        * gfortran.dg/warning-directive-2.F90: New.
        * gfortran.dg/warning-directive-4.F90: New.


Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi (revision 153803)
+++ gcc/doc/invoke.texi (working copy)
@@ -263,7 +263,7 @@ Objective-C and Objective-C++ Dialects}.
 -Wunsuffixed-float-constants  -Wunused  -Wunused-function @gol
 -Wunused-label  -Wunused-parameter -Wno-unused-result -Wunused-value  -Wunused-variable @gol
 -Wvariadic-macros -Wvla @gol
--Wvolatile-register-var  -Wwrite-strings}
+-Wvolatile-register-var  -Wwarning-directive  -Wwrite-strings}
 
 @item C and Objective-C-only Warning Options
 @gccoptlist{-Wbad-function-cast  -Wmissing-declarations @gol
@@ -4340,6 +4340,11 @@ a suffix.  When used together with @opti
 warn about such constants in system header files.  This can be useful
 when preparing code to use with the @code{FLOAT_CONST_DECIMAL64} pragma
 from the decimal floating-point extension to C99.
+
+@item -Wno-warning-directive \
+@r{(C, Objective-C, C++, Objective-C++ and Fortran only)}
+
+Suppress warning messages emitted by @code{#warning} directives.
 @end table
 
 @node Debugging Options
Index: gcc/diagnostic.h
===================================================================
--- gcc/diagnostic.h (revision 153803)
+++ gcc/diagnostic.h (working copy)
@@ -190,6 +190,11 @@ extern diagnostic_context *global_dc;
    diagnostic.  */
 #define diagnostic_override_column(DI, COL) (DI)->override_column = (COL)
 
+/* Override the option index to be used for reporting a
+   diagnostic.  */
+#define diagnostic_override_option_index(DI, OPTIDX) \
+    (DI)->option_index = (OPTIDX)
+
 /* Diagnostic related functions.  */
 extern void diagnostic_initialize (diagnostic_context *);
 extern void diagnostic_report_current_module (diagnostic_context *);
Index: gcc/testsuite/gcc.dg/cpp/warn-undef-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-undef-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-undef-2.c (revision 0)
@@ -0,0 +1,5 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=undef" }
+
+#if x  // { dg-error "\"x\" is not defined .-Wundef." }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-traditional-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-traditional-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-traditional-2.c (revision 0)
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=traditional -Wno-deprecated -Wno-long-long" }
+
+#assert x(x)         // { dg-error "suggest hiding #assert from traditional C with an indented # .-Wtraditional." }
+
+ #define X X         // { dg-error "traditional C ignores #define with the # indented .-Wtraditional." }
+
+#if 0
+#elif 1              // { dg-error "suggest not using #elif in traditional C .-Wtraditional." }
+#endif
+
+#define f(X) X
+int f;               // { dg-error "function-like macro \"f\" must be used with arguments in traditional C .-Wtraditional." }
+
+#if 0U               // { dg-error "traditional C rejects the \"U\" suffix .-Wtraditional." }
+#endif
+
+#if +1               // { dg-error " traditional C rejects the unary plus operator .-Wtraditional." }
+#endif
+
+char *x = "\x0";     // { dg-error "the meaning of '.x' is different in traditional C .-Wtraditional." }
+char *y = "\a";      // { dg-error "the meaning of '.a' is different in traditional C .-Wtraditional." }
+char *z = "\u0F43";  // { dg-error "the meaning of '.u' is different in traditional C .-Wtraditional." }
Index: gcc/testsuite/gcc.dg/cpp/warn-comments-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-comments-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-comments-2.c (revision 0)
@@ -0,0 +1,7 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=comments" }
+
+/* /* */  // { dg-error "\"\.\*\" within comment .-Wcomments." }
+
+// \
+          // { dg-error "multi-line comment .-Wcomments." "multi-line" { target *-*-* } 6 }
Index: gcc/testsuite/gcc.dg/cpp/warning-directive-1.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warning-directive-1.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warning-directive-1.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option" }
+
+#warning "Printed"  // { dg-warning "\"Printed\" .-Wwarning-directive." }
Index: gcc/testsuite/gcc.dg/cpp/warn-long-long.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-long-long.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-long-long.c (revision 0)
@@ -0,0 +1,6 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wtraditional -Wlong-long" }
+
+#if 0LL  // { dg-warning "traditional C rejects the \"LL\" suffix .-Wlong-long." }
+         // { dg-warning "use of C99 long long integer constant .-Wlong-long." "use long long" { target *-*-* } 4 }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-traditional.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-traditional.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-traditional.c (revision 0)
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wtraditional -Wno-deprecated -Wno-long-long" }
+
+#assert x(x)         // { dg-warning "suggest hiding #assert from traditional C with an indented # .-Wtraditional." }
+
+ #define X X         // { dg-warning "traditional C ignores #define with the # indented .-Wtraditional." }
+
+#if 0
+#elif 1              // { dg-warning "suggest not using #elif in traditional C .-Wtraditional." }
+#endif
+
+#define f(X) X
+int f;               // { dg-warning "function-like macro \"f\" must be used with arguments in traditional C .-Wtraditional." }
+
+#if 0U               // { dg-warning "traditional C rejects the \"U\" suffix .-Wtraditional." }
+#endif
+
+#if +1               // { dg-warning " traditional C rejects the unary plus operator .-Wtraditional." }
+#endif
+
+char *x = "\x0";     // { dg-warning "the meaning of '.x' is different in traditional C .-Wtraditional." }
+char *y = "\a";      // { dg-warning "the meaning of '.a' is different in traditional C .-Wtraditional." }
+char *z = "\u0F43";  // { dg-warning "the meaning of '.u' is different in traditional C .-Wtraditional." }
Index: gcc/testsuite/gcc.dg/cpp/warn-variadic-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-variadic-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-variadic-2.c (revision 0)
@@ -0,0 +1,6 @@
+/* { dg-do preprocess } */
+/* { dg-options "-ansi -fdiagnostics-show-option -pedantic -Werror=variadic-macros" } */
+
+#define F(...) X   /* { dg-error "anonymous variadic macros were introduced in C99 .-Wvariadic-macros." } */
+
+#define G(X...) X  /* { dg-error "ISO C does not permit named variadic macros .-Wvariadic-macros." } */
Index: gcc/testsuite/gcc.dg/cpp/warn-undef.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-undef.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-undef.c (revision 0)
@@ -0,0 +1,5 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wundef" }
+
+#if x  // { dg-warning "\"x\" is not defined .-Wundef." }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-normalized-1.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-normalized-1.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-normalized-1.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -fextended-identifiers -Wnormalized=nfc" }
+
+\u0F43  // { dg-warning "`.U00000f43' is not in NFC .-Wnormalized=." }
Index: gcc/testsuite/gcc.dg/cpp/warning-directive-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warning-directive-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warning-directive-2.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=warning-directive" }
+
+#warning "Printed"  // { dg-error "\"Printed\" .-Wwarning-directive." }
Index: gcc/testsuite/gcc.dg/cpp/warn-long-long-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-long-long-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-long-long-2.c (revision 0)
@@ -0,0 +1,6 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wtraditional -Werror=long-long" }
+
+#if 0LL  // { dg-error "traditional C rejects the \"LL\" suffix .-Wlong-long." }
+         // { dg-error "use of C99 long long integer constant .-Wlong-long." "use long long" { target *-*-* } 4 }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-variadic.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-variadic.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-variadic.c (revision 0)
@@ -0,0 +1,6 @@
+/* { dg-do preprocess } */
+/* { dg-options "-ansi -fdiagnostics-show-option -pedantic -Wvariadic-macros" } */
+
+#define F(...) X   /* { dg-warning "anonymous variadic macros were introduced in C99 .-Wvariadic-macros." } */
+
+#define G(X...) X  /* { dg-warning "ISO C does not permit named variadic macros .-Wvariadic-macros." } */
Index: gcc/testsuite/gcc.dg/cpp/warn-normalized-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-normalized-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-normalized-2.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -fextended-identifiers -Wnormalized=nfkc" }
+
+\u00AA  // { dg-warning "`.U000000aa' is not in NFKC .-Wnormalized=." }
Index: gcc/testsuite/gcc.dg/cpp/warning-directive-3.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warning-directive-3.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warning-directive-3.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror -Wno-error=warning-directive" }
+
+#warning "Printed"  // { dg-warning "\"Printed\" .-Wwarning-directive." }
Index: gcc/testsuite/gcc.dg/cpp/warn-deprecated-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-deprecated-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-deprecated-2.c (revision 0)
@@ -0,0 +1,7 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=deprecated" }
+
+#assert x(x)  // { dg-error "#assert is a deprecated GCC extension .-Wdeprecated." }
+
+#if #x(x)     // { dg-error "assertions are a deprecated extension .-Wdeprecated." }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-trigraphs-1.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-trigraphs-1.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-trigraphs-1.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -trigraphs -Wtrigraphs" }
+
+??=  // { dg-warning "trigraph \\?\\?= converted to # .-Wtrigraphs." }
Index: gcc/testsuite/gcc.dg/cpp/warn-multichar-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-multichar-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-multichar-2.c (revision 0)
@@ -0,0 +1,5 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=multichar" }
+
+#if 'abc'  // { dg-error "multi-character character constant .-Wmultichar." }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-normalized-3.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-normalized-3.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-normalized-3.c (revision 0)
@@ -0,0 +1,5 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -fextended-identifiers -Werror=normalized=" }
+
+        // { dg-prune-output ".*-Werror=normalized=: Set -Wnormalized=nfc.*" }
+\u0F43  // { dg-error "`.U00000f43' is not in NFC .-Wnormalized=." }
Index: gcc/testsuite/gcc.dg/cpp/warning-directive-4.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warning-directive-4.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warning-directive-4.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wno-warning-directive" }
+
+#warning "Not printed"  // { dg-bogus "." }
Index: gcc/testsuite/gcc.dg/cpp/warn-unused-macros.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-unused-macros.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-unused-macros.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wunused-macros" }
+
+#define X X  // { dg-warning "macro \"X\" is not used .-Wunused-macros." }
Index: gcc/testsuite/gcc.dg/cpp/warn-trigraphs-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-trigraphs-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-trigraphs-2.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wtrigraphs" }
+
+??=  // { dg-warning "trigraph \\?\\?= ignored, use -trigraphs to enable .-Wtrigraphs." }
Index: gcc/testsuite/gcc.dg/cpp/warn-cxx-compat-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-cxx-compat-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-cxx-compat-2.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=c++-compat" }
+
+#define not !  // { dg-error "identifier \"not\" is a special operator name in C\\+\\+ .-Wc\\+\\+-compat." }
Index: gcc/testsuite/gcc.dg/cpp/warn-cxx-compat.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-cxx-compat.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-cxx-compat.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wc++-compat" }
+
+#define not !  // { dg-warning "identifier \"not\" is a special operator name in C\\+\\+ .-Wc\\+\\+-compat." }
Index: gcc/testsuite/gcc.dg/cpp/warn-redefined.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-redefined.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-redefined.c (revision 0)
@@ -0,0 +1,18 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wbuiltin-macro-redefined" }
+
+#ifndef __TIME__
+#error "__TIME__ builtin is not defined"
+// { dg-bogus "__TIME__ builtin is not defined" "no-time" { target *-*-* } 5 }
+#endif
+
+#define __TIME__ "X"  // { dg-warning "\"__TIME__\" redefined .-Wbuiltin-macro-redefined." }
+
+#define __TIME__ "Y"  // { dg-bogus "-Wbuiltin-macro-redefined" }
+                      // { dg-warning "\"__TIME__\" redefined" "not-builtin-1" { target *-*-* } 11 }
+                      // { dg-message "previous definition" "previous-1" { target *-*-* } 9 }
+
+#define X "X"
+#define X "Y"         // { dg-bogus "-Wbuiltin-macro-redefined" }
+                      // { dg-warning "\"X\" redefined" "not-builtin-2" { target *-*-* } 16 }
+                      // { dg-message "previous definition" "previous-2" { target *-*-* } 15 }
Index: gcc/testsuite/gcc.dg/cpp/warn-trigraphs-3.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-trigraphs-3.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-trigraphs-3.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -trigraphs -Werror=trigraphs" }
+
+??=  // { dg-error "trigraph \\?\\?= converted to # .-Wtrigraphs." }
Index: gcc/testsuite/gcc.dg/cpp/warn-unused-macros-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-unused-macros-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-unused-macros-2.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=unused-macros" }
+
+#define X X  // { dg-error "macro \"X\" is not used .-Wunused-macros." }
Index: gcc/testsuite/gcc.dg/cpp/warn-deprecated.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-deprecated.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-deprecated.c (revision 0)
@@ -0,0 +1,7 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wdeprecated" }
+
+#assert x(x)  // { dg-warning "#assert is a deprecated GCC extension .-Wdeprecated." }
+
+#if #x(x)     // { dg-warning "assertions are a deprecated extension .-Wdeprecated." }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-trigraphs-4.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-trigraphs-4.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-trigraphs-4.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=trigraphs" }
+
+??=  // { dg-error "trigraph \\?\\?= ignored, use -trigraphs to enable .-Wtrigraphs." }
Index: gcc/testsuite/gcc.dg/cpp/warn-redefined-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-redefined-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-redefined-2.c (revision 0)
@@ -0,0 +1,18 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=builtin-macro-redefined" }
+
+#ifndef __TIME__
+#error "__TIME__ builtin is not defined"
+// { dg-bogus "__TIME__ builtin is not defined" "no-time" { target *-*-* } 5 }
+#endif
+
+#define __TIME__ "X"  // { dg-error "\"__TIME__\" redefined .-Wbuiltin-macro-redefined." }
+
+#define __TIME__ "Y"  // { dg-bogus "-Wbuiltin-macro-redefined" }
+                      // { dg-warning "\"__TIME__\" redefined" "not-builtin-1" { target *-*-* } 11 }
+                      // { dg-message "previous definition" "previous-1" { target *-*-* } 9 }
+
+#define X "X"
+#define X "Y"         // { dg-bogus "-Wbuiltin-macro-redefined" }
+                      // { dg-warning "\"X\" redefined" "not-builtin-2" { target *-*-* } 16 }
+                      // { dg-message "previous definition" "previous-2" { target *-*-* } 15 }
Index: gcc/testsuite/gcc.dg/cpp/warn-comments.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-comments.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-comments.c (revision 0)
@@ -0,0 +1,7 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wcomments" }
+
+/* /* */  // { dg-warning "\"\.\*\" within comment .-Wcomments." }
+
+// \
+          // { dg-warning "multi-line comment .-Wcomments." "multi-line" { target *-*-* } 6 }
Index: gcc/testsuite/gcc.dg/cpp/warn-multichar.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-multichar.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-multichar.c (revision 0)
@@ -0,0 +1,5 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wmultichar" }
+
+#if 'abc'  // { dg-warning "multi-character character constant .-Wmultichar." }
+#endif
Index: gcc/testsuite/g++.dg/cpp/warning-directive-1.C
===================================================================
--- gcc/testsuite/g++.dg/cpp/warning-directive-1.C (revision 0)
+++ gcc/testsuite/g++.dg/cpp/warning-directive-1.C (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-fdiagnostics-show-option" }
+
+#warning "Printed"  // { dg-warning "\"Printed\" .-Wwarning-directive." }
Index: gcc/testsuite/g++.dg/cpp/warning-directive-2.C
===================================================================
--- gcc/testsuite/g++.dg/cpp/warning-directive-2.C (revision 0)
+++ gcc/testsuite/g++.dg/cpp/warning-directive-2.C (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-fdiagnostics-show-option -Werror=warning-directive" }
+
+#warning "Printed"  // { dg-error "\"Printed\" .-Wwarning-directive." }
Index: gcc/testsuite/g++.dg/cpp/warning-directive-3.C
===================================================================
--- gcc/testsuite/g++.dg/cpp/warning-directive-3.C (revision 0)
+++ gcc/testsuite/g++.dg/cpp/warning-directive-3.C (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-fdiagnostics-show-option -Werror -Wno-error=warning-directive" }
+
+#warning "Printed"  // { dg-warning "\"Printed\" .-Wwarning-directive." }
Index: gcc/testsuite/g++.dg/cpp/warning-directive-4.C
===================================================================
--- gcc/testsuite/g++.dg/cpp/warning-directive-4.C (revision 0)
+++ gcc/testsuite/g++.dg/cpp/warning-directive-4.C (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-fdiagnostics-show-option -Wno-warning-directive" }
+
+#warning "Not printed"  // { dg-bogus "." }
Index: gcc/testsuite/gfortran.dg/warning-directive-1.F90
===================================================================
--- gcc/testsuite/gfortran.dg/warning-directive-1.F90 (revision 0)
+++ gcc/testsuite/gfortran.dg/warning-directive-1.F90 (revision 0)
@@ -0,0 +1,5 @@
+! { dg-do preprocess }
+! { dg-options "-std=f95 -fdiagnostics-show-option" }
+
+#warning "Printed"
+! { dg-warning "\"Printed\" .-Wwarning-directive." "" { target *-*-* } 4 }
Index: gcc/testsuite/gfortran.dg/warning-directive-3.F90
===================================================================
--- gcc/testsuite/gfortran.dg/warning-directive-3.F90 (revision 0)
+++ gcc/testsuite/gfortran.dg/warning-directive-3.F90 (revision 0)
@@ -0,0 +1,5 @@
+! { dg-do preprocess }
+! { dg-options "-std=f95 -fdiagnostics-show-option -Werror -Wno-error=warning-directive" }
+
+#warning "Printed"
+! { dg-warning "\"Printed\" .-Wwarning-directive." "" { target *-*-* } 4 }
Index: gcc/testsuite/gfortran.dg/warning-directive-2.F90
===================================================================
--- gcc/testsuite/gfortran.dg/warning-directive-2.F90 (revision 0)
+++ gcc/testsuite/gfortran.dg/warning-directive-2.F90 (revision 0)
@@ -0,0 +1,5 @@
+! { dg-do preprocess }
+! { dg-options "-std=f95 -fdiagnostics-show-option -Werror=warning-directive" }
+
+#warning "Printed"
+! { dg-error "\"Printed\" .-Wwarning-directive." "" { target *-*-* } 4 }
Index: gcc/testsuite/gfortran.dg/warning-directive-4.F90
===================================================================
--- gcc/testsuite/gfortran.dg/warning-directive-4.F90 (revision 0)
+++ gcc/testsuite/gfortran.dg/warning-directive-4.F90 (revision 0)
@@ -0,0 +1,5 @@
+! { dg-do preprocess }
+! { dg-options "-std=f95 -fdiagnostics-show-option -Wno-warning-directive" }
+
+#warning "Not printed"
+! { dg-bogus "." "" { target *-*-* } 4 }
Index: gcc/c-tree.h
===================================================================
--- gcc/c-tree.h (revision 153803)
+++ gcc/c-tree.h (working copy)
@@ -608,8 +608,8 @@ extern void c_write_global_declarations
 extern void pedwarn_c90 (location_t, int opt, const char *, ...) ATTRIBUTE_GCC_CDIAG(3,4);
 extern void pedwarn_c99 (location_t, int opt, const char *, ...) ATTRIBUTE_GCC_CDIAG(3,4);
 
-extern bool c_cpp_error (cpp_reader *, int, location_t, unsigned int,
+extern bool c_cpp_error (cpp_reader *, int, int, location_t, unsigned int,
  const char *, va_list *)
-     ATTRIBUTE_GCC_CDIAG(5,0);
+     ATTRIBUTE_GCC_CDIAG(6,0);
 
 #endif /* ! GCC_C_TREE_H */
Index: gcc/opts.c
===================================================================
--- gcc/opts.c (revision 153803)
+++ gcc/opts.c (working copy)
@@ -2364,6 +2364,19 @@ set_option (const struct cl_option *opti
     }
 }
 
+
+/* Callback function, called when -Werror= enables a warning.  */
+
+static void (*warning_as_error_callback) (int) = NULL;
+
+/* Register a callback for enable_warning_as_error calls.  */
+
+void
+register_warning_as_error_callback (void (*callback) (int))
+{
+  warning_as_error_callback = callback;
+}
+
 /* Enable a warning option as an error.  This is used by -Werror= and
    also by legacy Werror-implicit-function-declaration.  */
 
@@ -2383,14 +2396,20 @@ enable_warning_as_error (const char *arg
     }
   else
     {
-      diagnostic_t kind = value ? DK_ERROR : DK_WARNING;
+      const diagnostic_t kind = value ? DK_ERROR : DK_WARNING;
+
       diagnostic_classify_diagnostic (global_dc, option_index, kind);
-      
-      /* -Werror=foo implies -Wfoo.  */
-      if (cl_options[option_index].var_type == CLVC_BOOLEAN
-  && cl_options[option_index].flag_var
-  && kind == DK_ERROR)
- *(int *) cl_options[option_index].flag_var = 1;
+      if (kind == DK_ERROR)
+        {
+  const struct cl_option * const option = cl_options + option_index;
+
+  /* -Werror=foo implies -Wfoo.  */
+  if (option->var_type == CLVC_BOOLEAN && option->flag_var)
+    *(int *) option->flag_var = 1;
+
+  if (warning_as_error_callback)
+    warning_as_error_callback (option_index);
+ }
     }
   free (new_option);
 }
Index: gcc/opts.h
===================================================================
--- gcc/opts.h (revision 153803)
+++ gcc/opts.h (working copy)
@@ -105,6 +105,7 @@ extern int option_enabled (int opt_idx);
 extern bool get_option_state (int, struct cl_option_state *);
 extern void set_option (const struct cl_option *, int, const char *);
 
+extern void register_warning_as_error_callback (void (*callback) (int));
 extern void enable_warning_as_error (const char *arg, int value,
      unsigned int lang_mask);
 extern void print_ignored_options (void);
Index: gcc/fortran/cpp.c
===================================================================
--- gcc/fortran/cpp.c (revision 153803)
+++ gcc/fortran/cpp.c (working copy)
@@ -137,9 +137,9 @@ static void cb_include (cpp_reader *, so
 static void cb_ident (cpp_reader *, source_location, const cpp_string *);
 static void cb_used_define (cpp_reader *, source_location, cpp_hashnode *);
 static void cb_used_undef (cpp_reader *, source_location, cpp_hashnode *);
-static bool cb_cpp_error (cpp_reader *, int, location_t, unsigned int,
+static bool cb_cpp_error (cpp_reader *, int, int, location_t, unsigned int,
   const char *, va_list *)
-     ATTRIBUTE_GCC_DIAG(5,0);
+     ATTRIBUTE_GCC_DIAG(6,0);
 void pp_dir_change (cpp_reader *, const char *);
 
 static int dump_macro (cpp_reader *, cpp_hashnode *, void *);
@@ -962,13 +962,14 @@ cb_used_define (cpp_reader *pfile, sourc
 }
 
 /* Callback from cpp_error for PFILE to print diagnostics from the
-   preprocessor.  The diagnostic is of type LEVEL, at location
+   preprocessor.  The diagnostic is of type LEVEL, with REASON set
+   to the reason code if LEVEL is represents a warning, at location
    LOCATION, with column number possibly overridden by COLUMN_OVERRIDE
    if not zero; MSG is the translated message and AP the arguments.
    Returns true if a diagnostic was emitted, false otherwise.  */
 
 static bool
-cb_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level,
+cb_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason,
       location_t location, unsigned int column_override,
       const char *msg, va_list *ap)
 {
@@ -1007,6 +1008,8 @@ cb_cpp_error (cpp_reader *pfile ATTRIBUT
   location, dlevel);
   if (column_override)
     diagnostic_override_column (&diagnostic, column_override);
+  if (reason == CPP_W_WARNING_DIRECTIVE)
+    diagnostic_override_option_index (&diagnostic, OPT_Wwarning_directive);
   ret = report_diagnostic (&diagnostic);
   if (level == CPP_DL_WARNING_SYSHDR)
     warn_system_headers = save_warn_system_headers;
Index: gcc/c-opts.c
===================================================================
--- gcc/c-opts.c (revision 153803)
+++ gcc/c-opts.c (working copy)
@@ -196,6 +196,90 @@ defer_opt (enum opt_code code, const cha
   deferred_count++;
 }
 
+/* -Werror= may set a warning option to enable a warning that is emitted
+   by the preprocessor.  Set any corresponding flag in cpp_opts.  */
+
+static void
+warning_as_error_callback (int option_index)
+{
+  switch (option_index)
+    {
+      default:
+ /* Ignore options not associated with the preprocessor.  */
+ break;
+
+      case OPT_Wdeprecated:
+ cpp_opts->warn_deprecated = 1;
+ break;
+
+      case OPT_Wcomment:
+      case OPT_Wcomments:
+ cpp_opts->warn_comments = 1;
+ break;
+
+      case OPT_Wtrigraphs:
+ cpp_opts->warn_trigraphs = 1;
+ break;
+
+      case OPT_Wmultichar:
+ cpp_opts->warn_multichar = 1;
+ break;
+
+      case OPT_Wtraditional:
+ cpp_opts->warn_traditional = 1;
+ break;
+
+      case OPT_Wlong_long:
+ cpp_opts->warn_long_long = 1;
+ break;
+
+      case OPT_Wendif_labels:
+ cpp_opts->warn_endif_labels = 1;
+ break;
+
+      case OPT_Wvariadic_macros:
+ /* Set the local flag that is used later to update cpp_opts.  */
+ warn_variadic_macros = 1;
+ break;
+
+      case OPT_Wbuiltin_macro_redefined:
+ cpp_opts->warn_builtin_macro_redefined = 1;
+ break;
+
+      case OPT_Wundef:
+ cpp_opts->warn_undef = 1;
+ break;
+
+      case OPT_Wunused_macros:
+ /* Set the local flag that is used later to update cpp_opts.  */
+ warn_unused_macros = 1;
+ break;
+
+      case OPT_Wc___compat:
+ /* Add warnings in the same way as c_common_handle_option below.  */
+ if (warn_enum_compare == -1)
+  warn_enum_compare = 1;
+ if (warn_jump_misses_init == -1)
+  warn_jump_misses_init = 1;
+ cpp_opts->warn_cxx_operator_names = 1;
+ break;
+
+      case OPT_Wnormalized_:
+ inform (input_location, "-Werror=normalized=: Set -Wnormalized=nfc");
+ cpp_opts->warn_normalize = normalized_C;
+ break;
+
+      case OPT_Winvalid_pch:
+ cpp_opts->warn_invalid_pch = 1;
+ break;
+
+      case OPT_Wwarning_directive:
+ /* Handled by standard diagnostics using the option's associated
+   boolean variable.  */
+ break;
+    }
+}
+
 /* Common initialization before parsing options.  */
 unsigned int
 c_common_init_options (unsigned int argc, const char **argv)
@@ -204,6 +288,9 @@ c_common_init_options (unsigned int argc
   unsigned int i, result;
   struct cpp_callbacks *cb;
 
+  /* Register callback for warnings enabled by -Werror=.  */
+  register_warning_as_error_callback (warning_as_error_callback);
+
   /* This is conditionalized only because that is the way the front
      ends used to do it.  Maybe this should be unconditional?  */
   if (c_dialect_cxx ())
Index: gcc/common.opt
===================================================================
--- gcc/common.opt (revision 153803)
+++ gcc/common.opt (working copy)
@@ -228,6 +228,10 @@ Wunused-variable
 Common Var(warn_unused_variable) Init(-1) Warning
 Warn when a variable is unused
 
+Wwarning-directive
+Common Var(warn_warning_directive) Init(1) Warning
+Warn when a #warning directive is encountered
+
 Wcoverage-mismatch
 Common RejectNegative Var(warn_coverage_mismatch) Warning
 Warn instead of error in case profiles in -fprofile-use do not match
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c (revision 153803)
+++ gcc/c-common.c (working copy)
@@ -8245,8 +8245,52 @@ c_parse_error (const char *gmsgid, enum
 #undef catenate_messages
 }
 
+/* Mapping for cpp message reasons to the options that enable them.  */
+
+struct reason_option_codes_t
+{
+  const int reason; /* cpplib message reason.  */
+  const int option_code; /* gcc option that controls this message.  */
+};
+
+static const struct reason_option_codes_t option_codes[] = {
+  {CPP_W_DEPRECATED, OPT_Wdeprecated},
+  {CPP_W_COMMENTS, OPT_Wcomments},
+  {CPP_W_TRIGRAPHS, OPT_Wtrigraphs},
+  {CPP_W_MULTICHAR, OPT_Wmultichar},
+  {CPP_W_TRADITIONAL, OPT_Wtraditional},
+  {CPP_W_LONG_LONG, OPT_Wlong_long},
+  {CPP_W_ENDIF_LABELS, OPT_Wendif_labels},
+  {CPP_W_VARIADIC_MACROS, OPT_Wvariadic_macros},
+  {CPP_W_BUILTIN_MACRO_REDEFINED, OPT_Wbuiltin_macro_redefined},
+  {CPP_W_UNDEF, OPT_Wundef},
+  {CPP_W_UNUSED_MACROS, OPT_Wunused_macros},
+  {CPP_W_CXX_OPERATOR_NAMES, OPT_Wc___compat},
+  {CPP_W_NORMALIZE, OPT_Wnormalized_},
+  {CPP_W_INVALID_PCH, OPT_Winvalid_pch},
+  {CPP_W_WARNING_DIRECTIVE, OPT_Wwarning_directive},
+  {CPP_W_NONE, 0}
+};
+
+/* Return the gcc option code associated with the reason for a cpp
+   message, or 0 if none.  */
+
+static int
+c_option_controlling_cpp_error (int reason)
+{
+  const struct reason_option_codes_t *entry;
+
+  for (entry = option_codes; entry->reason != CPP_W_NONE; entry++)
+    {
+      if (entry->reason == reason)
+ return entry->option_code;
+    }
+  return 0;
+}
+
 /* Callback from cpp_error for PFILE to print diagnostics from the
-   preprocessor.  The diagnostic is of type LEVEL, at location
+   preprocessor.  The diagnostic is of type LEVEL, with REASON set
+   to the reason code if LEVEL is represents a warning, at location
    LOCATION unless this is after lexing and the compiler's location
    should be used instead, with column number possibly overridden by
    COLUMN_OVERRIDE if not zero; MSG is the translated message and AP
@@ -8254,7 +8298,7 @@ c_parse_error (const char *gmsgid, enum
    otherwise.  */
 
 bool
-c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level,
+c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason,
      location_t location, unsigned int column_override,
      const char *msg, va_list *ap)
 {
@@ -8301,6 +8345,8 @@ c_cpp_error (cpp_reader *pfile ATTRIBUTE
   location, dlevel);
   if (column_override)
     diagnostic_override_column (&diagnostic, column_override);
+  diagnostic_override_option_index (&diagnostic,
+                                    c_option_controlling_cpp_error (reason));
   ret = report_diagnostic (&diagnostic);
   if (level == CPP_DL_WARNING_SYSHDR)
     warn_system_headers = save_warn_system_headers;
Index: libcpp/macro.c
===================================================================
--- libcpp/macro.c (revision 153803)
+++ libcpp/macro.c (working copy)
@@ -83,8 +83,8 @@ _cpp_warn_if_unused_macro (cpp_reader *p
 
       if (!macro->used
   && MAIN_FILE_P (linemap_lookup (pfile->line_table, macro->line)))
- cpp_error_with_line (pfile, CPP_DL_WARNING, macro->line, 0,
-     "macro \"%s\" is not used", NODE_NAME (node));
+ cpp_warning_with_line (pfile, CPP_W_UNUSED_MACROS, macro->line, 0,
+       "macro \"%s\" is not used", NODE_NAME (node));
     }
 
   return 1;
@@ -860,9 +860,9 @@ enter_macro_context (cpp_reader *pfile,
   if (buff == NULL)
     {
       if (CPP_WTRADITIONAL (pfile) && ! node->value.macro->syshdr)
- cpp_error (pfile, CPP_DL_WARNING,
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
  "function-like macro \"%s\" must be used with arguments in traditional C",
-   NODE_NAME (node));
+     NODE_NAME (node));
 
       if (pragma_buff)
  _cpp_release_buff (pfile, pragma_buff);
@@ -1582,13 +1582,14 @@ parse_params (cpp_reader *pfile, cpp_mac
       if (! CPP_OPTION (pfile, c99)
   && CPP_OPTION (pfile, pedantic)
   && CPP_OPTION (pfile, warn_variadic_macros))
- cpp_error (pfile, CPP_DL_PEDWARN,
-   "anonymous variadic macros were introduced in C99");
+ cpp_pedwarning
+                  (pfile, CPP_W_VARIADIC_MACROS,
+   "anonymous variadic macros were introduced in C99");
     }
   else if (CPP_OPTION (pfile, pedantic)
    && CPP_OPTION (pfile, warn_variadic_macros))
-    cpp_error (pfile, CPP_DL_PEDWARN,
-       "ISO C does not permit named variadic macros");
+    cpp_pedwarning (pfile, CPP_W_VARIADIC_MACROS,
+            "ISO C does not permit named variadic macros");
 
   /* We're at the end, and just expect a closing parenthesis.  */
   token = _cpp_lex_token (pfile);
@@ -1891,10 +1892,14 @@ _cpp_create_definition (cpp_reader *pfil
 
       if (warn_of_redefinition (pfile, node, macro))
  {
+          const int reason = (node->flags & NODE_BUILTIN)
+                             ? CPP_W_BUILTIN_MACRO_REDEFINED : CPP_W_NONE;
   bool warned;
-  warned = cpp_error_with_line (pfile, CPP_DL_PEDWARN,
- pfile->directive_line, 0,
- "\"%s\" redefined", NODE_NAME (node));
+
+  warned = cpp_pedwarning_with_line (pfile, reason,
+     pfile->directive_line, 0,
+     "\"%s\" redefined",
+                                             NODE_NAME (node));
 
   if (warned && node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
     cpp_error_with_line (pfile, CPP_DL_NOTE,
Index: libcpp/Makefile.in
===================================================================
--- libcpp/Makefile.in (revision 153803)
+++ libcpp/Makefile.in (working copy)
@@ -249,8 +249,15 @@ po/$(PACKAGE).pot: $(libcpp_a_SOURCES)
  $(mkinstalldirs) $(srcdir)/po
  $(XGETTEXT) --default-domain=$(PACKAGE) \
   --keyword=_ --keyword=N_ \
-  --keyword=cpp_error:3 --keyword=cpp_errno:3 \
+  --keyword=cpp_error:3 \
+  --keyword=cpp_warning:3 \
+  --keyword=cpp_pedwarning:3 \
+  --keyword=cpp_warning_syshdr:3 \
   --keyword=cpp_error_with_line:5 \
+  --keyword=cpp_warning_with_line:5 \
+  --keyword=cpp_pedwarning_with_line:5 \
+  --keyword=cpp_warning_with_line_syshdr:5 \
+  --keyword=cpp_errno:3 \
   --keyword=SYNTAX_ERROR --keyword=SYNTAX_ERROR2 \
   --copyright-holder="Free Software Foundation, Inc." \
   --msgid-bugs-address="http://gcc.gnu.org/bugs.html" \
Index: libcpp/directives.c
===================================================================
--- libcpp/directives.c (revision 153803)
+++ libcpp/directives.c (working copy)
@@ -104,7 +104,7 @@ static const char *parse_include (cpp_re
 static void push_conditional (cpp_reader *, int, int, const cpp_hashnode *);
 static unsigned int read_flag (cpp_reader *, unsigned int);
 static bool strtolinenum (const uchar *, size_t, linenum_type *, bool *);
-static void do_diagnostic (cpp_reader *, int, int);
+static void do_diagnostic (cpp_reader *, int, int, int);
 static cpp_hashnode *lex_macro_node (cpp_reader *, bool);
 static int undefine_macros (cpp_reader *, cpp_hashnode *, void *);
 static void do_include_common (cpp_reader *, enum include_type);
@@ -353,8 +353,8 @@ directive_diagnostics (cpp_reader *pfile
       else if (((dir->flags & DEPRECATED) != 0
  || (dir == &dtable[T_IMPORT] && !CPP_OPTION (pfile, objc)))
        && CPP_OPTION (pfile, warn_deprecated))
- cpp_error (pfile, CPP_DL_WARNING, "#%s is a deprecated GCC extension",
-   dir->name);
+ cpp_warning (pfile, CPP_W_DEPRECATED,
+                     "#%s is a deprecated GCC extension", dir->name);
     }
 
   /* Traditionally, a directive is ignored unless its # is in
@@ -366,16 +366,16 @@ directive_diagnostics (cpp_reader *pfile
   if (CPP_WTRADITIONAL (pfile))
     {
       if (dir == &dtable[T_ELIF])
- cpp_error (pfile, CPP_DL_WARNING,
-   "suggest not using #elif in traditional C");
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+     "suggest not using #elif in traditional C");
       else if (indented && dir->origin == KANDR)
- cpp_error (pfile, CPP_DL_WARNING,
-   "traditional C ignores #%s with the # indented",
-   dir->name);
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+     "traditional C ignores #%s with the # indented",
+     dir->name);
       else if (!indented && dir->origin != KANDR)
- cpp_error (pfile, CPP_DL_WARNING,
-   "suggest hiding #%s from traditional C with an indented #",
-   dir->name);
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+     "suggest hiding #%s from traditional C with an indented #",
+     dir->name);
     }
 }
 
@@ -1043,7 +1043,7 @@ _cpp_do_file_change (cpp_reader *pfile,
 /* Report a warning or error detected by the program we are
    processing.  Use the directive's tokens in the error message.  */
 static void
-do_diagnostic (cpp_reader *pfile, int code, int print_dir)
+do_diagnostic (cpp_reader *pfile, int code, int reason, int print_dir)
 {
   const unsigned char *dir_name;
   unsigned char *line;
@@ -1057,21 +1057,26 @@ do_diagnostic (cpp_reader *pfile, int co
   line = cpp_output_line_to_string (pfile, dir_name);
   pfile->state.prevent_expansion--;
 
-  cpp_error_with_line (pfile, code, src_loc, 0, "%s", line);
+  if (code == CPP_DL_WARNING_SYSHDR && reason)
+    cpp_warning_with_line_syshdr (pfile, reason, src_loc, 0, "%s", line);
+  else if (code == CPP_DL_WARNING && reason)
+    cpp_warning_with_line (pfile, reason, src_loc, 0, "%s", line);
+  else
+    cpp_error_with_line (pfile, code, src_loc, 0, "%s", line);
   free (line);
 }
 
 static void
 do_error (cpp_reader *pfile)
 {
-  do_diagnostic (pfile, CPP_DL_ERROR, 1);
+  do_diagnostic (pfile, CPP_DL_ERROR, 0, 1);
 }
 
 static void
 do_warning (cpp_reader *pfile)
 {
   /* We want #warning diagnostics to be emitted in system headers too.  */
-  do_diagnostic (pfile, CPP_DL_WARNING_SYSHDR, 1);
+  do_diagnostic (pfile, CPP_DL_WARNING_SYSHDR, CPP_W_WARNING_DIRECTIVE, 1);
 }
 
 /* Report program identification.  */
@@ -1501,7 +1506,7 @@ do_pragma_dependency (cpp_reader *pfile)
       if (cpp_get_token (pfile)->type != CPP_EOF)
  {
   _cpp_backup_tokens (pfile, 1);
-  do_diagnostic (pfile, CPP_DL_WARNING, 0);
+  do_diagnostic (pfile, CPP_DL_WARNING, 0, 0);
  }
     }
 
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h (revision 153803)
+++ libcpp/include/cpplib.h (working copy)
@@ -497,9 +497,9 @@ struct cpp_callbacks
 
   /* Called to emit a diagnostic.  This callback receives the
      translated message.  */
-  bool (*error) (cpp_reader *, int, source_location, unsigned int,
+  bool (*error) (cpp_reader *, int, int, source_location, unsigned int,
  const char *, va_list *)
-       ATTRIBUTE_FPTR_PRINTF(5,0);
+       ATTRIBUTE_FPTR_PRINTF(6,0);
 
   /* Callbacks for when a macro is expanded, or tested (whether
      defined or not at the time) in #ifdef, #ifndef or "defined".  */
@@ -826,25 +826,57 @@ cpp_num cpp_num_sign_extend (cpp_num, si
    position in the translation unit with it, use cpp_error_with_line
    with a line number of zero.  */
 
-/* Warning, an error with -Werror.  */
-#define CPP_DL_WARNING 0x00
-/* Same as CPP_DL_WARNING, except it is not suppressed in system headers.  */
-#define CPP_DL_WARNING_SYSHDR 0x01
-/* Warning, an error with -pedantic-errors or -Werror.  */
-#define CPP_DL_PEDWARN 0x02
-/* An error.  */
-#define CPP_DL_ERROR 0x03
-/* An internal consistency check failed.  Prints "internal error: ",
-   otherwise the same as CPP_DL_ERROR.  */
-#define CPP_DL_ICE 0x04
-/* An informative note following a warning.  */
-#define CPP_DL_NOTE 0x05
-/* A fatal error.  */
-#define CPP_DL_FATAL 0x06
+enum {
+  /* Warning, an error with -Werror.  */
+  CPP_DL_WARNING = 0,
+  /* Same as CPP_DL_WARNING, except it is not suppressed in system headers.  */
+  CPP_DL_WARNING_SYSHDR,
+  /* Warning, an error with -pedantic-errors or -Werror.  */
+  CPP_DL_PEDWARN,
+  /* An error.  */
+  CPP_DL_ERROR,
+  /* An internal consistency check failed.  Prints "internal error: ",
+     otherwise the same as CPP_DL_ERROR.  */
+  CPP_DL_ICE,
+  /* An informative note following a warning.  */
+  CPP_DL_NOTE,
+  /* A fatal error.  */
+  CPP_DL_FATAL
+};
+
+/* Warning reason codes. Use a reason code of zero for unclassified warnings
+   and errors that are not warnings.  */
+enum {
+  CPP_W_NONE = 0,
+  CPP_W_DEPRECATED,
+  CPP_W_COMMENTS,
+  CPP_W_MISSING_INCLUDE_DIRS,
+  CPP_W_TRIGRAPHS,
+  CPP_W_MULTICHAR,
+  CPP_W_TRADITIONAL,
+  CPP_W_LONG_LONG,
+  CPP_W_ENDIF_LABELS,
+  CPP_W_NUM_SIGN_CHANGE,
+  CPP_W_VARIADIC_MACROS,
+  CPP_W_BUILTIN_MACRO_REDEFINED,
+  CPP_W_DOLLARS,
+  CPP_W_UNDEF,
+  CPP_W_UNUSED_MACROS,
+  CPP_W_CXX_OPERATOR_NAMES,
+  CPP_W_NORMALIZE,
+  CPP_W_INVALID_PCH,
+  CPP_W_WARNING_DIRECTIVE
+};
 
 /* Output a diagnostic of some kind.  */
 extern bool cpp_error (cpp_reader *, int, const char *msgid, ...)
   ATTRIBUTE_PRINTF_3;
+extern bool cpp_warning (cpp_reader *, int, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_3;
+extern bool cpp_pedwarning (cpp_reader *, int, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_3;
+extern bool cpp_warning_syshdr (cpp_reader *, int, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_3;
 
 /* Output a diagnostic with "MSGID: " preceding the
    error string of errno.  No location is printed.  */
@@ -853,8 +885,18 @@ extern bool cpp_errno (cpp_reader *, int
 /* Same as cpp_error, except additionally specifies a position as a
    (translation unit) physical line and physical column.  If the line is
    zero, then no location is printed.  */
-extern bool cpp_error_with_line (cpp_reader *, int, source_location, unsigned,
- const char *msgid, ...) ATTRIBUTE_PRINTF_5;
+extern bool cpp_error_with_line (cpp_reader *, int, source_location,
+                                 unsigned, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_5;
+extern bool cpp_warning_with_line (cpp_reader *, int, source_location,
+                                   unsigned, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_5;
+extern bool cpp_pedwarning_with_line (cpp_reader *, int, source_location,
+                                      unsigned, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_5;
+extern bool cpp_warning_with_line_syshdr (cpp_reader *, int, source_location,
+                                          unsigned, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_5;
 
 /* In lex.c */
 extern int cpp_ideq (const cpp_token *, const char *);
Index: libcpp/pch.c
===================================================================
--- libcpp/pch.c (revision 153803)
+++ libcpp/pch.c (working copy)
@@ -480,9 +480,9 @@ cpp_valid_state (cpp_reader *r, const ch
   || h->flags & NODE_POISONED)
  {
   if (CPP_OPTION (r, warn_invalid_pch))
-    cpp_error (r, CPP_DL_WARNING_SYSHDR,
-       "%s: not used because `%.*s' is poisoned",
-       name, m.name_length, namebuf);
+    cpp_warning_syshdr (r, CPP_W_INVALID_PCH,
+                "%s: not used because `%.*s' is poisoned",
+                name, m.name_length, namebuf);
   goto fail;
  }
 
@@ -502,9 +502,9 @@ cpp_valid_state (cpp_reader *r, const ch
     continue;
 
   if (CPP_OPTION (r, warn_invalid_pch))
-    cpp_error (r, CPP_DL_WARNING_SYSHDR,
-       "%s: not used because `%.*s' not defined",
-       name, m.name_length, namebuf);
+    cpp_warning_syshdr (r, CPP_W_INVALID_PCH,
+                "%s: not used because `%.*s' not defined",
+                name, m.name_length, namebuf);
   goto fail;
  }
 
@@ -514,7 +514,7 @@ cpp_valid_state (cpp_reader *r, const ch
   || memcmp (namebuf, newdefn, m.definition_length) != 0)
  {
   if (CPP_OPTION (r, warn_invalid_pch))
-    cpp_error (r, CPP_DL_WARNING_SYSHDR,
+    cpp_warning_syshdr (r, CPP_W_INVALID_PCH,
        "%s: not used because `%.*s' defined as `%s' not `%.*s'",
        name, m.name_length, namebuf, newdefn + m.name_length,
        m.definition_length - m.name_length,
@@ -555,9 +555,9 @@ cpp_valid_state (cpp_reader *r, const ch
       else
  {
   if (CPP_OPTION (r, warn_invalid_pch))
-    cpp_error (r, CPP_DL_WARNING_SYSHDR,
-       "%s: not used because `%s' is defined",
-       name, first);
+    cpp_warning_syshdr (r, CPP_W_INVALID_PCH,
+                "%s: not used because `%s' is defined",
+                name, first);
   goto fail;
  }
     }
@@ -575,9 +575,9 @@ cpp_valid_state (cpp_reader *r, const ch
   if (counter && r->counter)
     {
       if (CPP_OPTION (r, warn_invalid_pch))
- cpp_error (r, CPP_DL_WARNING_SYSHDR,
-   "%s: not used because `__COUNTER__' is invalid",
-   name);
+ cpp_warning_syshdr (r, CPP_W_INVALID_PCH,
+            "%s: not used because `__COUNTER__' is invalid",
+            name);
  goto fail;
     }
 
Index: libcpp/errors.c
===================================================================
--- libcpp/errors.c (revision 153803)
+++ libcpp/errors.c (working copy)
@@ -28,16 +28,16 @@ along with this program; see the file CO
 #include "cpplib.h"
 #include "internal.h"
 
-/* Print an error at the location of the previously lexed token.  */
-bool
-cpp_error (cpp_reader * pfile, int level, const char *msgid, ...)
+/* Print a diagnostic at the location of the previously lexed token.  */
+
+ATTRIBUTE_FPTR_PRINTF(4,0)
+static bool
+cpp_diagnostic (cpp_reader * pfile, int level, int reason,
+                const char *msgid, va_list *ap)
 {
   source_location src_loc;
-  va_list ap;
   bool ret;
 
-  va_start (ap, msgid);
-
   if (CPP_OPTION (pfile, traditional))
     {
       if (pfile->state.in_directive)
@@ -61,13 +61,95 @@ cpp_error (cpp_reader * pfile, int level
 
   if (!pfile->cb.error)
     abort ();
-  ret = pfile->cb.error (pfile, level, src_loc, 0, _(msgid), &ap);
+  ret = pfile->cb.error (pfile, level, reason, src_loc, 0, _(msgid), ap);
+
+  return ret;
+}
+
+/* Print a warning or error, depending on the value of LEVEL.  */
+
+bool
+cpp_error (cpp_reader * pfile, int level, const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic (pfile, level, CPP_W_NONE, msgid, &ap);
 
   va_end (ap);
   return ret;
 }
 
-/* Print an error at a specific location.  */
+/* Print a warning.  The warning reason may be given in REASON.  */
+
+bool
+cpp_warning (cpp_reader * pfile, int reason, const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic (pfile, CPP_DL_WARNING, reason, msgid, &ap);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a pedantic warning.  The warning reason may be given in REASON.  */
+
+bool
+cpp_pedwarning (cpp_reader * pfile, int reason, const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic (pfile, CPP_DL_PEDWARN, reason, msgid, &ap);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a warning, including system headers.  The warning reason may be
+   given in REASON.  */
+
+bool
+cpp_warning_syshdr (cpp_reader * pfile, int reason, const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic (pfile, CPP_DL_WARNING_SYSHDR, reason, msgid, &ap);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a diagnostic at a specific location.  */
+
+ATTRIBUTE_FPTR_PRINTF(6,0)
+static bool
+cpp_diagnostic_with_line (cpp_reader * pfile, int level, int reason,
+          source_location src_loc, unsigned int column,
+          const char *msgid, va_list *ap)
+{
+  bool ret;
+  
+  if (!pfile->cb.error)
+    abort ();
+  ret = pfile->cb.error (pfile, level, reason, src_loc, column, _(msgid), ap);
+
+  return ret;
+}
+
+/* Print a warning or error, depending on the value of LEVEL.  */
+
 bool
 cpp_error_with_line (cpp_reader *pfile, int level,
      source_location src_loc, unsigned int column,
@@ -75,17 +157,77 @@ cpp_error_with_line (cpp_reader *pfile,
 {
   va_list ap;
   bool ret;
-  
+
   va_start (ap, msgid);
 
-  if (!pfile->cb.error)
-    abort ();
-  ret = pfile->cb.error (pfile, level, src_loc, column, _(msgid), &ap);
+  ret = cpp_diagnostic_with_line (pfile, level, CPP_W_NONE, src_loc,
+                                  column, msgid, &ap);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a warning.  The warning reason may be given in REASON.  */
+
+bool
+cpp_warning_with_line (cpp_reader *pfile, int reason,
+       source_location src_loc, unsigned int column,
+       const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic_with_line (pfile, CPP_DL_WARNING, reason, src_loc,
+                                  column, msgid, &ap);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a pedantic warning.  The warning reason may be given in REASON.  */
+
+bool
+cpp_pedwarning_with_line (cpp_reader *pfile, int reason,
+          source_location src_loc, unsigned int column,
+          const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic_with_line (pfile, CPP_DL_PEDWARN, reason, src_loc,
+                                  column, msgid, &ap);
 
   va_end (ap);
   return ret;
 }
 
+/* Print a warning, including system headers.  The warning reason may be
+   given in REASON.  */
+
+bool
+cpp_warning_with_line_syshdr (cpp_reader *pfile, int reason,
+              source_location src_loc, unsigned int column,
+              const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic_with_line (pfile, CPP_DL_WARNING_SYSHDR, reason, src_loc,
+                                  column, msgid, &ap);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a warning or error, depending on the value of LEVEL.  Include
+   information from errno.  */
+
 bool
 cpp_errno (cpp_reader *pfile, int level, const char *msgid)
 {
Index: libcpp/expr.c
===================================================================
--- libcpp/expr.c (revision 153803)
+++ libcpp/expr.c (working copy)
@@ -365,9 +365,9 @@ cpp_classify_number (cpp_reader *pfile,
       if (limit != str
   && CPP_WTRADITIONAL (pfile)
   && ! cpp_sys_macro_p (pfile))
- cpp_error (pfile, CPP_DL_WARNING,
-   "traditional C rejects the \"%.*s\" suffix",
-   (int) (limit - str), str);
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+     "traditional C rejects the \"%.*s\" suffix",
+     (int) (limit - str), str);
 
       /* A suffix for double is a GCC extension via decimal float support.
  If the suffix also specifies an imaginary value we'll catch that
@@ -411,21 +411,27 @@ cpp_classify_number (cpp_reader *pfile,
       if (CPP_WTRADITIONAL (pfile) && ! cpp_sys_macro_p (pfile))
  {
   int u_or_i = (result & (CPP_N_UNSIGNED|CPP_N_IMAGINARY));
-  int large = (result & CPP_N_WIDTH) == CPP_N_LARGE;
+  int large = (result & CPP_N_WIDTH) == CPP_N_LARGE
+       && CPP_OPTION (pfile, warn_long_long);
 
-  if (u_or_i || (large && CPP_OPTION (pfile, warn_long_long)))
-    cpp_error (pfile, CPP_DL_WARNING,
-       "traditional C rejects the \"%.*s\" suffix",
-       (int) (limit - str), str);
+  if (u_or_i || large)
+    cpp_warning (pfile, large ? CPP_W_LONG_LONG : CPP_W_TRADITIONAL,
+         "traditional C rejects the \"%.*s\" suffix",
+         (int) (limit - str), str);
  }
 
       if ((result & CPP_N_WIDTH) == CPP_N_LARGE
   && CPP_OPTION (pfile, warn_long_long))
- cpp_error (pfile,
-   CPP_OPTION (pfile, c99) ? CPP_DL_WARNING : CPP_DL_PEDWARN,
-   CPP_OPTION (pfile, cplusplus)
-   ? "use of C++0x long long integer constant"
-   : "use of C99 long long integer constant");
+        {
+          const char *message = CPP_OPTION (pfile, cplusplus)
+                ? N_("use of C++0x long long integer constant")
+                : N_("use of C99 long long integer constant");
+
+  if (CPP_OPTION (pfile, c99))
+            cpp_warning (pfile, CPP_W_LONG_LONG, message);
+          else
+            cpp_pedwarning (pfile, CPP_W_LONG_LONG, message);
+        }
 
       result |= CPP_N_INTEGER;
     }
@@ -786,8 +792,8 @@ eval_token (cpp_reader *pfile, const cpp
   result.high = 0;
   result.low = 0;
   if (CPP_OPTION (pfile, warn_undef) && !pfile->state.skip_eval)
-    cpp_error (pfile, CPP_DL_WARNING, "\"%s\" is not defined",
-       NODE_NAME (token->val.node.node));
+    cpp_warning (pfile, CPP_W_UNDEF, "\"%s\" is not defined",
+         NODE_NAME (token->val.node.node));
  }
       break;
 
@@ -800,8 +806,8 @@ eval_token (cpp_reader *pfile, const cpp
     cpp_error (pfile, CPP_DL_PEDWARN,
        "assertions are a GCC extension");
   else if (CPP_OPTION (pfile, warn_deprecated))
-    cpp_error (pfile, CPP_DL_WARNING,
-       "assertions are a deprecated extension");
+    cpp_warning (pfile, CPP_W_DEPRECATED,
+         "assertions are a deprecated extension");
  }
       _cpp_test_assertion (pfile, &temp);
       result.high = 0;
@@ -1496,8 +1502,8 @@ num_unary_op (cpp_reader *pfile, cpp_num
     {
     case CPP_UPLUS:
       if (CPP_WTRADITIONAL (pfile) && !pfile->state.skip_eval)
- cpp_error (pfile, CPP_DL_WARNING,
-   "traditional C rejects the unary plus operator");
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+     "traditional C rejects the unary plus operator");
       num.overflow = false;
       break;
 
Index: libcpp/lex.c
===================================================================
--- libcpp/lex.c (revision 153803)
+++ libcpp/lex.c (working copy)
@@ -301,14 +301,16 @@ _cpp_process_line_notes (cpp_reader *pfi
       && (!in_comment || warn_in_comment (pfile, note)))
     {
       if (CPP_OPTION (pfile, trigraphs))
- cpp_error_with_line (pfile, CPP_DL_WARNING, pfile->line_table->highest_line, col,
-     "trigraph ??%c converted to %c",
-     note->type,
-     (int) _cpp_trigraph_map[note->type]);
+ cpp_warning_with_line (pfile, CPP_W_TRIGRAPHS,
+                                       pfile->line_table->highest_line, col,
+       "trigraph ??%c converted to %c",
+       note->type,
+       (int) _cpp_trigraph_map[note->type]);
       else
  {
-  cpp_error_with_line
-    (pfile, CPP_DL_WARNING, pfile->line_table->highest_line, col,
+  cpp_warning_with_line
+    (pfile, CPP_W_TRIGRAPHS,
+                     pfile->line_table->highest_line, col,
      "trigraph ??%c ignored, use -trigraphs to enable",
      note->type);
  }
@@ -353,9 +355,10 @@ _cpp_skip_block_comment (cpp_reader *pfi
       && cur[0] == '*' && cur[1] != '/')
     {
       buffer->cur = cur;
-      cpp_error_with_line (pfile, CPP_DL_WARNING,
-   pfile->line_table->highest_line, CPP_BUF_COL (buffer),
-   "\"/*\" within comment");
+      cpp_warning_with_line (pfile, CPP_W_COMMENTS,
+     pfile->line_table->highest_line,
+     CPP_BUF_COL (buffer),
+     "\"/*\" within comment");
     }
  }
       else if (c == '\n')
@@ -458,11 +461,11 @@ warn_about_normalization (cpp_reader *pf
 
       sz = cpp_spell_token (pfile, token, buf, false) - buf;
       if (NORMALIZE_STATE_RESULT (s) == normalized_C)
- cpp_error_with_line (pfile, CPP_DL_WARNING, token->src_loc, 0,
-     "`%.*s' is not in NFKC", (int) sz, buf);
+ cpp_warning_with_line (pfile, CPP_W_NORMALIZE, token->src_loc, 0,
+       "`%.*s' is not in NFKC", (int) sz, buf);
       else
- cpp_error_with_line (pfile, CPP_DL_WARNING, token->src_loc, 0,
-     "`%.*s' is not in NFC", (int) sz, buf);
+ cpp_warning_with_line (pfile, CPP_W_NORMALIZE, token->src_loc, 0,
+       "`%.*s' is not in NFC", (int) sz, buf);
     }
 }
 
@@ -563,9 +566,9 @@ lex_identifier (cpp_reader *pfile, const
 
       /* For -Wc++-compat, warn about use of C++ named operators.  */
       if (result->flags & NODE_WARN_OPERATOR)
- cpp_error (pfile, CPP_DL_WARNING,
-   "identifier \"%s\" is a special operator name in C++",
-   NODE_NAME (result));
+ cpp_warning (pfile, CPP_W_CXX_OPERATOR_NAMES,
+     "identifier \"%s\" is a special operator name in C++",
+     NODE_NAME (result));
     }
 
   return result;
@@ -1373,7 +1376,7 @@ _cpp_lex_direct (cpp_reader *pfile)
     }
 
   if (skip_line_comment (pfile) && CPP_OPTION (pfile, warn_comments))
-    cpp_error (pfile, CPP_DL_WARNING, "multi-line comment");
+    cpp_warning (pfile, CPP_W_COMMENTS, "multi-line comment");
  }
       else if (c == '=')
  {
Index: libcpp/charset.c
===================================================================
--- libcpp/charset.c (revision 153803)
+++ libcpp/charset.c (working copy)
@@ -993,9 +993,9 @@ _cpp_valid_ucn (cpp_reader *pfile, const
     cpp_error (pfile, CPP_DL_WARNING,
        "universal character names are only valid in C++ and C99");
   else if (CPP_WTRADITIONAL (pfile) && identifier_pos == 0)
-    cpp_error (pfile, CPP_DL_WARNING,
-       "the meaning of '\\%c' is different in traditional C",
-       (int) str[-1]);
+    cpp_warning (pfile, CPP_W_TRADITIONAL,
+         "the meaning of '\\%c' is different in traditional C",
+         (int) str[-1]);
 
   if (str[-1] == 'u')
     length = 4;
@@ -1174,8 +1174,8 @@ convert_hex (cpp_reader *pfile, const uc
   size_t mask = width_to_mask (width);
 
   if (CPP_WTRADITIONAL (pfile))
-    cpp_error (pfile, CPP_DL_WARNING,
-       "the meaning of '\\x' is different in traditional C");
+    cpp_warning (pfile, CPP_W_TRADITIONAL,
+         "the meaning of '\\x' is different in traditional C");
 
   from++;  /* Skip 'x'.  */
   while (from < limit)
@@ -1302,8 +1302,8 @@ convert_escape (cpp_reader *pfile, const
 
     case 'a':
       if (CPP_WTRADITIONAL (pfile))
- cpp_error (pfile, CPP_DL_WARNING,
-   "the meaning of '\\a' is different in traditional C");
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+     "the meaning of '\\a' is different in traditional C");
       c = charconsts[0];
       break;
 
@@ -1522,7 +1522,7 @@ narrow_str_to_charconst (cpp_reader *pfi
  "character constant too long for its type");
     }
   else if (i > 1 && CPP_OPTION (pfile, warn_multichar))
-    cpp_error (pfile, CPP_DL_WARNING, "multi-character character constant");
+    cpp_warning (pfile, CPP_W_MULTICHAR, "multi-character character constant");
 
   /* Multichar constants are of type int and therefore signed.  */
   if (i > 1)


Re: [PATCH][RFA] Enabling -W[no-]error=... for cpplib warnings

by Joseph S. Myers :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, 3 Nov 2009, Simon Baldwin wrote:

> Thank you for the review -- inlined responses below.
>
> I've attached a revised and corrected version of the patch to the
> mail; bootstrap C/C++/Fortran and appropriate suite re-done.  Please
> take a second look.  Thanks.

The C and cpplib parts of the revised patch are OK.  You still need review
of the Fortran, diagnostic.h and opts.[ch] parts.

--
Joseph S. Myers
joseph@...

Re: [PATCH][RFA] Enabling -W[no-]error=... for cpplib warnings

by Ian Lance Taylor-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Simon Baldwin <simonb@...> writes:

> gcc/ChangeLog:
> 2009-11-02  Simon Baldwin  <simonb@...>
>
> * diagnostic.h (diagnostic_override_option_index): New macro to
> set a diagnostic's option_index.
> * c-tree.h (c_cpp_error): Add warning reason argument.
> * opts.c (_warning_as_error_callback): New.
> (register_warning_as_error_callback): Store callback for
> warnings enabled via enable_warning_as_error.
> (enable_warning_as_error): Call callback, minor code tidy.
> * opts.h (register_warning_as_error_callback): Declare.
> * c-opts.c (warning_as_error_callback): New, set cpp_opts flag in
> response to -Werror=.
> (c_common_init_options): Register warning_as_error_callback in opts.c.
> * common.opt: Add -Wno-warning-directive option.
> * c-common.c (struct reason_option_codes_t): Map cpp warning
> reason codes to gcc option indexes.
> * (c_option_controlling_cpp_error): New function, lookup the gcc
> option index for a cpp warning reason code.
> * (c_cpp_error): Add warning reason argument, call
> c_option_controlling_cpp_error for diagnostic_override_option_index.
> * doc/invoke.texi: Document -Wno-warning-directive.
>
> gcc/fortran/ChangeLog:
> 2009-11-02  Simon Baldwin  <simonb@...>
>
> * cpp.c (cb_cpp_error): Add warning reason argument, set a value
> for diagnostic_override_option_index if CPP_W_WARNING_DIRECTIVE.
>
> libcpp/ChangeLog:
> 2009-11-02  Simon Baldwin  <simonb@...>
>
> * directives.c (do_diagnostic): Add warning reason argument,
> call appropriate error reporting function for code.
> (directive_diagnostics): Call specific warning functions with
> warning reason where appropriate.
> (do_error, do_warning, do_pragma_dependency): Add warning reason
> argument to do_diagnostic calls.
> * macro.c (_cpp_warn_if_unused_macro, enter_macro_context,
> _cpp_create_definition): Call specific warning functions with
>         warning reason where appropriate.
> * Makefile.in: Add new diagnostic functions to gettext translations.
> * include/cpplib.h (struct cpp_callbacks): Add warning reason code
> to error callback.
> (CPP_DL_WARNING, CPP_DL_WARNING_SYSHDR, CPP_DL_PEDWARN, CPP_DL_ERROR,
> CPP_DL_ICE, CPP_DL_NOTE, CPP_DL_FATAL): Replace macros with enums.
> (CPP_W_NONE, CPP_W_DEPRECATED, CPP_W_COMMENTS,
> CPP_W_MISSING_INCLUDE_DIRS, CPP_W_TRIGRAPHS, CPP_W_MULTICHAR,
> CPP_W_TRADITIONAL, CPP_W_LONG_LONG, CPP_W_ENDIF_LABELS,
> CPP_W_NUM_SIGN_CHANGE, CPP_W_VARIADIC_MACROS,
> CPP_W_BUILTIN_MACRO_REDEFINED, CPP_W_DOLLARS, CPP_W_UNDEF,
> CPP_W_UNUSED_MACROS, CPP_W_CXX_OPERATOR_NAMES, CPP_W_NORMALIZE,
> CPP_W_INVALID_PCH, CPP_W_WARNING_DIRECTIVE): New enums for cpp
> warning reason codes.
> (cpp_warning, cpp_pedwarning, cpp_warning_syshdr,
> cpp_warning_with_line, cpp_pedwarning_with_line,
> cpp_warning_with_line_syshdr): New specific error reporting functions.
> * pch.c (cpp_valid_state): Call specific warning functions with
>         warning reason where appropriate.
> * errors.c (cpp_diagnostic, cpp_diagnostic_with_line): New central
> diagnostic handlers.
> (cpp_warning, cpp_pedwarning, cpp_warning_syshdr,
> cpp_warning_with_line, cpp_pedwarning_with_line,
> cpp_warning_with_line_syshdr): New specific error reporting functions.
> * expr.c (cpp_classify_number, eval_token, num_unary_op): Call
> specific warning functions with warning reason where appropriate.
> * lex.c (_cpp_process_line_notes, _cpp_skip_block_comment,
> warn_about_normalization, lex_identifier, _cpp_lex_direct): Ditto.
> * charset.c (_cpp_valid_ucn, convert_hex, convert_escape,
> narrow_str_to_charconst): Ditto.
>
> gcc/testsuite/ChangeLog:
> 2009-11-02  Simon Baldwin  <simonb@...>
>
> * gcc.dg/cpp/warn-undef-2.c: New.
> * gcc.dg/cpp/warn-traditional-2.c: New.
> * gcc.dg/cpp/warn-comments-2.c: New.
> * gcc.dg/cpp/warning-directive-1.c: New.
> * gcc.dg/cpp/warn-long-long.c: New.
> * gcc.dg/cpp/warn-traditional.c: New.
> * gcc.dg/cpp/warn-variadic-2.c: New.
> * gcc.dg/cpp/warn-undef.c: New.
> * gcc.dg/cpp/warn-normalized-1.c: New.
> * gcc.dg/cpp/warning-directive-2.c: New.
> * gcc.dg/cpp/warn-long-long-2.c: New.
> * gcc.dg/cpp/warn-variadic.c: New.
> * gcc.dg/cpp/warn-normalized-2.c: New.
> * gcc.dg/cpp/warning-directive-3.c: New.
> * gcc.dg/cpp/warn-deprecated-2.c: New.
> * gcc.dg/cpp/warn-trigraphs-1.c: New.
> * gcc.dg/cpp/warn-multichar-2.c: New.
> * gcc.dg/cpp/warn-normalized-3.c: New.
> * gcc.dg/cpp/warning-directive-4.c: New.
> * gcc.dg/cpp/warn-unused-macros.c: New.
> * gcc.dg/cpp/warn-trigraphs-2.c: New.
> * gcc.dg/cpp/warn-cxx-compat-2.c: New.
> * gcc.dg/cpp/warn-cxx-compat.c: New.
> * gcc.dg/cpp/warn-redefined.c: New.
> * gcc.dg/cpp/warn-trigraphs-3.c: New.
> * gcc.dg/cpp/warn-unused-macros-2.c: New.
> * gcc.dg/cpp/warn-deprecated.c: New.
> * gcc.dg/cpp/warn-trigraphs-4.c: New.
> * gcc.dg/cpp/warn-redefined-2.c: New.
> * gcc.dg/cpp/warn-comments.c: New.
> * gcc.dg/cpp/warn-multichar.c: New.
> * g++.dg/cpp/warning-directive-1.C: New.
> * g++.dg/cpp/warning-directive-2.C: New.
> * g++.dg/cpp/warning-directive-3.C: New.
> * g++.dg/cpp/warning-directive-4.C: New.
> * gfortran.dg/warning-directive-1.F90: New.
> * gfortran.dg/warning-directive-3.F90: New.
> * gfortran.dg/warning-directive-2.F90: New.
> * gfortran.dg/warning-directive-4.F90: New.



> +/* Override the option index to be used for reporting a
> +   diagnostic.  */
> +#define diagnostic_override_option_index(DI, OPTIDX) \
> +    (DI)->option_index = (OPTIDX)

Please put parentheses around the macro expansion.


> +/* Callback function, called when -Werror= enables a warning.  */
> +
> +static void (*warning_as_error_callback) (int) = NULL;
> +
> +/* Register a callback for enable_warning_as_error calls.  */
> +
> +void
> +register_warning_as_error_callback (void (*callback) (int))
> +{
> +  warning_as_error_callback = callback;
> +}

Since there can only be one callback, please add something along the
lines of
  gcc_assert (warning_as_error_callback == NULL || callback == NULL);


This is OK with those changes.

Thanks.

Ian

Re: [PATCH][RFA] Enabling -W[no-]error=... for cpplib warnings

by Gabriel Dos Reis-6 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, Nov 3, 2009 at 6:25 AM, Simon Baldwin <simonb@...> wrote:
> Thank you for the review -- inlined responses below.
>
> I've attached a revised and corrected version of the patch to the
> mail; bootstrap C/C++/Fortran and appropriate suite re-done.  Please
> take a second look.  Thanks.

My earlier comments were about the name of the command line.  It is
misleading.  We are not warning #warning.  Please, change the
name to something like -Wcpp or better.  Wwarning-directive
sounds as if we were warning about #warning themselves.

-- Gaby

Re: [PATCH][RFA] Enabling -W[no-]error=... for cpplib warnings

by Simon Baldwin-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2009/11/8 Gabriel Dos Reis <dosreis@...>

>
> On Tue, Nov 3, 2009 at 6:25 AM, Simon Baldwin <simonb@...> wrote:
> > Thank you for the review -- inlined responses below.
> >
> > I've attached a revised and corrected version of the patch to the
> > mail; bootstrap C/C++/Fortran and appropriate suite re-done.  Please
> > take a second look.  Thanks.
>
> My earlier comments were about the name of the command line.  It is
> misleading.  We are not warning #warning.  Please, change the
> name to something like -Wcpp or better.  Wwarning-directive
> sounds as if we were warning about #warning themselves.

Neither -Wcomment nor -Wsystem-headers behave in the way this reading
of their names might suggest, yet both are accepted.

However, -Wcpp sounds worse to me.  The preprocessor can issue several
warnings, and -Wcpp sounds like it controls them all.  In fact, only
the output of #warning is what's affected here.  -Wwarning-directive
has the advantage of being relatively short and easy to remember, and
also contains "warning" and so is likely to be found in a man or text
search.

Please let me know precisely what you would like this command line
flag to be called, and I will change it to that.

Thanks,

--S

--
Google UK Limited | Registered Office: Belgrave House, 76 Buckingham
Palace Road, London SW1W 9TQ | Registered in England Number: 3977902

Re: [PATCH][RFA] Enabling -W[no-]error=... for cpplib warnings

by Gabriel Dos Reis :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Nov 9, 2009 at 5:16 AM, Simon Baldwin <simonb@...> wrote:

> 2009/11/8 Gabriel Dos Reis <dosreis@...>
>>
>> On Tue, Nov 3, 2009 at 6:25 AM, Simon Baldwin <simonb@...> wrote:
>> > Thank you for the review -- inlined responses below.
>> >
>> > I've attached a revised and corrected version of the patch to the
>> > mail; bootstrap C/C++/Fortran and appropriate suite re-done.  Please
>> > take a second look.  Thanks.
>>
>> My earlier comments were about the name of the command line.  It is
>> misleading.  We are not warning #warning.  Please, change the
>> name to something like -Wcpp or better.  Wwarning-directive
>> sounds as if we were warning about #warning themselves.
>
> Neither -Wcomment nor -Wsystem-headers behave in the way this reading
> of their names might suggest, yet both are accepted.

I believe building on 'exceptions' to make the list of exceptions long is
wrong headed and a wrong excuse.

>
> However, -Wcpp sounds worse to me.  The preprocessor can issue several
> warnings, and -Wcpp sounds like it controls them all.  In fact, only
> the output of #warning is what's affected here.  -Wwarning-directive
> has the advantage of being relatively short and easy to remember,

well, it is not shorter than 'cpp', and the issue is not 'easy to
remember' -- both
would be.

>  and
> also contains "warning" and so is likely to be found in a man or text
> search.

-W already standard for 'warn'.

>
> Please let me know precisely what you would like this command line
> flag to be called, and I will change it to that.

I believe I did.

-- Gaby

Re: [PATCH][RFA] Enabling -W[no-]error=... for cpplib warnings

by Simon Baldwin-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2009/11/9 Gabriel Dos Reis <gdr@...>:
> ...
>> Please let me know precisely what you would like this command line
>> flag to be called, and I will change it to that.
>
> I believe I did.

"...to something like -Wcpp or better" didn't seem all that precise to me.

Nevertheless I will change the patch to use this in place of
-Wwarning-directive and repost the updated version once it's completed
testing  Please take another look when ready.

Thanks,

--S

--
Google UK Limited | Registered Office: Belgrave House, 76 Buckingham
Palace Road, London SW1W 9TQ | Registered in England Number: 3977902

Re: [PATCH][RFA] Enabling -W[no-]error=... for cpplib warnings

by Gabriel Dos Reis :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Nov 9, 2009 at 7:47 AM, Simon Baldwin <simonb@...> wrote:

> 2009/11/9 Gabriel Dos Reis <gdr@...>:
>> ...
>>> Please let me know precisely what you would like this command line
>>> flag to be called, and I will change it to that.
>>
>> I believe I did.
>
> "...to something like -Wcpp or better" didn't seem all that precise to me.
>
> Nevertheless I will change the patch to use this in place of
> -Wwarning-directive and repost the updated version once it's completed
> testing  Please take another look when ready.

Thanks!

-- Gaby

Re: [PATCH][RFA] Enabling -W[no-]error=... for cpplib warnings

by Simon Baldwin-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Attached below is the updated version of this patch, incorporating
Ian's gcc_assert() and macro expansion parenthesis changes, and Gaby's
change of warning flag name from -Wwarning-directive to -Wcpp.

Okay for trunk?  I think that's everything covered, so I'll submit in
a few days if no further comments.  Thanks.

--
Google UK Limited | Registered Office: Belgrave House, 76 Buckingham
Palace Road, London SW1W 9TQ | Registered in England Number: 3977902

[cpp_warnings.patch]

This patch brings several preprocessor warnings under the control of the
-Werror= gcc flag.  At present, gcc does not associate preprocessor warnings
with gcc command line options, and so such warnings cannot be controlled
individually with -Werror=.

With the patch in place, preprocessor warnings can now be set separately as
errors with -Werror=, disabled as errors with -Wno-error=, and will report
their corresponding gcc diagnostic flag with -fdiagnostics-show-option when
requested.

The patch also adds a new gcc option -W[no-]cpp so that the output of #warning
operates symmetrically to other gcc warnings, and in particular so that the
combination "-Werror -Wno-error=cpp" allows all warnings except for #warning
directives to be treated as errors.

Confirmed C, C++ and Fortran dejagnu testsuite parity with the unpatched gcc,
and verified bootstrap of C/C++/Fortran on x86_64.


gcc/ChangeLog:
2009-11-09  Simon Baldwin  <simonb@...>

        * diagnostic.h (diagnostic_override_option_index): New macro to
        set a diagnostic's option_index.
        * c-tree.h (c_cpp_error): Add warning reason argument.
        * opts.c (_warning_as_error_callback): New.
        (register_warning_as_error_callback): Store callback for
        warnings enabled via enable_warning_as_error.
        (enable_warning_as_error): Call callback, minor code tidy.
        * opts.h (register_warning_as_error_callback): Declare.
        * c-opts.c (warning_as_error_callback): New, set cpp_opts flag in
        response to -Werror=.
        (c_common_init_options): Register warning_as_error_callback in opts.c.
        * common.opt: Add -Wno-cpp option.
        * c-common.c (struct reason_option_codes_t): Map cpp warning
        reason codes to gcc option indexes.
        * (c_option_controlling_cpp_error): New function, lookup the gcc
        option index for a cpp warning reason code.
        * (c_cpp_error): Add warning reason argument, call
        c_option_controlling_cpp_error for diagnostic_override_option_index.
        * doc/invoke.texi: Document -Wno-cpp.

gcc/fortran/ChangeLog:
2009-11-09  Simon Baldwin  <simonb@...>

        * cpp.c (cb_cpp_error): Add warning reason argument, set a value
        for diagnostic_override_option_index if CPP_W_WARNING_DIRECTIVE.

libcpp/ChangeLog:
2009-11-09  Simon Baldwin  <simonb@...>

        * directives.c (do_diagnostic): Add warning reason argument,
        call appropriate error reporting function for code.
        (directive_diagnostics): Call specific warning functions with
        warning reason where appropriate.
        (do_error, do_warning, do_pragma_dependency): Add warning reason
        argument to do_diagnostic calls.
        * macro.c (_cpp_warn_if_unused_macro, enter_macro_context,
        _cpp_create_definition): Call specific warning functions with
        warning reason where appropriate.
        * Makefile.in: Add new diagnostic functions to gettext translations.
        * include/cpplib.h (struct cpp_callbacks): Add warning reason code
        to error callback.
        (CPP_DL_WARNING, CPP_DL_WARNING_SYSHDR, CPP_DL_PEDWARN, CPP_DL_ERROR,
        CPP_DL_ICE, CPP_DL_NOTE, CPP_DL_FATAL): Replace macros with enums.
        (CPP_W_NONE, CPP_W_DEPRECATED, CPP_W_COMMENTS,
        CPP_W_MISSING_INCLUDE_DIRS, CPP_W_TRIGRAPHS, CPP_W_MULTICHAR,
        CPP_W_TRADITIONAL, CPP_W_LONG_LONG, CPP_W_ENDIF_LABELS,
        CPP_W_NUM_SIGN_CHANGE, CPP_W_VARIADIC_MACROS,
        CPP_W_BUILTIN_MACRO_REDEFINED, CPP_W_DOLLARS, CPP_W_UNDEF,
        CPP_W_UNUSED_MACROS, CPP_W_CXX_OPERATOR_NAMES, CPP_W_NORMALIZE,
        CPP_W_INVALID_PCH, CPP_W_WARNING_DIRECTIVE): New enums for cpp
        warning reason codes.
        (cpp_warning, cpp_pedwarning, cpp_warning_syshdr,
        cpp_warning_with_line, cpp_pedwarning_with_line,
        cpp_warning_with_line_syshdr): New specific error reporting functions.
        * pch.c (cpp_valid_state): Call specific warning functions with
        warning reason where appropriate.
        * errors.c (cpp_diagnostic, cpp_diagnostic_with_line): New central
        diagnostic handlers.
        (cpp_warning, cpp_pedwarning, cpp_warning_syshdr,
        cpp_warning_with_line, cpp_pedwarning_with_line,
        cpp_warning_with_line_syshdr): New specific error reporting functions.
        * expr.c (cpp_classify_number, eval_token, num_unary_op): Call
        specific warning functions with warning reason where appropriate.
        * lex.c (_cpp_process_line_notes, _cpp_skip_block_comment,
        warn_about_normalization, lex_identifier, _cpp_lex_direct): Ditto.
        * charset.c (_cpp_valid_ucn, convert_hex, convert_escape,
        narrow_str_to_charconst): Ditto.

gcc/testsuite/ChangeLog:
2009-11-09  Simon Baldwin  <simonb@...>

        * gcc.dg/cpp/warn-undef-2.c: New.
        * gcc.dg/cpp/warn-traditional-2.c: New.
        * gcc.dg/cpp/warn-comments-2.c: New.
        * gcc.dg/cpp/warning-directive-1.c: New.
        * gcc.dg/cpp/warn-long-long.c: New.
        * gcc.dg/cpp/warn-traditional.c: New.
        * gcc.dg/cpp/warn-variadic-2.c: New.
        * gcc.dg/cpp/warn-undef.c: New.
        * gcc.dg/cpp/warn-normalized-1.c: New.
        * gcc.dg/cpp/warning-directive-2.c: New.
        * gcc.dg/cpp/warn-long-long-2.c: New.
        * gcc.dg/cpp/warn-variadic.c: New.
        * gcc.dg/cpp/warn-normalized-2.c: New.
        * gcc.dg/cpp/warning-directive-3.c: New.
        * gcc.dg/cpp/warn-deprecated-2.c: New.
        * gcc.dg/cpp/warn-trigraphs-1.c: New.
        * gcc.dg/cpp/warn-multichar-2.c: New.
        * gcc.dg/cpp/warn-normalized-3.c: New.
        * gcc.dg/cpp/warning-directive-4.c: New.
        * gcc.dg/cpp/warn-unused-macros.c: New.
        * gcc.dg/cpp/warn-trigraphs-2.c: New.
        * gcc.dg/cpp/warn-cxx-compat-2.c: New.
        * gcc.dg/cpp/warn-cxx-compat.c: New.
        * gcc.dg/cpp/warn-redefined.c: New.
        * gcc.dg/cpp/warn-trigraphs-3.c: New.
        * gcc.dg/cpp/warn-unused-macros-2.c: New.
        * gcc.dg/cpp/warn-deprecated.c: New.
        * gcc.dg/cpp/warn-trigraphs-4.c: New.
        * gcc.dg/cpp/warn-redefined-2.c: New.
        * gcc.dg/cpp/warn-comments.c: New.
        * gcc.dg/cpp/warn-multichar.c: New.
        * g++.dg/cpp/warning-directive-1.C: New.
        * g++.dg/cpp/warning-directive-2.C: New.
        * g++.dg/cpp/warning-directive-3.C: New.
        * g++.dg/cpp/warning-directive-4.C: New.
        * gfortran.dg/warning-directive-1.F90: New.
        * gfortran.dg/warning-directive-3.F90: New.
        * gfortran.dg/warning-directive-2.F90: New.
        * gfortran.dg/warning-directive-4.F90: New.


Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi (revision 153803)
+++ gcc/doc/invoke.texi (working copy)
@@ -232,7 +232,7 @@ Objective-C and Objective-C++ Dialects}.
 -Wno-attributes -Wno-builtin-macro-redefined @gol
 -Wc++-compat -Wc++0x-compat -Wcast-align  -Wcast-qual  @gol
 -Wchar-subscripts -Wclobbered  -Wcomment @gol
--Wconversion  -Wcoverage-mismatch  -Wno-deprecated  @gol
+-Wconversion  -Wcoverage-mismatch  -Wcpp  -Wno-deprecated  @gol
 -Wno-deprecated-declarations -Wdisabled-optimization  @gol
 -Wno-div-by-zero -Wempty-body  -Wenum-compare -Wno-endif-labels @gol
 -Werror  -Werror=* @gol
@@ -2936,6 +2936,11 @@ Warn whenever a comment-start sequence @
 comment, or whenever a Backslash-Newline appears in a @samp{//} comment.
 This warning is enabled by @option{-Wall}.
 
+@item -Wno-cpp \
+@r{(C, Objective-C, C++, Objective-C++ and Fortran only)}
+
+Suppress warning messages emitted by @code{#warning} directives.
+
 @item -Wformat
 @opindex Wformat
 @opindex Wno-format
Index: gcc/diagnostic.h
===================================================================
--- gcc/diagnostic.h (revision 153803)
+++ gcc/diagnostic.h (working copy)
@@ -190,6 +190,11 @@ extern diagnostic_context *global_dc;
    diagnostic.  */
 #define diagnostic_override_column(DI, COL) (DI)->override_column = (COL)
 
+/* Override the option index to be used for reporting a
+   diagnostic.  */
+#define diagnostic_override_option_index(DI, OPTIDX) \
+    ((DI)->option_index = (OPTIDX))
+
 /* Diagnostic related functions.  */
 extern void diagnostic_initialize (diagnostic_context *);
 extern void diagnostic_report_current_module (diagnostic_context *);
Index: gcc/testsuite/gcc.dg/cpp/warn-undef-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-undef-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-undef-2.c (revision 0)
@@ -0,0 +1,5 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=undef" }
+
+#if x  // { dg-error "\"x\" is not defined .-Wundef." }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-traditional-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-traditional-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-traditional-2.c (revision 0)
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=traditional -Wno-deprecated -Wno-long-long" }
+
+#assert x(x)         // { dg-error "suggest hiding #assert from traditional C with an indented # .-Wtraditional." }
+
+ #define X X         // { dg-error "traditional C ignores #define with the # indented .-Wtraditional." }
+
+#if 0
+#elif 1              // { dg-error "suggest not using #elif in traditional C .-Wtraditional." }
+#endif
+
+#define f(X) X
+int f;               // { dg-error "function-like macro \"f\" must be used with arguments in traditional C .-Wtraditional." }
+
+#if 0U               // { dg-error "traditional C rejects the \"U\" suffix .-Wtraditional." }
+#endif
+
+#if +1               // { dg-error " traditional C rejects the unary plus operator .-Wtraditional." }
+#endif
+
+char *x = "\x0";     // { dg-error "the meaning of '.x' is different in traditional C .-Wtraditional." }
+char *y = "\a";      // { dg-error "the meaning of '.a' is different in traditional C .-Wtraditional." }
+char *z = "\u0F43";  // { dg-error "the meaning of '.u' is different in traditional C .-Wtraditional." }
Index: gcc/testsuite/gcc.dg/cpp/warn-comments-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-comments-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-comments-2.c (revision 0)
@@ -0,0 +1,7 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=comments" }
+
+/* /* */  // { dg-error "\"\.\*\" within comment .-Wcomments." }
+
+// \
+          // { dg-error "multi-line comment .-Wcomments." "multi-line" { target *-*-* } 6 }
Index: gcc/testsuite/gcc.dg/cpp/warning-directive-1.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warning-directive-1.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warning-directive-1.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option" }
+
+#warning "Printed"  // { dg-warning "\"Printed\" .-Wcpp." }
Index: gcc/testsuite/gcc.dg/cpp/warn-long-long.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-long-long.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-long-long.c (revision 0)
@@ -0,0 +1,6 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wtraditional -Wlong-long" }
+
+#if 0LL  // { dg-warning "traditional C rejects the \"LL\" suffix .-Wlong-long." }
+         // { dg-warning "use of C99 long long integer constant .-Wlong-long." "use long long" { target *-*-* } 4 }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-traditional.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-traditional.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-traditional.c (revision 0)
@@ -0,0 +1,23 @@
+// { dg-do compile }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wtraditional -Wno-deprecated -Wno-long-long" }
+
+#assert x(x)         // { dg-warning "suggest hiding #assert from traditional C with an indented # .-Wtraditional." }
+
+ #define X X         // { dg-warning "traditional C ignores #define with the # indented .-Wtraditional." }
+
+#if 0
+#elif 1              // { dg-warning "suggest not using #elif in traditional C .-Wtraditional." }
+#endif
+
+#define f(X) X
+int f;               // { dg-warning "function-like macro \"f\" must be used with arguments in traditional C .-Wtraditional." }
+
+#if 0U               // { dg-warning "traditional C rejects the \"U\" suffix .-Wtraditional." }
+#endif
+
+#if +1               // { dg-warning " traditional C rejects the unary plus operator .-Wtraditional." }
+#endif
+
+char *x = "\x0";     // { dg-warning "the meaning of '.x' is different in traditional C .-Wtraditional." }
+char *y = "\a";      // { dg-warning "the meaning of '.a' is different in traditional C .-Wtraditional." }
+char *z = "\u0F43";  // { dg-warning "the meaning of '.u' is different in traditional C .-Wtraditional." }
Index: gcc/testsuite/gcc.dg/cpp/warn-variadic-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-variadic-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-variadic-2.c (revision 0)
@@ -0,0 +1,6 @@
+/* { dg-do preprocess } */
+/* { dg-options "-ansi -fdiagnostics-show-option -pedantic -Werror=variadic-macros" } */
+
+#define F(...) X   /* { dg-error "anonymous variadic macros were introduced in C99 .-Wvariadic-macros." } */
+
+#define G(X...) X  /* { dg-error "ISO C does not permit named variadic macros .-Wvariadic-macros." } */
Index: gcc/testsuite/gcc.dg/cpp/warn-undef.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-undef.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-undef.c (revision 0)
@@ -0,0 +1,5 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wundef" }
+
+#if x  // { dg-warning "\"x\" is not defined .-Wundef." }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-normalized-1.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-normalized-1.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-normalized-1.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -fextended-identifiers -Wnormalized=nfc" }
+
+\u0F43  // { dg-warning "`.U00000f43' is not in NFC .-Wnormalized=." }
Index: gcc/testsuite/gcc.dg/cpp/warning-directive-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warning-directive-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warning-directive-2.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=cpp" }
+
+#warning "Printed"  // { dg-error "\"Printed\" .-Wcpp." }
Index: gcc/testsuite/gcc.dg/cpp/warn-long-long-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-long-long-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-long-long-2.c (revision 0)
@@ -0,0 +1,6 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wtraditional -Werror=long-long" }
+
+#if 0LL  // { dg-error "traditional C rejects the \"LL\" suffix .-Wlong-long." }
+         // { dg-error "use of C99 long long integer constant .-Wlong-long." "use long long" { target *-*-* } 4 }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-variadic.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-variadic.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-variadic.c (revision 0)
@@ -0,0 +1,6 @@
+/* { dg-do preprocess } */
+/* { dg-options "-ansi -fdiagnostics-show-option -pedantic -Wvariadic-macros" } */
+
+#define F(...) X   /* { dg-warning "anonymous variadic macros were introduced in C99 .-Wvariadic-macros." } */
+
+#define G(X...) X  /* { dg-warning "ISO C does not permit named variadic macros .-Wvariadic-macros." } */
Index: gcc/testsuite/gcc.dg/cpp/warn-normalized-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-normalized-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-normalized-2.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -fextended-identifiers -Wnormalized=nfkc" }
+
+\u00AA  // { dg-warning "`.U000000aa' is not in NFKC .-Wnormalized=." }
Index: gcc/testsuite/gcc.dg/cpp/warning-directive-3.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warning-directive-3.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warning-directive-3.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror -Wno-error=cpp" }
+
+#warning "Printed"  // { dg-warning "\"Printed\" .-Wcpp." }
Index: gcc/testsuite/gcc.dg/cpp/warn-deprecated-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-deprecated-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-deprecated-2.c (revision 0)
@@ -0,0 +1,7 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=deprecated" }
+
+#assert x(x)  // { dg-error "#assert is a deprecated GCC extension .-Wdeprecated." }
+
+#if #x(x)     // { dg-error "assertions are a deprecated extension .-Wdeprecated." }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-trigraphs-1.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-trigraphs-1.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-trigraphs-1.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -trigraphs -Wtrigraphs" }
+
+??=  // { dg-warning "trigraph \\?\\?= converted to # .-Wtrigraphs." }
Index: gcc/testsuite/gcc.dg/cpp/warn-multichar-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-multichar-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-multichar-2.c (revision 0)
@@ -0,0 +1,5 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=multichar" }
+
+#if 'abc'  // { dg-error "multi-character character constant .-Wmultichar." }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-normalized-3.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-normalized-3.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-normalized-3.c (revision 0)
@@ -0,0 +1,5 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -fextended-identifiers -Werror=normalized=" }
+
+        // { dg-prune-output ".*-Werror=normalized=: Set -Wnormalized=nfc.*" }
+\u0F43  // { dg-error "`.U00000f43' is not in NFC .-Wnormalized=." }
Index: gcc/testsuite/gcc.dg/cpp/warning-directive-4.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warning-directive-4.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warning-directive-4.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wno-cpp" }
+
+#warning "Not printed"  // { dg-bogus "." }
Index: gcc/testsuite/gcc.dg/cpp/warn-unused-macros.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-unused-macros.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-unused-macros.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wunused-macros" }
+
+#define X X  // { dg-warning "macro \"X\" is not used .-Wunused-macros." }
Index: gcc/testsuite/gcc.dg/cpp/warn-trigraphs-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-trigraphs-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-trigraphs-2.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wtrigraphs" }
+
+??=  // { dg-warning "trigraph \\?\\?= ignored, use -trigraphs to enable .-Wtrigraphs." }
Index: gcc/testsuite/gcc.dg/cpp/warn-cxx-compat-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-cxx-compat-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-cxx-compat-2.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=c++-compat" }
+
+#define not !  // { dg-error "identifier \"not\" is a special operator name in C\\+\\+ .-Wc\\+\\+-compat." }
Index: gcc/testsuite/gcc.dg/cpp/warn-cxx-compat.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-cxx-compat.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-cxx-compat.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wc++-compat" }
+
+#define not !  // { dg-warning "identifier \"not\" is a special operator name in C\\+\\+ .-Wc\\+\\+-compat." }
Index: gcc/testsuite/gcc.dg/cpp/warn-redefined.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-redefined.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-redefined.c (revision 0)
@@ -0,0 +1,18 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wbuiltin-macro-redefined" }
+
+#ifndef __TIME__
+#error "__TIME__ builtin is not defined"
+// { dg-bogus "__TIME__ builtin is not defined" "no-time" { target *-*-* } 5 }
+#endif
+
+#define __TIME__ "X"  // { dg-warning "\"__TIME__\" redefined .-Wbuiltin-macro-redefined." }
+
+#define __TIME__ "Y"  // { dg-bogus "-Wbuiltin-macro-redefined" }
+                      // { dg-warning "\"__TIME__\" redefined" "not-builtin-1" { target *-*-* } 11 }
+                      // { dg-message "previous definition" "previous-1" { target *-*-* } 9 }
+
+#define X "X"
+#define X "Y"         // { dg-bogus "-Wbuiltin-macro-redefined" }
+                      // { dg-warning "\"X\" redefined" "not-builtin-2" { target *-*-* } 16 }
+                      // { dg-message "previous definition" "previous-2" { target *-*-* } 15 }
Index: gcc/testsuite/gcc.dg/cpp/warn-trigraphs-3.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-trigraphs-3.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-trigraphs-3.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -trigraphs -Werror=trigraphs" }
+
+??=  // { dg-error "trigraph \\?\\?= converted to # .-Wtrigraphs." }
Index: gcc/testsuite/gcc.dg/cpp/warn-unused-macros-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-unused-macros-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-unused-macros-2.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=unused-macros" }
+
+#define X X  // { dg-error "macro \"X\" is not used .-Wunused-macros." }
Index: gcc/testsuite/gcc.dg/cpp/warn-deprecated.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-deprecated.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-deprecated.c (revision 0)
@@ -0,0 +1,7 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wdeprecated" }
+
+#assert x(x)  // { dg-warning "#assert is a deprecated GCC extension .-Wdeprecated." }
+
+#if #x(x)     // { dg-warning "assertions are a deprecated extension .-Wdeprecated." }
+#endif
Index: gcc/testsuite/gcc.dg/cpp/warn-trigraphs-4.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-trigraphs-4.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-trigraphs-4.c (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=trigraphs" }
+
+??=  // { dg-error "trigraph \\?\\?= ignored, use -trigraphs to enable .-Wtrigraphs." }
Index: gcc/testsuite/gcc.dg/cpp/warn-redefined-2.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-redefined-2.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-redefined-2.c (revision 0)
@@ -0,0 +1,18 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Werror=builtin-macro-redefined" }
+
+#ifndef __TIME__
+#error "__TIME__ builtin is not defined"
+// { dg-bogus "__TIME__ builtin is not defined" "no-time" { target *-*-* } 5 }
+#endif
+
+#define __TIME__ "X"  // { dg-error "\"__TIME__\" redefined .-Wbuiltin-macro-redefined." }
+
+#define __TIME__ "Y"  // { dg-bogus "-Wbuiltin-macro-redefined" }
+                      // { dg-warning "\"__TIME__\" redefined" "not-builtin-1" { target *-*-* } 11 }
+                      // { dg-message "previous definition" "previous-1" { target *-*-* } 9 }
+
+#define X "X"
+#define X "Y"         // { dg-bogus "-Wbuiltin-macro-redefined" }
+                      // { dg-warning "\"X\" redefined" "not-builtin-2" { target *-*-* } 16 }
+                      // { dg-message "previous definition" "previous-2" { target *-*-* } 15 }
Index: gcc/testsuite/gcc.dg/cpp/warn-comments.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-comments.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-comments.c (revision 0)
@@ -0,0 +1,7 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wcomments" }
+
+/* /* */  // { dg-warning "\"\.\*\" within comment .-Wcomments." }
+
+// \
+          // { dg-warning "multi-line comment .-Wcomments." "multi-line" { target *-*-* } 6 }
Index: gcc/testsuite/gcc.dg/cpp/warn-multichar.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/warn-multichar.c (revision 0)
+++ gcc/testsuite/gcc.dg/cpp/warn-multichar.c (revision 0)
@@ -0,0 +1,5 @@
+// { dg-do preprocess }
+// { dg-options "-std=gnu99 -fdiagnostics-show-option -Wmultichar" }
+
+#if 'abc'  // { dg-warning "multi-character character constant .-Wmultichar." }
+#endif
Index: gcc/testsuite/g++.dg/cpp/warning-directive-1.C
===================================================================
--- gcc/testsuite/g++.dg/cpp/warning-directive-1.C (revision 0)
+++ gcc/testsuite/g++.dg/cpp/warning-directive-1.C (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-fdiagnostics-show-option" }
+
+#warning "Printed"  // { dg-warning "\"Printed\" .-Wcpp." }
Index: gcc/testsuite/g++.dg/cpp/warning-directive-2.C
===================================================================
--- gcc/testsuite/g++.dg/cpp/warning-directive-2.C (revision 0)
+++ gcc/testsuite/g++.dg/cpp/warning-directive-2.C (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-fdiagnostics-show-option -Werror=cpp" }
+
+#warning "Printed"  // { dg-error "\"Printed\" .-Wcpp." }
Index: gcc/testsuite/g++.dg/cpp/warning-directive-3.C
===================================================================
--- gcc/testsuite/g++.dg/cpp/warning-directive-3.C (revision 0)
+++ gcc/testsuite/g++.dg/cpp/warning-directive-3.C (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-fdiagnostics-show-option -Werror -Wno-error=cpp" }
+
+#warning "Printed"  // { dg-warning "\"Printed\" .-Wcpp." }
Index: gcc/testsuite/g++.dg/cpp/warning-directive-4.C
===================================================================
--- gcc/testsuite/g++.dg/cpp/warning-directive-4.C (revision 0)
+++ gcc/testsuite/g++.dg/cpp/warning-directive-4.C (revision 0)
@@ -0,0 +1,4 @@
+// { dg-do preprocess }
+// { dg-options "-fdiagnostics-show-option -Wno-cpp" }
+
+#warning "Not printed"  // { dg-bogus "." }
Index: gcc/testsuite/gfortran.dg/warning-directive-1.F90
===================================================================
--- gcc/testsuite/gfortran.dg/warning-directive-1.F90 (revision 0)
+++ gcc/testsuite/gfortran.dg/warning-directive-1.F90 (revision 0)
@@ -0,0 +1,5 @@
+! { dg-do preprocess }
+! { dg-options "-std=f95 -fdiagnostics-show-option" }
+
+#warning "Printed"
+! { dg-warning "\"Printed\" .-Wcpp." "" { target *-*-* } 4 }
Index: gcc/testsuite/gfortran.dg/warning-directive-3.F90
===================================================================
--- gcc/testsuite/gfortran.dg/warning-directive-3.F90 (revision 0)
+++ gcc/testsuite/gfortran.dg/warning-directive-3.F90 (revision 0)
@@ -0,0 +1,5 @@
+! { dg-do preprocess }
+! { dg-options "-std=f95 -fdiagnostics-show-option -Werror -Wno-error=cpp" }
+
+#warning "Printed"
+! { dg-warning "\"Printed\" .-Wcpp." "" { target *-*-* } 4 }
Index: gcc/testsuite/gfortran.dg/warning-directive-2.F90
===================================================================
--- gcc/testsuite/gfortran.dg/warning-directive-2.F90 (revision 0)
+++ gcc/testsuite/gfortran.dg/warning-directive-2.F90 (revision 0)
@@ -0,0 +1,5 @@
+! { dg-do preprocess }
+! { dg-options "-std=f95 -fdiagnostics-show-option -Werror=cpp" }
+
+#warning "Printed"
+! { dg-error "\"Printed\" .-Wcpp." "" { target *-*-* } 4 }
Index: gcc/testsuite/gfortran.dg/warning-directive-4.F90
===================================================================
--- gcc/testsuite/gfortran.dg/warning-directive-4.F90 (revision 0)
+++ gcc/testsuite/gfortran.dg/warning-directive-4.F90 (revision 0)
@@ -0,0 +1,5 @@
+! { dg-do preprocess }
+! { dg-options "-std=f95 -fdiagnostics-show-option -Wno-cpp" }
+
+#warning "Not printed"
+! { dg-bogus "." "" { target *-*-* } 4 }
Index: gcc/c-tree.h
===================================================================
--- gcc/c-tree.h (revision 153803)
+++ gcc/c-tree.h (working copy)
@@ -608,8 +608,8 @@ extern void c_write_global_declarations
 extern void pedwarn_c90 (location_t, int opt, const char *, ...) ATTRIBUTE_GCC_CDIAG(3,4);
 extern void pedwarn_c99 (location_t, int opt, const char *, ...) ATTRIBUTE_GCC_CDIAG(3,4);
 
-extern bool c_cpp_error (cpp_reader *, int, location_t, unsigned int,
+extern bool c_cpp_error (cpp_reader *, int, int, location_t, unsigned int,
  const char *, va_list *)
-     ATTRIBUTE_GCC_CDIAG(5,0);
+     ATTRIBUTE_GCC_CDIAG(6,0);
 
 #endif /* ! GCC_C_TREE_H */
Index: gcc/opts.c
===================================================================
--- gcc/opts.c (revision 153803)
+++ gcc/opts.c (working copy)
@@ -2364,6 +2364,20 @@ set_option (const struct cl_option *opti
     }
 }
 
+
+/* Callback function, called when -Werror= enables a warning.  */
+
+static void (*warning_as_error_callback) (int) = NULL;
+
+/* Register a callback for enable_warning_as_error calls.  */
+
+void
+register_warning_as_error_callback (void (*callback) (int))
+{
+  gcc_assert (warning_as_error_callback == NULL || callback == NULL);
+  warning_as_error_callback = callback;
+}
+
 /* Enable a warning option as an error.  This is used by -Werror= and
    also by legacy Werror-implicit-function-declaration.  */
 
@@ -2383,14 +2397,20 @@ enable_warning_as_error (const char *arg
     }
   else
     {
-      diagnostic_t kind = value ? DK_ERROR : DK_WARNING;
+      const diagnostic_t kind = value ? DK_ERROR : DK_WARNING;
+
       diagnostic_classify_diagnostic (global_dc, option_index, kind);
-      
-      /* -Werror=foo implies -Wfoo.  */
-      if (cl_options[option_index].var_type == CLVC_BOOLEAN
-  && cl_options[option_index].flag_var
-  && kind == DK_ERROR)
- *(int *) cl_options[option_index].flag_var = 1;
+      if (kind == DK_ERROR)
+        {
+  const struct cl_option * const option = cl_options + option_index;
+
+  /* -Werror=foo implies -Wfoo.  */
+  if (option->var_type == CLVC_BOOLEAN && option->flag_var)
+    *(int *) option->flag_var = 1;
+
+  if (warning_as_error_callback)
+    warning_as_error_callback (option_index);
+ }
     }
   free (new_option);
 }
Index: gcc/opts.h
===================================================================
--- gcc/opts.h (revision 153803)
+++ gcc/opts.h (working copy)
@@ -105,6 +105,7 @@ extern int option_enabled (int opt_idx);
 extern bool get_option_state (int, struct cl_option_state *);
 extern void set_option (const struct cl_option *, int, const char *);
 
+extern void register_warning_as_error_callback (void (*callback) (int));
 extern void enable_warning_as_error (const char *arg, int value,
      unsigned int lang_mask);
 extern void print_ignored_options (void);
Index: gcc/fortran/cpp.c
===================================================================
--- gcc/fortran/cpp.c (revision 153803)
+++ gcc/fortran/cpp.c (working copy)
@@ -137,9 +137,9 @@ static void cb_include (cpp_reader *, so
 static void cb_ident (cpp_reader *, source_location, const cpp_string *);
 static void cb_used_define (cpp_reader *, source_location, cpp_hashnode *);
 static void cb_used_undef (cpp_reader *, source_location, cpp_hashnode *);
-static bool cb_cpp_error (cpp_reader *, int, location_t, unsigned int,
+static bool cb_cpp_error (cpp_reader *, int, int, location_t, unsigned int,
   const char *, va_list *)
-     ATTRIBUTE_GCC_DIAG(5,0);
+     ATTRIBUTE_GCC_DIAG(6,0);
 void pp_dir_change (cpp_reader *, const char *);
 
 static int dump_macro (cpp_reader *, cpp_hashnode *, void *);
@@ -962,13 +962,14 @@ cb_used_define (cpp_reader *pfile, sourc
 }
 
 /* Callback from cpp_error for PFILE to print diagnostics from the
-   preprocessor.  The diagnostic is of type LEVEL, at location
+   preprocessor.  The diagnostic is of type LEVEL, with REASON set
+   to the reason code if LEVEL is represents a warning, at location
    LOCATION, with column number possibly overridden by COLUMN_OVERRIDE
    if not zero; MSG is the translated message and AP the arguments.
    Returns true if a diagnostic was emitted, false otherwise.  */
 
 static bool
-cb_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level,
+cb_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason,
       location_t location, unsigned int column_override,
       const char *msg, va_list *ap)
 {
@@ -1007,6 +1008,8 @@ cb_cpp_error (cpp_reader *pfile ATTRIBUT
   location, dlevel);
   if (column_override)
     diagnostic_override_column (&diagnostic, column_override);
+  if (reason == CPP_W_WARNING_DIRECTIVE)
+    diagnostic_override_option_index (&diagnostic, OPT_Wcpp);
   ret = report_diagnostic (&diagnostic);
   if (level == CPP_DL_WARNING_SYSHDR)
     warn_system_headers = save_warn_system_headers;
@@ -1090,5 +1093,3 @@ dump_queued_macros (cpp_reader *pfile AT
     }
   cpp_undefine_queue = NULL;
 }
-
-
Index: gcc/c-opts.c
===================================================================
--- gcc/c-opts.c (revision 153803)
+++ gcc/c-opts.c (working copy)
@@ -196,6 +196,90 @@ defer_opt (enum opt_code code, const cha
   deferred_count++;
 }
 
+/* -Werror= may set a warning option to enable a warning that is emitted
+   by the preprocessor.  Set any corresponding flag in cpp_opts.  */
+
+static void
+warning_as_error_callback (int option_index)
+{
+  switch (option_index)
+    {
+      default:
+ /* Ignore options not associated with the preprocessor.  */
+ break;
+
+      case OPT_Wdeprecated:
+ cpp_opts->warn_deprecated = 1;
+ break;
+
+      case OPT_Wcomment:
+      case OPT_Wcomments:
+ cpp_opts->warn_comments = 1;
+ break;
+
+      case OPT_Wtrigraphs:
+ cpp_opts->warn_trigraphs = 1;
+ break;
+
+      case OPT_Wmultichar:
+ cpp_opts->warn_multichar = 1;
+ break;
+
+      case OPT_Wtraditional:
+ cpp_opts->warn_traditional = 1;
+ break;
+
+      case OPT_Wlong_long:
+ cpp_opts->warn_long_long = 1;
+ break;
+
+      case OPT_Wendif_labels:
+ cpp_opts->warn_endif_labels = 1;
+ break;
+
+      case OPT_Wvariadic_macros:
+ /* Set the local flag that is used later to update cpp_opts.  */
+ warn_variadic_macros = 1;
+ break;
+
+      case OPT_Wbuiltin_macro_redefined:
+ cpp_opts->warn_builtin_macro_redefined = 1;
+ break;
+
+      case OPT_Wundef:
+ cpp_opts->warn_undef = 1;
+ break;
+
+      case OPT_Wunused_macros:
+ /* Set the local flag that is used later to update cpp_opts.  */
+ warn_unused_macros = 1;
+ break;
+
+      case OPT_Wc___compat:
+ /* Add warnings in the same way as c_common_handle_option below.  */
+ if (warn_enum_compare == -1)
+  warn_enum_compare = 1;
+ if (warn_jump_misses_init == -1)
+  warn_jump_misses_init = 1;
+ cpp_opts->warn_cxx_operator_names = 1;
+ break;
+
+      case OPT_Wnormalized_:
+ inform (input_location, "-Werror=normalized=: Set -Wnormalized=nfc");
+ cpp_opts->warn_normalize = normalized_C;
+ break;
+
+      case OPT_Winvalid_pch:
+ cpp_opts->warn_invalid_pch = 1;
+ break;
+
+      case OPT_Wcpp:
+ /* Handled by standard diagnostics using the option's associated
+   boolean variable.  */
+ break;
+    }
+}
+
 /* Common initialization before parsing options.  */
 unsigned int
 c_common_init_options (unsigned int argc, const char **argv)
@@ -204,6 +288,9 @@ c_common_init_options (unsigned int argc
   unsigned int i, result;
   struct cpp_callbacks *cb;
 
+  /* Register callback for warnings enabled by -Werror=.  */
+  register_warning_as_error_callback (warning_as_error_callback);
+
   /* This is conditionalized only because that is the way the front
      ends used to do it.  Maybe this should be unconditional?  */
   if (c_dialect_cxx ())
Index: gcc/common.opt
===================================================================
--- gcc/common.opt (revision 153803)
+++ gcc/common.opt (working copy)
@@ -89,6 +89,10 @@ Wcast-align
 Common Var(warn_cast_align) Warning
 Warn about pointer casts which increase alignment
 
+Wcpp
+Common Var(warn_cpp) Init(1) Warning
+Warn when a #warning directive is encountered
+
 Wdeprecated-declarations
 Common Var(warn_deprecated_decl) Init(1) Warning
 Warn about uses of __attribute__((deprecated)) declarations
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c (revision 153803)
+++ gcc/c-common.c (working copy)
@@ -8245,8 +8245,52 @@ c_parse_error (const char *gmsgid, enum
 #undef catenate_messages
 }
 
+/* Mapping for cpp message reasons to the options that enable them.  */
+
+struct reason_option_codes_t
+{
+  const int reason; /* cpplib message reason.  */
+  const int option_code; /* gcc option that controls this message.  */
+};
+
+static const struct reason_option_codes_t option_codes[] = {
+  {CPP_W_DEPRECATED, OPT_Wdeprecated},
+  {CPP_W_COMMENTS, OPT_Wcomments},
+  {CPP_W_TRIGRAPHS, OPT_Wtrigraphs},
+  {CPP_W_MULTICHAR, OPT_Wmultichar},
+  {CPP_W_TRADITIONAL, OPT_Wtraditional},
+  {CPP_W_LONG_LONG, OPT_Wlong_long},
+  {CPP_W_ENDIF_LABELS, OPT_Wendif_labels},
+  {CPP_W_VARIADIC_MACROS, OPT_Wvariadic_macros},
+  {CPP_W_BUILTIN_MACRO_REDEFINED, OPT_Wbuiltin_macro_redefined},
+  {CPP_W_UNDEF, OPT_Wundef},
+  {CPP_W_UNUSED_MACROS, OPT_Wunused_macros},
+  {CPP_W_CXX_OPERATOR_NAMES, OPT_Wc___compat},
+  {CPP_W_NORMALIZE, OPT_Wnormalized_},
+  {CPP_W_INVALID_PCH, OPT_Winvalid_pch},
+  {CPP_W_WARNING_DIRECTIVE, OPT_Wcpp},
+  {CPP_W_NONE, 0}
+};
+
+/* Return the gcc option code associated with the reason for a cpp
+   message, or 0 if none.  */
+
+static int
+c_option_controlling_cpp_error (int reason)
+{
+  const struct reason_option_codes_t *entry;
+
+  for (entry = option_codes; entry->reason != CPP_W_NONE; entry++)
+    {
+      if (entry->reason == reason)
+ return entry->option_code;
+    }
+  return 0;
+}
+
 /* Callback from cpp_error for PFILE to print diagnostics from the
-   preprocessor.  The diagnostic is of type LEVEL, at location
+   preprocessor.  The diagnostic is of type LEVEL, with REASON set
+   to the reason code if LEVEL is represents a warning, at location
    LOCATION unless this is after lexing and the compiler's location
    should be used instead, with column number possibly overridden by
    COLUMN_OVERRIDE if not zero; MSG is the translated message and AP
@@ -8254,7 +8298,7 @@ c_parse_error (const char *gmsgid, enum
    otherwise.  */
 
 bool
-c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level,
+c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason,
      location_t location, unsigned int column_override,
      const char *msg, va_list *ap)
 {
@@ -8301,6 +8345,8 @@ c_cpp_error (cpp_reader *pfile ATTRIBUTE
   location, dlevel);
   if (column_override)
     diagnostic_override_column (&diagnostic, column_override);
+  diagnostic_override_option_index (&diagnostic,
+                                    c_option_controlling_cpp_error (reason));
   ret = report_diagnostic (&diagnostic);
   if (level == CPP_DL_WARNING_SYSHDR)
     warn_system_headers = save_warn_system_headers;
Index: libcpp/macro.c
===================================================================
--- libcpp/macro.c (revision 153803)
+++ libcpp/macro.c (working copy)
@@ -83,8 +83,8 @@ _cpp_warn_if_unused_macro (cpp_reader *p
 
       if (!macro->used
   && MAIN_FILE_P (linemap_lookup (pfile->line_table, macro->line)))
- cpp_error_with_line (pfile, CPP_DL_WARNING, macro->line, 0,
-     "macro \"%s\" is not used", NODE_NAME (node));
+ cpp_warning_with_line (pfile, CPP_W_UNUSED_MACROS, macro->line, 0,
+       "macro \"%s\" is not used", NODE_NAME (node));
     }
 
   return 1;
@@ -860,9 +860,9 @@ enter_macro_context (cpp_reader *pfile,
   if (buff == NULL)
     {
       if (CPP_WTRADITIONAL (pfile) && ! node->value.macro->syshdr)
- cpp_error (pfile, CPP_DL_WARNING,
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
  "function-like macro \"%s\" must be used with arguments in traditional C",
-   NODE_NAME (node));
+     NODE_NAME (node));
 
       if (pragma_buff)
  _cpp_release_buff (pfile, pragma_buff);
@@ -1582,13 +1582,14 @@ parse_params (cpp_reader *pfile, cpp_mac
       if (! CPP_OPTION (pfile, c99)
   && CPP_OPTION (pfile, pedantic)
   && CPP_OPTION (pfile, warn_variadic_macros))
- cpp_error (pfile, CPP_DL_PEDWARN,
-   "anonymous variadic macros were introduced in C99");
+ cpp_pedwarning
+                  (pfile, CPP_W_VARIADIC_MACROS,
+   "anonymous variadic macros were introduced in C99");
     }
   else if (CPP_OPTION (pfile, pedantic)
    && CPP_OPTION (pfile, warn_variadic_macros))
-    cpp_error (pfile, CPP_DL_PEDWARN,
-       "ISO C does not permit named variadic macros");
+    cpp_pedwarning (pfile, CPP_W_VARIADIC_MACROS,
+            "ISO C does not permit named variadic macros");
 
   /* We're at the end, and just expect a closing parenthesis.  */
   token = _cpp_lex_token (pfile);
@@ -1891,10 +1892,14 @@ _cpp_create_definition (cpp_reader *pfil
 
       if (warn_of_redefinition (pfile, node, macro))
  {
+          const int reason = (node->flags & NODE_BUILTIN)
+                             ? CPP_W_BUILTIN_MACRO_REDEFINED : CPP_W_NONE;
   bool warned;
-  warned = cpp_error_with_line (pfile, CPP_DL_PEDWARN,
- pfile->directive_line, 0,
- "\"%s\" redefined", NODE_NAME (node));
+
+  warned = cpp_pedwarning_with_line (pfile, reason,
+     pfile->directive_line, 0,
+     "\"%s\" redefined",
+                                             NODE_NAME (node));
 
   if (warned && node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
     cpp_error_with_line (pfile, CPP_DL_NOTE,
Index: libcpp/Makefile.in
===================================================================
--- libcpp/Makefile.in (revision 153803)
+++ libcpp/Makefile.in (working copy)
@@ -249,8 +249,15 @@ po/$(PACKAGE).pot: $(libcpp_a_SOURCES)
  $(mkinstalldirs) $(srcdir)/po
  $(XGETTEXT) --default-domain=$(PACKAGE) \
   --keyword=_ --keyword=N_ \
-  --keyword=cpp_error:3 --keyword=cpp_errno:3 \
+  --keyword=cpp_error:3 \
+  --keyword=cpp_warning:3 \
+  --keyword=cpp_pedwarning:3 \
+  --keyword=cpp_warning_syshdr:3 \
   --keyword=cpp_error_with_line:5 \
+  --keyword=cpp_warning_with_line:5 \
+  --keyword=cpp_pedwarning_with_line:5 \
+  --keyword=cpp_warning_with_line_syshdr:5 \
+  --keyword=cpp_errno:3 \
   --keyword=SYNTAX_ERROR --keyword=SYNTAX_ERROR2 \
   --copyright-holder="Free Software Foundation, Inc." \
   --msgid-bugs-address="http://gcc.gnu.org/bugs.html" \
Index: libcpp/directives.c
===================================================================
--- libcpp/directives.c (revision 153803)
+++ libcpp/directives.c (working copy)
@@ -104,7 +104,7 @@ static const char *parse_include (cpp_re
 static void push_conditional (cpp_reader *, int, int, const cpp_hashnode *);
 static unsigned int read_flag (cpp_reader *, unsigned int);
 static bool strtolinenum (const uchar *, size_t, linenum_type *, bool *);
-static void do_diagnostic (cpp_reader *, int, int);
+static void do_diagnostic (cpp_reader *, int, int, int);
 static cpp_hashnode *lex_macro_node (cpp_reader *, bool);
 static int undefine_macros (cpp_reader *, cpp_hashnode *, void *);
 static void do_include_common (cpp_reader *, enum include_type);
@@ -353,8 +353,8 @@ directive_diagnostics (cpp_reader *pfile
       else if (((dir->flags & DEPRECATED) != 0
  || (dir == &dtable[T_IMPORT] && !CPP_OPTION (pfile, objc)))
        && CPP_OPTION (pfile, warn_deprecated))
- cpp_error (pfile, CPP_DL_WARNING, "#%s is a deprecated GCC extension",
-   dir->name);
+ cpp_warning (pfile, CPP_W_DEPRECATED,
+                     "#%s is a deprecated GCC extension", dir->name);
     }
 
   /* Traditionally, a directive is ignored unless its # is in
@@ -366,16 +366,16 @@ directive_diagnostics (cpp_reader *pfile
   if (CPP_WTRADITIONAL (pfile))
     {
       if (dir == &dtable[T_ELIF])
- cpp_error (pfile, CPP_DL_WARNING,
-   "suggest not using #elif in traditional C");
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+     "suggest not using #elif in traditional C");
       else if (indented && dir->origin == KANDR)
- cpp_error (pfile, CPP_DL_WARNING,
-   "traditional C ignores #%s with the # indented",
-   dir->name);
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+     "traditional C ignores #%s with the # indented",
+     dir->name);
       else if (!indented && dir->origin != KANDR)
- cpp_error (pfile, CPP_DL_WARNING,
-   "suggest hiding #%s from traditional C with an indented #",
-   dir->name);
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+     "suggest hiding #%s from traditional C with an indented #",
+     dir->name);
     }
 }
 
@@ -1043,7 +1043,7 @@ _cpp_do_file_change (cpp_reader *pfile,
 /* Report a warning or error detected by the program we are
    processing.  Use the directive's tokens in the error message.  */
 static void
-do_diagnostic (cpp_reader *pfile, int code, int print_dir)
+do_diagnostic (cpp_reader *pfile, int code, int reason, int print_dir)
 {
   const unsigned char *dir_name;
   unsigned char *line;
@@ -1057,21 +1057,26 @@ do_diagnostic (cpp_reader *pfile, int co
   line = cpp_output_line_to_string (pfile, dir_name);
   pfile->state.prevent_expansion--;
 
-  cpp_error_with_line (pfile, code, src_loc, 0, "%s", line);
+  if (code == CPP_DL_WARNING_SYSHDR && reason)
+    cpp_warning_with_line_syshdr (pfile, reason, src_loc, 0, "%s", line);
+  else if (code == CPP_DL_WARNING && reason)
+    cpp_warning_with_line (pfile, reason, src_loc, 0, "%s", line);
+  else
+    cpp_error_with_line (pfile, code, src_loc, 0, "%s", line);
   free (line);
 }
 
 static void
 do_error (cpp_reader *pfile)
 {
-  do_diagnostic (pfile, CPP_DL_ERROR, 1);
+  do_diagnostic (pfile, CPP_DL_ERROR, 0, 1);
 }
 
 static void
 do_warning (cpp_reader *pfile)
 {
   /* We want #warning diagnostics to be emitted in system headers too.  */
-  do_diagnostic (pfile, CPP_DL_WARNING_SYSHDR, 1);
+  do_diagnostic (pfile, CPP_DL_WARNING_SYSHDR, CPP_W_WARNING_DIRECTIVE, 1);
 }
 
 /* Report program identification.  */
@@ -1501,7 +1506,7 @@ do_pragma_dependency (cpp_reader *pfile)
       if (cpp_get_token (pfile)->type != CPP_EOF)
  {
   _cpp_backup_tokens (pfile, 1);
-  do_diagnostic (pfile, CPP_DL_WARNING, 0);
+  do_diagnostic (pfile, CPP_DL_WARNING, 0, 0);
  }
     }
 
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h (revision 153803)
+++ libcpp/include/cpplib.h (working copy)
@@ -497,9 +497,9 @@ struct cpp_callbacks
 
   /* Called to emit a diagnostic.  This callback receives the
      translated message.  */
-  bool (*error) (cpp_reader *, int, source_location, unsigned int,
+  bool (*error) (cpp_reader *, int, int, source_location, unsigned int,
  const char *, va_list *)
-       ATTRIBUTE_FPTR_PRINTF(5,0);
+       ATTRIBUTE_FPTR_PRINTF(6,0);
 
   /* Callbacks for when a macro is expanded, or tested (whether
      defined or not at the time) in #ifdef, #ifndef or "defined".  */
@@ -826,25 +826,57 @@ cpp_num cpp_num_sign_extend (cpp_num, si
    position in the translation unit with it, use cpp_error_with_line
    with a line number of zero.  */
 
-/* Warning, an error with -Werror.  */
-#define CPP_DL_WARNING 0x00
-/* Same as CPP_DL_WARNING, except it is not suppressed in system headers.  */
-#define CPP_DL_WARNING_SYSHDR 0x01
-/* Warning, an error with -pedantic-errors or -Werror.  */
-#define CPP_DL_PEDWARN 0x02
-/* An error.  */
-#define CPP_DL_ERROR 0x03
-/* An internal consistency check failed.  Prints "internal error: ",
-   otherwise the same as CPP_DL_ERROR.  */
-#define CPP_DL_ICE 0x04
-/* An informative note following a warning.  */
-#define CPP_DL_NOTE 0x05
-/* A fatal error.  */
-#define CPP_DL_FATAL 0x06
+enum {
+  /* Warning, an error with -Werror.  */
+  CPP_DL_WARNING = 0,
+  /* Same as CPP_DL_WARNING, except it is not suppressed in system headers.  */
+  CPP_DL_WARNING_SYSHDR,
+  /* Warning, an error with -pedantic-errors or -Werror.  */
+  CPP_DL_PEDWARN,
+  /* An error.  */
+  CPP_DL_ERROR,
+  /* An internal consistency check failed.  Prints "internal error: ",
+     otherwise the same as CPP_DL_ERROR.  */
+  CPP_DL_ICE,
+  /* An informative note following a warning.  */
+  CPP_DL_NOTE,
+  /* A fatal error.  */
+  CPP_DL_FATAL
+};
+
+/* Warning reason codes. Use a reason code of zero for unclassified warnings
+   and errors that are not warnings.  */
+enum {
+  CPP_W_NONE = 0,
+  CPP_W_DEPRECATED,
+  CPP_W_COMMENTS,
+  CPP_W_MISSING_INCLUDE_DIRS,
+  CPP_W_TRIGRAPHS,
+  CPP_W_MULTICHAR,
+  CPP_W_TRADITIONAL,
+  CPP_W_LONG_LONG,
+  CPP_W_ENDIF_LABELS,
+  CPP_W_NUM_SIGN_CHANGE,
+  CPP_W_VARIADIC_MACROS,
+  CPP_W_BUILTIN_MACRO_REDEFINED,
+  CPP_W_DOLLARS,
+  CPP_W_UNDEF,
+  CPP_W_UNUSED_MACROS,
+  CPP_W_CXX_OPERATOR_NAMES,
+  CPP_W_NORMALIZE,
+  CPP_W_INVALID_PCH,
+  CPP_W_WARNING_DIRECTIVE
+};
 
 /* Output a diagnostic of some kind.  */
 extern bool cpp_error (cpp_reader *, int, const char *msgid, ...)
   ATTRIBUTE_PRINTF_3;
+extern bool cpp_warning (cpp_reader *, int, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_3;
+extern bool cpp_pedwarning (cpp_reader *, int, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_3;
+extern bool cpp_warning_syshdr (cpp_reader *, int, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_3;
 
 /* Output a diagnostic with "MSGID: " preceding the
    error string of errno.  No location is printed.  */
@@ -853,8 +885,18 @@ extern bool cpp_errno (cpp_reader *, int
 /* Same as cpp_error, except additionally specifies a position as a
    (translation unit) physical line and physical column.  If the line is
    zero, then no location is printed.  */
-extern bool cpp_error_with_line (cpp_reader *, int, source_location, unsigned,
- const char *msgid, ...) ATTRIBUTE_PRINTF_5;
+extern bool cpp_error_with_line (cpp_reader *, int, source_location,
+                                 unsigned, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_5;
+extern bool cpp_warning_with_line (cpp_reader *, int, source_location,
+                                   unsigned, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_5;
+extern bool cpp_pedwarning_with_line (cpp_reader *, int, source_location,
+                                      unsigned, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_5;
+extern bool cpp_warning_with_line_syshdr (cpp_reader *, int, source_location,
+                                          unsigned, const char *msgid, ...)
+  ATTRIBUTE_PRINTF_5;
 
 /* In lex.c */
 extern int cpp_ideq (const cpp_token *, const char *);
Index: libcpp/pch.c
===================================================================
--- libcpp/pch.c (revision 153803)
+++ libcpp/pch.c (working copy)
@@ -480,9 +480,9 @@ cpp_valid_state (cpp_reader *r, const ch
   || h->flags & NODE_POISONED)
  {
   if (CPP_OPTION (r, warn_invalid_pch))
-    cpp_error (r, CPP_DL_WARNING_SYSHDR,
-       "%s: not used because `%.*s' is poisoned",
-       name, m.name_length, namebuf);
+    cpp_warning_syshdr (r, CPP_W_INVALID_PCH,
+                "%s: not used because `%.*s' is poisoned",
+                name, m.name_length, namebuf);
   goto fail;
  }
 
@@ -502,9 +502,9 @@ cpp_valid_state (cpp_reader *r, const ch
     continue;
 
   if (CPP_OPTION (r, warn_invalid_pch))
-    cpp_error (r, CPP_DL_WARNING_SYSHDR,
-       "%s: not used because `%.*s' not defined",
-       name, m.name_length, namebuf);
+    cpp_warning_syshdr (r, CPP_W_INVALID_PCH,
+                "%s: not used because `%.*s' not defined",
+                name, m.name_length, namebuf);
   goto fail;
  }
 
@@ -514,7 +514,7 @@ cpp_valid_state (cpp_reader *r, const ch
   || memcmp (namebuf, newdefn, m.definition_length) != 0)
  {
   if (CPP_OPTION (r, warn_invalid_pch))
-    cpp_error (r, CPP_DL_WARNING_SYSHDR,
+    cpp_warning_syshdr (r, CPP_W_INVALID_PCH,
        "%s: not used because `%.*s' defined as `%s' not `%.*s'",
        name, m.name_length, namebuf, newdefn + m.name_length,
        m.definition_length - m.name_length,
@@ -555,9 +555,9 @@ cpp_valid_state (cpp_reader *r, const ch
       else
  {
   if (CPP_OPTION (r, warn_invalid_pch))
-    cpp_error (r, CPP_DL_WARNING_SYSHDR,
-       "%s: not used because `%s' is defined",
-       name, first);
+    cpp_warning_syshdr (r, CPP_W_INVALID_PCH,
+                "%s: not used because `%s' is defined",
+                name, first);
   goto fail;
  }
     }
@@ -575,9 +575,9 @@ cpp_valid_state (cpp_reader *r, const ch
   if (counter && r->counter)
     {
       if (CPP_OPTION (r, warn_invalid_pch))
- cpp_error (r, CPP_DL_WARNING_SYSHDR,
-   "%s: not used because `__COUNTER__' is invalid",
-   name);
+ cpp_warning_syshdr (r, CPP_W_INVALID_PCH,
+            "%s: not used because `__COUNTER__' is invalid",
+            name);
  goto fail;
     }
 
Index: libcpp/errors.c
===================================================================
--- libcpp/errors.c (revision 153803)
+++ libcpp/errors.c (working copy)
@@ -28,16 +28,16 @@ along with this program; see the file CO
 #include "cpplib.h"
 #include "internal.h"
 
-/* Print an error at the location of the previously lexed token.  */
-bool
-cpp_error (cpp_reader * pfile, int level, const char *msgid, ...)
+/* Print a diagnostic at the location of the previously lexed token.  */
+
+ATTRIBUTE_FPTR_PRINTF(4,0)
+static bool
+cpp_diagnostic (cpp_reader * pfile, int level, int reason,
+                const char *msgid, va_list *ap)
 {
   source_location src_loc;
-  va_list ap;
   bool ret;
 
-  va_start (ap, msgid);
-
   if (CPP_OPTION (pfile, traditional))
     {
       if (pfile->state.in_directive)
@@ -61,13 +61,95 @@ cpp_error (cpp_reader * pfile, int level
 
   if (!pfile->cb.error)
     abort ();
-  ret = pfile->cb.error (pfile, level, src_loc, 0, _(msgid), &ap);
+  ret = pfile->cb.error (pfile, level, reason, src_loc, 0, _(msgid), ap);
+
+  return ret;
+}
+
+/* Print a warning or error, depending on the value of LEVEL.  */
+
+bool
+cpp_error (cpp_reader * pfile, int level, const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic (pfile, level, CPP_W_NONE, msgid, &ap);
 
   va_end (ap);
   return ret;
 }
 
-/* Print an error at a specific location.  */
+/* Print a warning.  The warning reason may be given in REASON.  */
+
+bool
+cpp_warning (cpp_reader * pfile, int reason, const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic (pfile, CPP_DL_WARNING, reason, msgid, &ap);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a pedantic warning.  The warning reason may be given in REASON.  */
+
+bool
+cpp_pedwarning (cpp_reader * pfile, int reason, const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic (pfile, CPP_DL_PEDWARN, reason, msgid, &ap);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a warning, including system headers.  The warning reason may be
+   given in REASON.  */
+
+bool
+cpp_warning_syshdr (cpp_reader * pfile, int reason, const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic (pfile, CPP_DL_WARNING_SYSHDR, reason, msgid, &ap);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a diagnostic at a specific location.  */
+
+ATTRIBUTE_FPTR_PRINTF(6,0)
+static bool
+cpp_diagnostic_with_line (cpp_reader * pfile, int level, int reason,
+          source_location src_loc, unsigned int column,
+          const char *msgid, va_list *ap)
+{
+  bool ret;
+  
+  if (!pfile->cb.error)
+    abort ();
+  ret = pfile->cb.error (pfile, level, reason, src_loc, column, _(msgid), ap);
+
+  return ret;
+}
+
+/* Print a warning or error, depending on the value of LEVEL.  */
+
 bool
 cpp_error_with_line (cpp_reader *pfile, int level,
      source_location src_loc, unsigned int column,
@@ -75,17 +157,77 @@ cpp_error_with_line (cpp_reader *pfile,
 {
   va_list ap;
   bool ret;
-  
+
   va_start (ap, msgid);
 
-  if (!pfile->cb.error)
-    abort ();
-  ret = pfile->cb.error (pfile, level, src_loc, column, _(msgid), &ap);
+  ret = cpp_diagnostic_with_line (pfile, level, CPP_W_NONE, src_loc,
+                                  column, msgid, &ap);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a warning.  The warning reason may be given in REASON.  */
+
+bool
+cpp_warning_with_line (cpp_reader *pfile, int reason,
+       source_location src_loc, unsigned int column,
+       const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic_with_line (pfile, CPP_DL_WARNING, reason, src_loc,
+                                  column, msgid, &ap);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a pedantic warning.  The warning reason may be given in REASON.  */
+
+bool
+cpp_pedwarning_with_line (cpp_reader *pfile, int reason,
+          source_location src_loc, unsigned int column,
+          const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic_with_line (pfile, CPP_DL_PEDWARN, reason, src_loc,
+                                  column, msgid, &ap);
 
   va_end (ap);
   return ret;
 }
 
+/* Print a warning, including system headers.  The warning reason may be
+   given in REASON.  */
+
+bool
+cpp_warning_with_line_syshdr (cpp_reader *pfile, int reason,
+              source_location src_loc, unsigned int column,
+              const char *msgid, ...)
+{
+  va_list ap;
+  bool ret;
+
+  va_start (ap, msgid);
+
+  ret = cpp_diagnostic_with_line (pfile, CPP_DL_WARNING_SYSHDR, reason, src_loc,
+                                  column, msgid, &ap);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a warning or error, depending on the value of LEVEL.  Include
+   information from errno.  */
+
 bool
 cpp_errno (cpp_reader *pfile, int level, const char *msgid)
 {
Index: libcpp/expr.c
===================================================================
--- libcpp/expr.c (revision 153803)
+++ libcpp/expr.c (working copy)
@@ -365,9 +365,9 @@ cpp_classify_number (cpp_reader *pfile,
       if (limit != str
   && CPP_WTRADITIONAL (pfile)
   && ! cpp_sys_macro_p (pfile))
- cpp_error (pfile, CPP_DL_WARNING,
-   "traditional C rejects the \"%.*s\" suffix",
-   (int) (limit - str), str);
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+     "traditional C rejects the \"%.*s\" suffix",
+     (int) (limit - str), str);
 
       /* A suffix for double is a GCC extension via decimal float support.
  If the suffix also specifies an imaginary value we'll catch that
@@ -411,21 +411,27 @@ cpp_classify_number (cpp_reader *pfile,
       if (CPP_WTRADITIONAL (pfile) && ! cpp_sys_macro_p (pfile))
  {
   int u_or_i = (result & (CPP_N_UNSIGNED|CPP_N_IMAGINARY));
-  int large = (result & CPP_N_WIDTH) == CPP_N_LARGE;
+  int large = (result & CPP_N_WIDTH) == CPP_N_LARGE
+       && CPP_OPTION (pfile, warn_long_long);
 
-  if (u_or_i || (large && CPP_OPTION (pfile, warn_long_long)))
-    cpp_error (pfile, CPP_DL_WARNING,
-       "traditional C rejects the \"%.*s\" suffix",
-       (int) (limit - str), str);
+  if (u_or_i || large)
+    cpp_warning (pfile, large ? CPP_W_LONG_LONG : CPP_W_TRADITIONAL,
+         "traditional C rejects the \"%.*s\" suffix",
+         (int) (limit - str), str);
  }
 
       if ((result & CPP_N_WIDTH) == CPP_N_LARGE
   && CPP_OPTION (pfile, warn_long_long))
- cpp_error (pfile,
-   CPP_OPTION (pfile, c99) ? CPP_DL_WARNING : CPP_DL_PEDWARN,
-   CPP_OPTION (pfile, cplusplus)
-   ? "use of C++0x long long integer constant"
-   : "use of C99 long long integer constant");
+        {
+          const char *message = CPP_OPTION (pfile, cplusplus)
+                ? N_("use of C++0x long long integer constant")
+                : N_("use of C99 long long integer constant");
+
+  if (CPP_OPTION (pfile, c99))
+            cpp_warning (pfile, CPP_W_LONG_LONG, message);
+          else
+            cpp_pedwarning (pfile, CPP_W_LONG_LONG, message);
+        }
 
       result |= CPP_N_INTEGER;
     }
@@ -786,8 +792,8 @@ eval_token (cpp_reader *pfile, const cpp
   result.high = 0;
   result.low = 0;
   if (CPP_OPTION (pfile, warn_undef) && !pfile->state.skip_eval)
-    cpp_error (pfile, CPP_DL_WARNING, "\"%s\" is not defined",
-       NODE_NAME (token->val.node.node));
+    cpp_warning (pfile, CPP_W_UNDEF, "\"%s\" is not defined",
+         NODE_NAME (token->val.node.node));
  }
       break;
 
@@ -800,8 +806,8 @@ eval_token (cpp_reader *pfile, const cpp
     cpp_error (pfile, CPP_DL_PEDWARN,
        "assertions are a GCC extension");
   else if (CPP_OPTION (pfile, warn_deprecated))
-    cpp_error (pfile, CPP_DL_WARNING,
-       "assertions are a deprecated extension");
+    cpp_warning (pfile, CPP_W_DEPRECATED,
+         "assertions are a deprecated extension");
  }
       _cpp_test_assertion (pfile, &temp);
       result.high = 0;
@@ -1496,8 +1502,8 @@ num_unary_op (cpp_reader *pfile, cpp_num
     {
     case CPP_UPLUS:
       if (CPP_WTRADITIONAL (pfile) && !pfile->state.skip_eval)
- cpp_error (pfile, CPP_DL_WARNING,
-   "traditional C rejects the unary plus operator");
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+     "traditional C rejects the unary plus operator");
       num.overflow = false;
       break;
 
Index: libcpp/lex.c
===================================================================
--- libcpp/lex.c (revision 153803)
+++ libcpp/lex.c (working copy)
@@ -301,14 +301,16 @@ _cpp_process_line_notes (cpp_reader *pfi
       && (!in_comment || warn_in_comment (pfile, note)))
     {
       if (CPP_OPTION (pfile, trigraphs))
- cpp_error_with_line (pfile, CPP_DL_WARNING, pfile->line_table->highest_line, col,
-     "trigraph ??%c converted to %c",
-     note->type,
-     (int) _cpp_trigraph_map[note->type]);
+ cpp_warning_with_line (pfile, CPP_W_TRIGRAPHS,
+                                       pfile->line_table->highest_line, col,
+       "trigraph ??%c converted to %c",
+       note->type,
+       (int) _cpp_trigraph_map[note->type]);
       else
  {
-  cpp_error_with_line
-    (pfile, CPP_DL_WARNING, pfile->line_table->highest_line, col,
+  cpp_warning_with_line
+    (pfile, CPP_W_TRIGRAPHS,
+                     pfile->line_table->highest_line, col,
      "trigraph ??%c ignored, use -trigraphs to enable",
      note->type);
  }
@@ -353,9 +355,10 @@ _cpp_skip_block_comment (cpp_reader *pfi
       && cur[0] == '*' && cur[1] != '/')
     {
       buffer->cur = cur;
-      cpp_error_with_line (pfile, CPP_DL_WARNING,
-   pfile->line_table->highest_line, CPP_BUF_COL (buffer),
-   "\"/*\" within comment");
+      cpp_warning_with_line (pfile, CPP_W_COMMENTS,
+     pfile->line_table->highest_line,
+     CPP_BUF_COL (buffer),
+     "\"/*\" within comment");
     }
  }
       else if (c == '\n')
@@ -458,11 +461,11 @@ warn_about_normalization (cpp_reader *pf
 
       sz = cpp_spell_token (pfile, token, buf, false) - buf;
       if (NORMALIZE_STATE_RESULT (s) == normalized_C)
- cpp_error_with_line (pfile, CPP_DL_WARNING, token->src_loc, 0,
-     "`%.*s' is not in NFKC", (int) sz, buf);
+ cpp_warning_with_line (pfile, CPP_W_NORMALIZE, token->src_loc, 0,
+       "`%.*s' is not in NFKC", (int) sz, buf);
       else
- cpp_error_with_line (pfile, CPP_DL_WARNING, token->src_loc, 0,
-     "`%.*s' is not in NFC", (int) sz, buf);
+ cpp_warning_with_line (pfile, CPP_W_NORMALIZE, token->src_loc, 0,
+       "`%.*s' is not in NFC", (int) sz, buf);
     }
 }
 
@@ -563,9 +566,9 @@ lex_identifier (cpp_reader *pfile, const
 
       /* For -Wc++-compat, warn about use of C++ named operators.  */
       if (result->flags & NODE_WARN_OPERATOR)
- cpp_error (pfile, CPP_DL_WARNING,
-   "identifier \"%s\" is a special operator name in C++",
-   NODE_NAME (result));
+ cpp_warning (pfile, CPP_W_CXX_OPERATOR_NAMES,
+     "identifier \"%s\" is a special operator name in C++",
+     NODE_NAME (result));
     }
 
   return result;
@@ -1373,7 +1376,7 @@ _cpp_lex_direct (cpp_reader *pfile)
     }
 
   if (skip_line_comment (pfile) && CPP_OPTION (pfile, warn_comments))
-    cpp_error (pfile, CPP_DL_WARNING, "multi-line comment");
+    cpp_warning (pfile, CPP_W_COMMENTS, "multi-line comment");
  }
       else if (c == '=')
  {
Index: libcpp/charset.c
===================================================================
--- libcpp/charset.c (revision 153803)
+++ libcpp/charset.c (working copy)
@@ -993,9 +993,9 @@ _cpp_valid_ucn (cpp_reader *pfile, const
     cpp_error (pfile, CPP_DL_WARNING,
        "universal character names are only valid in C++ and C99");
   else if (CPP_WTRADITIONAL (pfile) && identifier_pos == 0)
-    cpp_error (pfile, CPP_DL_WARNING,
-       "the meaning of '\\%c' is different in traditional C",
-       (int) str[-1]);
+    cpp_warning (pfile, CPP_W_TRADITIONAL,
+         "the meaning of '\\%c' is different in traditional C",
+         (int) str[-1]);
 
   if (str[-1] == 'u')
     length = 4;
@@ -1174,8 +1174,8 @@ convert_hex (cpp_reader *pfile, const uc
   size_t mask = width_to_mask (width);
 
   if (CPP_WTRADITIONAL (pfile))
-    cpp_error (pfile, CPP_DL_WARNING,
-       "the meaning of '\\x' is different in traditional C");
+    cpp_warning (pfile, CPP_W_TRADITIONAL,
+         "the meaning of '\\x' is different in traditional C");
 
   from++;  /* Skip 'x'.  */
   while (from < limit)
@@ -1302,8 +1302,8 @@ convert_escape (cpp_reader *pfile, const
 
     case 'a':
       if (CPP_WTRADITIONAL (pfile))
- cpp_error (pfile, CPP_DL_WARNING,
-   "the meaning of '\\a' is different in traditional C");
+ cpp_warning (pfile, CPP_W_TRADITIONAL,
+     "the meaning of '\\a' is different in traditional C");
       c = charconsts[0];
       break;
 
@@ -1522,7 +1522,7 @@ narrow_str_to_charconst (cpp_reader *pfi
  "character constant too long for its type");
     }
   else if (i > 1 && CPP_OPTION (pfile, warn_multichar))
-    cpp_error (pfile, CPP_DL_WARNING, "multi-character character constant");
+    cpp_warning (pfile, CPP_W_MULTICHAR, "multi-character character constant");
 
   /* Multichar constants are of type int and therefore signed.  */
   if (i > 1)


Re: [PATCH][RFA] Enabling -W[no-]error=... for cpplib warnings

by Gabriel Dos Reis :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, Nov 10, 2009 at 4:29 AM, Simon Baldwin <simonb@...> wrote:
> Attached below is the updated version of this patch, incorporating
> Ian's gcc_assert() and macro expansion parenthesis changes, and Gaby's
> change of warning flag name from -Wwarning-directive to -Wcpp.
>
> Okay for trunk?  I think that's everything covered, so I'll submit in
> a few days if no further comments.  Thanks.

OK.
-- Gaby