One of the pending issues that we should address before we release GCC 7 is
that sometimes we don't issue a warning if the location points to a macro
defined in a system header, unless -Wsystem-headers.  Consider e.g.
  
  enum { e1 = LLONG_MIN };

or

  float_var = LLONG_MIN;

Here, LLONG_MIN comes from a system header and so the compiler doesn't print
any warnings even though it should--the problem is not in the macro itself,
but in how it's used.  This has happened before, e.g. with NULL, and the fix
was to call expansion_point_location_if_in_system_header, but this strategy
is not tenable; there are too many such issues.  After having spent days on
this it seems that we should always use the expansion location except for
certain pedwarns/warnings--the challenge is of course how to distinguish
which ones.  This patch introduces expand_macros_sentinel that can be used
to suppress expanding macros, removes various
expansion_point_location_if_in_system_header calls and fixes testsuite
fallout.  I have *not* gone over all the warnings/pedwarns yet, because this
is touch-and-go whether this'll be considered a reasonable approach.

The general principle should be: is it the macro or its user that is
responsible for the warning?, but in practice it was often less clear to
me what to do.  So e.g. imagine

  #define C :
  #define F i ?: 3

in a system header and then

  i = i ? C 5;  // 1
  return F;     // 2

in user code -- I believe we should NOT warn for 2 (so don't expand the 
location),
but that also means we won't warn for 1.

Thoughts?

Bootstrapped/regtested on x86_64-linux and ppc64-linux.

2016-11-02  Marek Polacek  <pola...@redhat.com>

        PR c/78000
        PR c/71613
gcc/c-family/
        * c-common.c (unsafe_conversion_p): Don't call
        expansion_point_location_if_in_system_header.
        (c_cpp_error): Add a paramater and expand locations depending on that.
        * c-common.h (c_cpp_error): Update declaration.
        * c-warn.c (warnings_for_convert_and_check): Don't call
        expansion_point_location_if_in_system_header.
gcc/c/
        * c-decl.c (declspecs_add_type): Use expand_macros_sentinel to suppress
        expanding macro locations.
        * c-parser.c (c_parser_postfix_expression) [RID_FUNCTION_NAME,
        RID_PRETTY_FUNCTION_NAME, RID_C99_FUNCTION_NAME]: Likewise.
        * c-typeck.c (convert_arguments): Don't call
        expansion_point_location_if_in_system_header.
        (pedwarn_init): Likewise.
        (warning_init): Likewise.
        (convert_for_assignment): Don't call
        expansion_point_location_if_in_system_header.
        (c_finish_return): Likewise.
gcc/cp/
        * call.c (conversion_null_warnings): Don't call
        expansion_point_location_if_in_system_header.
        * cvt.c (build_expr_type_conversion): Likewise.
        * parser.c (set_and_check_decl_spec_loc): Use expand_macros_sentinel to
        suppress expanding macro locations.
        * typeck.c (cp_build_binary_op): Don't call
        expansion_point_location_if_in_system_header.
gcc/
        * diagnostic.c (diagnostic_initialize): Initialize dc_expand_locations.
        (diagnostic_report_warnings_p): New function.
        * diagnostic.h (struct diagnostic_context): Add dc_expand_locations.
        (diagnostic_report_warnings_p): Remove.
        (struct expand_macros_sentinel): New sentinel.
        (diagnostic_report_warnings_p): Declare.
        * genmatch.c (error_cb): Add bool parameter.
        (fatal_at): Adjust error_cb call.
        (warning_at): Likewise.
        * input.c (on_error): Add bool parameter.
gcc/fortran/
        * cpp.c (cb_cpp_error): Add a paramater and expand locations depending
        on that.
gcc/testsuite/
        * gcc.dg/pr71613.c: New.
        * gcc.dg/pr78000.c: New.
        * gcc.dg/pr78000.h: New.
libcpp/
        * charset.c (noop_error_cb): Add bool parameter.
        (saved_error_handler): Likewise.
        (cpp_interpret_string_ranges):
        * errors.c (cpp_diagnostic_at_richloc): Adjust cb.error call.
        (cpp_diagnostic_at): Likewise.
        (cpp_diagnostic_with_line): Add bool parameter and pass it down to
        cb.error.
        (cpp_error_with_line_noexpand): New.
        (cpp_warning_with_line_noexpand): New.
        (cpp_pedwarning_with_line_noexpand): New.
        (cpp_warning_with_line_syshdr): Pass true to cpp_diagnostic_with_line.
        * expr.c (cpp_classify_number): Call *_noexpand variants.
        * include/cpplib.h (error): Adjust declaration.
        (cpp_error_with_line_noexpand): New.
        (cpp_warning_with_line_noexpand): New.
        (cpp_pedwarning_with_line_noexpand): New.

diff --git gcc/gcc/c-family/c-common.c gcc/gcc/c-family/c-common.c
index 307862b..b0a1b5c 100644
--- gcc/gcc/c-family/c-common.c
+++ gcc/gcc/c-family/c-common.c
@@ -1230,7 +1230,6 @@ unsafe_conversion_p (location_t loc, tree type, tree 
expr, bool produce_warns)
 {
   enum conversion_safety give_warning = SAFE_CONVERSION; /* is 0 or false */
   tree expr_type = TREE_TYPE (expr);
-  loc = expansion_point_location_if_in_system_header (loc);
 
   if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST)
     {
@@ -6113,12 +6112,12 @@ c_option_controlling_cpp_error (int reason)
 
 bool
 c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason,
-            rich_location *richloc,
-            const char *msg, va_list *ap)
+            rich_location *richloc, const char *msg, va_list *ap, bool expand)
 {
   diagnostic_info diagnostic;
   diagnostic_t dlevel;
   bool save_warn_system_headers = global_dc->dc_warn_system_headers;
+  bool save_expand_locations = global_dc->dc_expand_locations;
   bool ret;
 
   switch (level)
@@ -6159,9 +6158,12 @@ c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int 
level, int reason,
                                  richloc, dlevel);
   diagnostic_override_option_index (&diagnostic,
                                     c_option_controlling_cpp_error (reason));
+  if (!expand)
+   global_dc->dc_expand_locations = false;
   ret = report_diagnostic (&diagnostic);
   if (level == CPP_DL_WARNING_SYSHDR)
     global_dc->dc_warn_system_headers = save_warn_system_headers;
+  global_dc->dc_expand_locations = save_expand_locations;
   return ret;
 }
 
diff --git gcc/gcc/c-family/c-common.h gcc/gcc/c-family/c-common.h
index 547bab2..b0153b2 100644
--- gcc/gcc/c-family/c-common.h
+++ gcc/gcc/c-family/c-common.h
@@ -1010,7 +1010,7 @@ extern void init_c_lex (void);
 extern void c_cpp_builtins (cpp_reader *);
 extern void c_cpp_builtins_optimize_pragma (cpp_reader *, tree, tree);
 extern bool c_cpp_error (cpp_reader *, int, int, rich_location *,
-                        const char *, va_list *)
+                        const char *, va_list *, bool)
      ATTRIBUTE_GCC_DIAG(5,0);
 extern int c_common_has_attribute (cpp_reader *);
 
diff --git gcc/gcc/c-family/c-warn.c gcc/gcc/c-family/c-warn.c
index 904f6d3..0abb896 100644
--- gcc/gcc/c-family/c-warn.c
+++ gcc/gcc/c-family/c-warn.c
@@ -1002,8 +1002,6 @@ void
 warnings_for_convert_and_check (location_t loc, tree type, tree expr,
                                tree result)
 {
-  loc = expansion_point_location_if_in_system_header (loc);
-
   if (TREE_CODE (expr) == INTEGER_CST
       && (TREE_CODE (type) == INTEGER_TYPE
          || TREE_CODE (type) == ENUMERAL_TYPE)
diff --git gcc/gcc/c/c-decl.c gcc/gcc/c/c-decl.c
index 3e1b7a4..23fc489 100644
--- gcc/gcc/c/c-decl.c
+++ gcc/gcc/c/c-decl.c
@@ -9834,6 +9834,7 @@ declspecs_add_type (location_t loc, struct c_declspecs 
*specs,
                                 "declaration specifiers"));
                      break;
                    }
+                 expand_macros_sentinel e;
                  pedwarn_c90 (loc, OPT_Wlong_long,
                               "ISO C90 does not support %<long long%>");
                  specs->long_long_p = 1;
diff --git gcc/gcc/c/c-parser.c gcc/gcc/c/c-parser.c
index 6bc42da..0591534 100644
--- gcc/gcc/c/c-parser.c
+++ gcc/gcc/c/c-parser.c
@@ -7749,32 +7749,41 @@ c_parser_postfix_expression (c_parser *parser)
       switch (c_parser_peek_token (parser)->keyword)
        {
        case RID_FUNCTION_NAME:
-         pedwarn (loc, OPT_Wpedantic,  "ISO C does not support "
-                  "%<__FUNCTION__%> predefined identifier");
-         expr.value = fname_decl (loc,
-                                  c_parser_peek_token (parser)->keyword,
-                                  c_parser_peek_token (parser)->value);
-         set_c_expr_source_range (&expr, loc, loc);
-         c_parser_consume_token (parser);
-         break;
+         {
+           expand_macros_sentinel e;
+           pedwarn (loc, OPT_Wpedantic,  "ISO C does not support "
+                    "%<__FUNCTION__%> predefined identifier");
+           expr.value = fname_decl (loc,
+                                    c_parser_peek_token (parser)->keyword,
+                                    c_parser_peek_token (parser)->value);
+           set_c_expr_source_range (&expr, loc, loc);
+           c_parser_consume_token (parser);
+           break;
+         }
        case RID_PRETTY_FUNCTION_NAME:
-         pedwarn (loc, OPT_Wpedantic,  "ISO C does not support "
-                  "%<__PRETTY_FUNCTION__%> predefined identifier");
-         expr.value = fname_decl (loc,
-                                  c_parser_peek_token (parser)->keyword,
-                                  c_parser_peek_token (parser)->value);
-         set_c_expr_source_range (&expr, loc, loc);
-         c_parser_consume_token (parser);
-         break;
+         {
+           expand_macros_sentinel e;
+           pedwarn (loc, OPT_Wpedantic,  "ISO C does not support "
+                    "%<__PRETTY_FUNCTION__%> predefined identifier");
+           expr.value = fname_decl (loc,
+                                    c_parser_peek_token (parser)->keyword,
+                                    c_parser_peek_token (parser)->value);
+           set_c_expr_source_range (&expr, loc, loc);
+           c_parser_consume_token (parser);
+           break;
+         }
        case RID_C99_FUNCTION_NAME:
-         pedwarn_c90 (loc, OPT_Wpedantic,  "ISO C90 does not support "
-                  "%<__func__%> predefined identifier");
-         expr.value = fname_decl (loc,
-                                  c_parser_peek_token (parser)->keyword,
-                                  c_parser_peek_token (parser)->value);
-         set_c_expr_source_range (&expr, loc, loc);
-         c_parser_consume_token (parser);
-         break;
+         {
+           expand_macros_sentinel e;
+           pedwarn_c90 (loc, OPT_Wpedantic,  "ISO C90 does not support "
+                        "%<__func__%> predefined identifier");
+           expr.value = fname_decl (loc,
+                                    c_parser_peek_token (parser)->keyword,
+                                    c_parser_peek_token (parser)->value);
+           set_c_expr_source_range (&expr, loc, loc);
+           c_parser_consume_token (parser);
+           break;
+         }
        case RID_VA_ARG:
          {
            location_t start_loc = loc;
diff --git gcc/gcc/c/c-typeck.c gcc/gcc/c/c-typeck.c
index f0917ed..f911f01 100644
--- gcc/gcc/c/c-typeck.c
+++ gcc/gcc/c/c-typeck.c
@@ -3270,8 +3270,7 @@ convert_arguments (location_t loc, vec<location_t> 
arg_loc, tree typelist,
         position 0.  */
       location_t ploc
        = !arg_loc.is_empty () && values->length () == arg_loc.length ()
-         ? expansion_point_location_if_in_system_header (arg_loc[parmnum])
-         : input_location;
+         ? arg_loc[parmnum] : input_location;
 
       if (type == void_type_node)
        {
@@ -6002,16 +6001,11 @@ pedwarn_init (location_t loc, int opt, const char 
*gmsgid)
   char *ofwhat;
   bool warned;
 
-  /* Use the location where a macro was expanded rather than where
-     it was defined to make sure macros defined in system headers
-     but used incorrectly elsewhere are diagnosed.  */
-  source_location exploc = expansion_point_location_if_in_system_header (loc);
-
   /* The gmsgid may be a format string with %< and %>. */
-  warned = pedwarn (exploc, opt, gmsgid);
+  warned = pedwarn (loc, opt, gmsgid);
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat && warned)
-    inform (exploc, "(near initialization for %qs)", ofwhat);
+    inform (loc, "(near initialization for %qs)", ofwhat);
 }
 
 /* Issue a warning for a bad initializer component.
@@ -6026,16 +6020,11 @@ warning_init (location_t loc, int opt, const char 
*gmsgid)
   char *ofwhat;
   bool warned;
 
-  /* Use the location where a macro was expanded rather than where
-     it was defined to make sure macros defined in system headers
-     but used incorrectly elsewhere are diagnosed.  */
-  source_location exploc = expansion_point_location_if_in_system_header (loc);
-
   /* The gmsgid may be a format string with %< and %>. */
-  warned = warning_at (exploc, opt, gmsgid);
+  warned = warning_at (loc, opt, gmsgid);
   ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
   if (*ofwhat && warned)
-    inform (exploc, "(near initialization for %qs)", ofwhat);
+    inform (loc, "(near initialization for %qs)", ofwhat);
 }
 
 /* If TYPE is an array type and EXPR is a parenthesized string
@@ -6092,10 +6081,6 @@ convert_for_assignment (location_t location, location_t 
expr_loc, tree type,
   tree rname = NULL_TREE;
   bool objc_ok = false;
 
-  /* Use the expansion point location to handle cases such as user's
-     function returning a wrong-type macro defined in a system header.  */
-  location = expansion_point_location_if_in_system_header (location);
-
   if (errtype == ic_argpass)
     {
       tree selector;
@@ -9770,12 +9755,8 @@ c_finish_return (location_t loc, tree retval, tree 
origtype)
   bool npc = false;
   size_t rank = 0;
 
-  /* Use the expansion point to handle cases such as returning NULL
-     in a function returning void.  */
-  source_location xloc = expansion_point_location_if_in_system_header (loc);
-
   if (TREE_THIS_VOLATILE (current_function_decl))
-    warning_at (xloc, 0,
+    warning_at (loc, 0,
                "function declared %<noreturn%> has a %<return%> statement");
 
   if (flag_cilkplus && contains_array_notation_expr (retval))
@@ -9838,11 +9819,11 @@ c_finish_return (location_t loc, tree retval, tree 
origtype)
       bool warned_here;
       if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
        warned_here = pedwarn
-         (xloc, 0,
+         (loc, 0,
           "%<return%> with a value, in function returning void");
       else
        warned_here = pedwarn
-         (xloc, OPT_Wpedantic, "ISO C forbids "
+         (loc, OPT_Wpedantic, "ISO C forbids "
           "%<return%> with expression, in function returning void");
       if (warned_here)
        inform (DECL_SOURCE_LOCATION (current_function_decl),
diff --git gcc/gcc/cp/call.c gcc/gcc/cp/call.c
index 4c19d2f..f9e0c9a 100644
--- gcc/gcc/cp/call.c
+++ gcc/gcc/cp/call.c
@@ -6413,15 +6413,12 @@ conversion_null_warnings (tree totype, tree expr, tree 
fn, int argnum)
   if (expr == null_node && TREE_CODE (totype) != BOOLEAN_TYPE
       && ARITHMETIC_TYPE_P (totype))
     {
-      source_location loc =
-       expansion_point_location_if_in_system_header (input_location);
-
       if (fn)
-       warning_at (loc, OPT_Wconversion_null,
+       warning_at (input_location, OPT_Wconversion_null,
                    "passing NULL to non-pointer argument %P of %qD",
                    argnum, fn);
       else
-       warning_at (loc, OPT_Wconversion_null,
+       warning_at (input_location, OPT_Wconversion_null,
                    "converting to non-pointer type %qT from NULL", totype);
     }
 
diff --git gcc/gcc/cp/cvt.c gcc/gcc/cp/cvt.c
index 2f5f15a..66266e0 100644
--- gcc/gcc/cp/cvt.c
+++ gcc/gcc/cp/cvt.c
@@ -1647,13 +1647,8 @@ build_expr_type_conversion (int desires, tree expr, bool 
complain)
   if (expr == null_node
       && (desires & WANT_INT)
       && !(desires & WANT_NULL))
-    {
-      source_location loc =
-       expansion_point_location_if_in_system_header (input_location);
-
-      warning_at (loc, OPT_Wconversion_null,
-                 "converting NULL to non-pointer type");
-    }
+    warning_at (input_location, OPT_Wconversion_null,
+               "converting NULL to non-pointer type");
 
   if (basetype == error_mark_node)
     return error_mark_node;
diff --git gcc/gcc/cp/parser.c gcc/gcc/cp/parser.c
index e443648..32857b9 100644
--- gcc/gcc/cp/parser.c
+++ gcc/gcc/cp/parser.c
@@ -27259,6 +27259,7 @@ set_and_check_decl_spec_loc (cp_decl_specifier_seq 
*decl_specs,
                      "%<long long long%> is too long for GCC");
          else
            {
+             expand_macros_sentinel e;
              decl_specs->locations[ds_long_long] = location;
              pedwarn_cxx98 (location,
                             OPT_Wlong_long, 
diff --git gcc/gcc/cp/typeck.c gcc/gcc/cp/typeck.c
index 569442f..2f01f62 100644
--- gcc/gcc/cp/typeck.c
+++ gcc/gcc/cp/typeck.c
@@ -4202,12 +4202,7 @@ cp_build_binary_op (location_t location,
          || (!null_ptr_cst_p (orig_op1) 
              && !TYPE_PTR_OR_PTRMEM_P (type1)))
       && (complain & tf_warning))
-    {
-      source_location loc =
-       expansion_point_location_if_in_system_header (input_location);
-
-      warning_at (loc, OPT_Wpointer_arith, "NULL used in arithmetic");
-    }
+    warning_at (input_location, OPT_Wpointer_arith, "NULL used in arithmetic");
 
   /* In case when one of the operands of the binary operation is
      a vector and another is a scalar -- convert scalar to vector.  */
diff --git gcc/gcc/diagnostic.c gcc/gcc/diagnostic.c
index 2304e14..c523d2d 100644
--- gcc/gcc/diagnostic.c
+++ gcc/gcc/diagnostic.c
@@ -163,6 +163,7 @@ diagnostic_initialize (diagnostic_context *context, int 
n_opts)
   context->fatal_errors = false;
   context->dc_inhibit_warnings = false;
   context->dc_warn_system_headers = false;
+  context->dc_expand_locations = true;
   context->max_errors = 0;
   context->internal_error = NULL;
   diagnostic_starter (context) = default_diagnostic_starter;
@@ -785,6 +786,22 @@ print_parseable_fixits (pretty_printer *pp, rich_location 
*richloc)
     }
 }
 
+
+/* Returns nonzero if warnings should be emitted.  */
+
+bool
+diagnostic_report_warnings_p (diagnostic_context *dc, location_t loc)
+{
+  /* Use the location where a macro was expanded rather than where
+     it was defined to make sure macros defined in system headers
+     but used incorrectly elsewhere are diagnosed.  */
+  if (dc->dc_expand_locations)
+    loc = expansion_point_location_if_in_system_header (loc);
+
+  return (!dc->dc_inhibit_warnings
+         && !(in_system_header_at (loc) && !dc->dc_warn_system_headers));
+}
+
 /* Report a diagnostic message (an error or a warning) as specified by
    DC.  This function is *the* subroutine in terms of which front-ends
    should implement their specific diagnostic handling modules.  The
diff --git gcc/gcc/diagnostic.h gcc/gcc/diagnostic.h
index ead4d2a..c448059 100644
--- gcc/gcc/diagnostic.h
+++ gcc/gcc/diagnostic.h
@@ -142,6 +142,9 @@ struct diagnostic_context
   /* True if warnings should be given in system headers.  */
   bool dc_warn_system_headers;
 
+  /* True if locations should be expanded.  */
+  bool dc_expand_locations;
+
   /* Maximum number of errors to report.  */
   unsigned int max_errors;
 
@@ -273,11 +276,6 @@ extern diagnostic_context *global_dc;
 /* Similarly, but for sorrys.  */
 #define sorrycount diagnostic_kind_count (global_dc, DK_SORRY)
 
-/* Returns nonzero if warnings should be emitted.  */
-#define diagnostic_report_warnings_p(DC, LOC)                          \
-  (!(DC)->dc_inhibit_warnings                                          \
-   && !(in_system_header_at (LOC) && !(DC)->dc_warn_system_headers))
-
 #define report_diagnostic(D) diagnostic_report_diagnostic (global_dc, D)
 
 /* Override the option index to be used for reporting a
@@ -285,6 +283,22 @@ extern diagnostic_context *global_dc;
 #define diagnostic_override_option_index(DI, OPTIDX) \
     ((DI)->option_index = (OPTIDX))
 
+/* RAII sentinel to handle (not) expanding macros when needed.  */
+
+struct expand_macros_sentinel
+{
+  bool saved;
+  expand_macros_sentinel ()
+    : saved (global_dc->dc_expand_locations)
+  {
+    global_dc->dc_expand_locations = false;
+  }
+  ~expand_macros_sentinel ()
+  {
+    global_dc->dc_expand_locations = saved;
+  }
+};
+
 /* Diagnostic related functions.  */
 extern void diagnostic_initialize (diagnostic_context *, int);
 extern void diagnostic_color_init (diagnostic_context *, int value = -1);
@@ -293,6 +307,7 @@ extern void diagnostic_report_current_module 
(diagnostic_context *, location_t);
 extern void diagnostic_show_locus (diagnostic_context *,
                                   rich_location *richloc,
                                   diagnostic_t diagnostic_kind);
+extern bool diagnostic_report_warnings_p (diagnostic_context *, location_t);
 
 /* Force diagnostics controlled by OPTIDX to be kind KIND.  */
 extern diagnostic_t diagnostic_classify_diagnostic (diagnostic_context *,
diff --git gcc/gcc/fortran/cpp.c gcc/gcc/fortran/cpp.c
index 8ac8092..0a16f12 100644
--- gcc/gcc/fortran/cpp.c
+++ gcc/gcc/fortran/cpp.c
@@ -143,7 +143,7 @@ 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, int, rich_location *,
-                         const char *, va_list *)
+                         const char *, va_list *, bool)
      ATTRIBUTE_GCC_DIAG(5,0);
 void pp_dir_change (cpp_reader *, const char *);
 
@@ -1025,11 +1025,12 @@ cb_used_define (cpp_reader *pfile, source_location line 
ATTRIBUTE_UNUSED,
 static bool
 cb_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason,
              rich_location *richloc,
-             const char *msg, va_list *ap)
+             const char *msg, va_list *ap, bool expand)
 {
   diagnostic_info diagnostic;
   diagnostic_t dlevel;
   bool save_warn_system_headers = global_dc->dc_warn_system_headers;
+  bool save_expand_locations = global_dc->dc_expand_locations;
   bool ret;
 
   switch (level)
@@ -1062,9 +1063,12 @@ cb_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int 
level, int reason,
                                  richloc, dlevel);
   if (reason == CPP_W_WARNING_DIRECTIVE)
     diagnostic_override_option_index (&diagnostic, OPT_Wcpp);
+  if (!expand)
+    global_dc->dc_expand_locations = false;
   ret = report_diagnostic (&diagnostic);
   if (level == CPP_DL_WARNING_SYSHDR)
     global_dc->dc_warn_system_headers = save_warn_system_headers;
+  global_dc->dc_expand_locations = save_expand_locations;
   return ret;
 }
 
diff --git gcc/gcc/genmatch.c gcc/gcc/genmatch.c
index b14034d..4be9931 100644
--- gcc/gcc/genmatch.c
+++ gcc/gcc/genmatch.c
@@ -73,7 +73,7 @@ static bool
 __attribute__((format (printf, 5, 0)))
 #endif
 error_cb (cpp_reader *, int errtype, int, rich_location *richloc,
-         const char *msg, va_list *ap)
+         const char *msg, va_list *ap, bool)
 {
   const line_map_ordinary *map;
   source_location location = richloc->get_loc ();
@@ -121,7 +121,7 @@ fatal_at (const cpp_token *tk, const char *msg, ...)
   rich_location richloc (line_table, tk->src_loc);
   va_list ap;
   va_start (ap, msg);
-  error_cb (NULL, CPP_DL_FATAL, 0, &richloc, msg, &ap);
+  error_cb (NULL, CPP_DL_FATAL, 0, &richloc, msg, &ap, true);
   va_end (ap);
 }
 
@@ -134,7 +134,7 @@ fatal_at (source_location loc, const char *msg, ...)
   rich_location richloc (line_table, loc);
   va_list ap;
   va_start (ap, msg);
-  error_cb (NULL, CPP_DL_FATAL, 0, &richloc, msg, &ap);
+  error_cb (NULL, CPP_DL_FATAL, 0, &richloc, msg, &ap, true);
   va_end (ap);
 }
 
@@ -147,7 +147,7 @@ warning_at (const cpp_token *tk, const char *msg, ...)
   rich_location richloc (line_table, tk->src_loc);
   va_list ap;
   va_start (ap, msg);
-  error_cb (NULL, CPP_DL_WARNING, 0, &richloc, msg, &ap);
+  error_cb (NULL, CPP_DL_WARNING, 0, &richloc, msg, &ap, true);
   va_end (ap);
 }
 
@@ -160,7 +160,7 @@ warning_at (source_location loc, const char *msg, ...)
   rich_location richloc (line_table, loc);
   va_list ap;
   va_start (ap, msg);
-  error_cb (NULL, CPP_DL_WARNING, 0, &richloc, msg, &ap);
+  error_cb (NULL, CPP_DL_WARNING, 0, &richloc, msg, &ap, true);
   va_end (ap);
 }
 
diff --git gcc/gcc/input.c gcc/gcc/input.c
index c2042e8..e3bf57f 100644
--- gcc/gcc/input.c
+++ gcc/gcc/input.c
@@ -2002,7 +2002,7 @@ class ebcdic_execution_charset : public lexer_test_options
                        int level ATTRIBUTE_UNUSED,
                        int reason ATTRIBUTE_UNUSED,
                        rich_location *richloc ATTRIBUTE_UNUSED,
-                       const char *msgid, va_list *ap ATTRIBUTE_UNUSED)
+                       const char *msgid, va_list *ap ATTRIBUTE_UNUSED, bool)
     ATTRIBUTE_FPTR_PRINTF(5,0)
   {
     gcc_assert (s_singleton);
diff --git gcc/gcc/testsuite/gcc.dg/.pr67730.c.swp 
gcc/gcc/testsuite/gcc.dg/.pr67730.c.swp
index e69de29..dd35600 100644
Binary files gcc/gcc/testsuite/gcc.dg/.pr67730.c.swp and 
gcc/gcc/testsuite/gcc.dg/.pr67730.c.swp differ
diff --git gcc/gcc/testsuite/gcc.dg/pr71613.c gcc/gcc/testsuite/gcc.dg/pr71613.c
index e69de29..581a521 100644
--- gcc/gcc/testsuite/gcc.dg/pr71613.c
+++ gcc/gcc/testsuite/gcc.dg/pr71613.c
@@ -0,0 +1,14 @@
+/* Don't suppress the warning here even though LLONG_MIN comes from
+   a system header.  */
+/* PR c/71613 */
+/* { dg-do compile } */
+/* { dg-options "-Wpedantic" } */
+
+#include <limits.h>
+
+void
+f (void)
+{
+  enum { e1 = LLONG_MIN }; /* { dg-warning "ISO C restricts enumerator values" 
} */
+  enum { e2 = +LLONG_MIN }; /* { dg-warning "ISO C restricts enumerator 
values" } */
+}
diff --git gcc/gcc/testsuite/gcc.dg/pr78000.c gcc/gcc/testsuite/gcc.dg/pr78000.c
index e69de29..0d0ce06 100644
--- gcc/gcc/testsuite/gcc.dg/pr78000.c
+++ gcc/gcc/testsuite/gcc.dg/pr78000.c
@@ -0,0 +1,11 @@
+/* PR c/78000 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+#include "pr78000.h"
+
+int
+main ()
+{
+  foo (42); /* { dg-warning "implicit declaration" } */
+}
diff --git gcc/gcc/testsuite/gcc.dg/pr78000.h gcc/gcc/testsuite/gcc.dg/pr78000.h
index e69de29..2319e45 100644
--- gcc/gcc/testsuite/gcc.dg/pr78000.h
+++ gcc/gcc/testsuite/gcc.dg/pr78000.h
@@ -0,0 +1,2 @@
+#pragma GCC system_header
+#define foo bar
diff --git gcc/libcpp/charset.c gcc/libcpp/charset.c
index e77270a..63a7ae0 100644
--- gcc/libcpp/charset.c
+++ gcc/libcpp/charset.c
@@ -1688,7 +1688,7 @@ cpp_interpret_string (cpp_reader *pfile, const cpp_string 
*from, size_t count,
 
 static bool
 noop_error_cb (cpp_reader *, int, int, rich_location *,
-              const char *, va_list *)
+              const char *, va_list *, bool)
 {
   /* no-op.  */
   return true;
@@ -1734,7 +1734,7 @@ cpp_interpret_string_ranges (cpp_reader *pfile, const 
cpp_string *from,
      If an error does occur, we should see it via the return value of
      cpp_interpret_string_1.  */
   bool (*saved_error_handler) (cpp_reader *, int, int, rich_location *,
-                              const char *, va_list *)
+                              const char *, va_list *, bool)
     ATTRIBUTE_FPTR_PRINTF(5,0);
 
   saved_error_handler = pfile->cb.error;
diff --git gcc/libcpp/errors.c gcc/libcpp/errors.c
index 3b0a0b4..64e089b 100644
--- gcc/libcpp/errors.c
+++ gcc/libcpp/errors.c
@@ -39,7 +39,8 @@ cpp_diagnostic_at_richloc (cpp_reader * pfile, int level, int 
reason,
 
   if (!pfile->cb.error)
     abort ();
-  ret = pfile->cb.error (pfile, level, reason, richloc, _(msgid), ap);
+  ret = pfile->cb.error (pfile, level, reason, richloc, _(msgid), ap,
+                        /*expand=*/true);
 
   return ret;
 }
@@ -57,7 +58,8 @@ cpp_diagnostic_at (cpp_reader * pfile, int level, int reason,
   if (!pfile->cb.error)
     abort ();
   rich_location richloc (pfile->line_table, src_loc);
-  ret = pfile->cb.error (pfile, level, reason, &richloc, _(msgid), ap);
+  ret = pfile->cb.error (pfile, level, reason, &richloc, _(msgid), ap,
+                        /*expand=*/true);
 
   return ret;
 }
@@ -162,7 +164,7 @@ 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)
+                         const char *msgid, va_list *ap, bool expand)
 {
   bool ret;
   
@@ -171,7 +173,8 @@ cpp_diagnostic_with_line (cpp_reader * pfile, int level, 
int reason,
   rich_location richloc (pfile->line_table, src_loc);
   if (column)
     richloc.override_column (column);
-  ret = pfile->cb.error (pfile, level, reason, &richloc, _(msgid), ap);
+  ret = pfile->cb.error (pfile, level, reason, &richloc, _(msgid), ap,
+                        expand);
 
   return ret;
 }
@@ -189,7 +192,27 @@ cpp_error_with_line (cpp_reader *pfile, int level,
   va_start (ap, msgid);
 
   ret = cpp_diagnostic_with_line (pfile, level, CPP_W_NONE, src_loc,
-                                  column, msgid, &ap);
+                                  column, msgid, &ap, true);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a warning or error, depending on the value of LEVEL.  Do not
+   expand the location.  */
+
+bool
+cpp_error_with_line_noexpand (cpp_reader *pfile, int level,
+                             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, level, CPP_W_NONE, src_loc,
+                                  column, msgid, &ap, false);
 
   va_end (ap);
   return ret;
@@ -208,7 +231,27 @@ cpp_warning_with_line (cpp_reader *pfile, int reason,
   va_start (ap, msgid);
 
   ret = cpp_diagnostic_with_line (pfile, CPP_DL_WARNING, reason, src_loc,
-                                  column, msgid, &ap);
+                                  column, msgid, &ap, true);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a warning.  The warning reason may be given in REASON.   Do not
+   expand the location.  */
+
+bool
+cpp_warning_with_line_noexpand (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, false);
 
   va_end (ap);
   return ret;
@@ -227,7 +270,27 @@ cpp_pedwarning_with_line (cpp_reader *pfile, int reason,
   va_start (ap, msgid);
 
   ret = cpp_diagnostic_with_line (pfile, CPP_DL_PEDWARN, reason, src_loc,
-                                  column, msgid, &ap);
+                                  column, msgid, &ap, true);
+
+  va_end (ap);
+  return ret;
+}
+
+/* Print a pedantic warning.  The warning reason may be given in REASON.  Do 
not
+   expand the location.  */
+
+bool
+cpp_pedwarning_with_line_noexpand (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, false);
 
   va_end (ap);
   return ret;
@@ -247,7 +310,7 @@ cpp_warning_with_line_syshdr (cpp_reader *pfile, int reason,
   va_start (ap, msgid);
 
   ret = cpp_diagnostic_with_line (pfile, CPP_DL_WARNING_SYSHDR, reason, 
src_loc,
-                                  column, msgid, &ap);
+                                  column, msgid, &ap, true);
 
   va_end (ap);
   return ret;
diff --git gcc/libcpp/expr.c gcc/libcpp/expr.c
index 61bc1b2..99b9f30 100644
--- gcc/libcpp/expr.c
+++ gcc/libcpp/expr.c
@@ -766,11 +766,11 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token 
*token,
                                : N_("use of C99 long long integer constant");
 
          if (CPP_OPTION (pfile, c99))
-            cpp_warning_with_line (pfile, CPP_W_LONG_LONG, virtual_location,
-                                  0, message);
+            cpp_warning_with_line_noexpand (pfile, CPP_W_LONG_LONG,
+                                           virtual_location, 0, message);
           else
-            cpp_pedwarning_with_line (pfile, CPP_W_LONG_LONG,
-                                     virtual_location, 0, message);
+            cpp_pedwarning_with_line_noexpand (pfile, CPP_W_LONG_LONG,
+                                              virtual_location, 0, message);
         }
 
       result |= CPP_N_INTEGER;
@@ -778,16 +778,16 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token 
*token,
 
  syntax_ok:
   if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile))
-    cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
-                        "imaginary constants are a GCC extension");
+    cpp_error_with_line_noexpand (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+                                 "imaginary constants are a GCC extension");
   if (radix == 2
       && !CPP_OPTION (pfile, binary_constants)
       && CPP_PEDANTIC (pfile))
-    cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
-                        CPP_OPTION (pfile, cplusplus)
-                        ? N_("binary constants are a C++14 feature "
-                             "or GCC extension")
-                        : N_("binary constants are a GCC extension"));
+    cpp_error_with_line_noexpand (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+                                 CPP_OPTION (pfile, cplusplus)
+                                 ? N_("binary constants are a C++14 feature "
+                                      "or GCC extension")
+                                 : N_("binary constants are a GCC extension"));
 
   if (radix == 10)
     result |= CPP_N_DECIMAL;
diff --git gcc/libcpp/include/cpplib.h gcc/libcpp/include/cpplib.h
index 0781c09..2971ed7 100644
--- gcc/libcpp/include/cpplib.h
+++ gcc/libcpp/include/cpplib.h
@@ -580,7 +580,7 @@ struct cpp_callbacks
   /* Called to emit a diagnostic.  This callback receives the
      translated message.  */
   bool (*error) (cpp_reader *, int, int, rich_location *,
-                const char *, va_list *)
+                const char *, va_list *, bool)
        ATTRIBUTE_FPTR_PRINTF(5,0);
 
   /* Callbacks for when a macro is expanded, or tested (whether
@@ -1067,12 +1067,22 @@ extern bool cpp_errno_filename (cpp_reader *, int, 
const char *filename,
 extern bool cpp_error_with_line (cpp_reader *, int, source_location,
                                  unsigned, const char *msgid, ...)
   ATTRIBUTE_PRINTF_5;
+extern bool cpp_error_with_line_noexpand (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_warning_with_line_noexpand (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_pedwarning_with_line_noexpand (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;

        Marek

Reply via email to