public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] improve warning suppression for inlined functions (PR 98465,  98512)
@ 2021-01-19 18:58 Martin Sebor
  2021-01-21 17:34 ` Florian Weimer
                   ` (2 more replies)
  0 siblings, 3 replies; 44+ messages in thread
From: Martin Sebor @ 2021-01-19 18:58 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2077 bytes --]

std::string tends to trigger a class of false positive out of bounds
access warnings for code GCC cannot prove is unreachable because of
missing aliasing constrains, and that ends up expanded inline into
user code.  Simply inserting the contents of a constant char array
does that.  In GCC 10 these false positives are suppressed due to
-Wno-system-headers, but in GCC 11, to help detect calls rendered
invalid by user code passing in either incorrect or insufficiently
constrained arguments, -Wno-system-header no longer has this effect
on invalid access warnings.

To solve the problem without at least partially reverting the change
and going back to the GCC 10 way of things for the affected subset
of calls (just memcpy and memmove), the attached patch enhances
the #pragma GCC diagnostic machinery to consider not just a single
location for inlined code but all locations at which an expression
and its callers are inlined all the way up the stack.  This gives
each author of a function involved in inlining the ability to
control a warning issued for the code, not just the user into whose
code all the calls end up inlined.  To resolve PR 98465, it lets us
suppress the false positives selectively in std::string rather
than across the board in GCC.

The solution is to provide a new pair of overloads for warning
functions that, instead of taking a single location argument, take
a tree node from which the location(s) are determined.  The tree
argument is indirect because the diagnostic machinery doesn't (and
cannot without more intrusive changes) at the moment depend on
the various tree definitions.  A nice feature of these overloads
is that they do away with the need for the %K directive (and in
the future also %G, with another enhancement to accept a gimple*
argument).

This patch depends on the fix for PR 98664 (already approved but
not yet checked in).  I've tested it on x86_64-linux.

To avoid fallout I tried to keep the changes to a minimum, and
so the design isn't as robust as I'd like it ultimately to be.
I plan to enhance it in stage 1.

Martin

[-- Attachment #2: gcc-98465.diff --]
[-- Type: text/x-patch, Size: 53353 bytes --]

PR middle-end/98465 - Bogus -Wstringop-overread in std::string
PR middle-end/98512 - “#pragma GCC diagnostic ignored” ineffective in conjunction with alias attribute

gcc/ChangeLog:

	PR middle-end/98465
	PR middle-end/98512
	* builtins.c (class diag_inlining_context): New class.
	(maybe_warn_for_bound): Adjust signature.  Use diag_inlining_context.
	(warn_for_access): Same.
	(check_access): Remove calls to tree_inlined_location.
	(expand_builtin_strncmp): Remove argument from calls to
	maybe_warn_for_bound.
	(warn_dealloc_offset): Adjust signature.  Use diag_inlining_context.
	(maybe_emit_free_warning): Remove calls to tree_inlined_location.
	* diagnostic-core.h (warning, warning_n): New overloads.
	* diagnostic-metadata.h (class diagnostic_metadata::location_context):
	New.
	(struct diagnostic_info): Declare.
	* diagnostic.c (location_context::locations): Define.
	(update_effective_level_from_pragmas): Use location_context to test
	inlinined locations.
	(diagnostic_report_diagnostic): Set location context.
	(warning, warning_n): Define new overloads.
	* diagnostic.h (diagnostic_inhibit_notes):

gcc/cp/ChangeLog:

	* mapper-client.cc: Include headers needed by others.

libstdc++-v3/ChangeLog:

	PR middle-end/98465
	* include/bits/basic_string.tcc (_M_replace): Suppress false positive
	warnings.
	* testsuite/18_support/new_delete_placement.cc: Suppress valid warnings.
	* testsuite/20_util/monotonic_buffer_resource/allocate.cc: Same.
	* testsuite/20_util/unsynchronized_pool_resource/allocate.cc: Same.

gcc/testsuite/ChangeLog:

	PR middle-end/98512	
	* gcc.dg/pragma-diag-9.c: New test.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index c1115a32d91..68f1ae042d8 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -39,7 +39,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "optabs.h"
 #include "emit-rtl.h"
 #include "recog.h"
-#include "diagnostic-core.h"
+#include "diagnostic.h"
 #include "alias.h"
 #include "fold-const.h"
 #include "fold-const-call.h"
@@ -79,6 +79,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-outof-ssa.h"
 #include "attr-fnspec.h"
 #include "demangle.h"
+#include "tree-pretty-print.h"
 
 struct target_builtins default_target_builtins;
 #if SWITCHABLE_TARGET
@@ -749,6 +750,93 @@ is_builtin_name (const char *name)
   return false;
 }
 
+/* Class to override the base location context for an expression EXPR.  */
+
+class diag_inlining_context: public diagnostic_metadata::location_context
+{
+ public:
+  diag_inlining_context (tree expr): m_expr (expr), m_ao (), m_loc () { }
+
+  virtual void locations (vec<location_t> &locs, diagnostic_info *di)
+  {
+    set_locations (&locs, di);
+  }
+
+  virtual void set_location (diagnostic_info *);
+
+ private:
+  void set_locations (vec<location_t> *, diagnostic_info *);
+
+  /* The expression for which a diagnostic is being issued.  */
+  tree m_expr;
+  /* The "abstract origin" of the diagnosed expression, or the BLOCK
+     into which the function containing the expression is inlined.  */
+  tree m_ao;
+  /* The expression location.  */
+  location_t m_loc;
+};
+
+/* Lazily initialize the expression abstract origin and location.  */
+
+/* virtual */ void
+diag_inlining_context::set_location (diagnostic_info *di)
+{
+  if (m_ao
+      && pp_ti_abstract_origin (&di->message)
+      && m_loc != UNKNOWN_LOCATION)
+    {
+      *pp_ti_abstract_origin (&di->message) = m_ao;
+      di->message.set_location (0, m_loc, SHOW_RANGE_WITH_CARET);
+    }
+  else
+    set_locations (NULL, di);
+}
+
+/* If LOC is nonnull, fill *LOCS with the locations M_EXPR has been inlined
+   into and if DI is nonnull, set *DI's message abstract origin and location.
+   Set M_MO.  */
+
+/* virtual */ void
+diag_inlining_context::set_locations (vec<location_t> *locs,
+				      diagnostic_info *di)
+{
+  tree block = TREE_BLOCK (m_expr);
+
+  while (block && TREE_CODE (block) == BLOCK
+	 && BLOCK_ABSTRACT_ORIGIN (block))
+    {
+      tree ao = BLOCK_ABSTRACT_ORIGIN (block);
+      if (TREE_CODE (ao) == FUNCTION_DECL)
+	{
+	  if (!m_ao)
+	    m_ao = block;
+
+	  if (!locs)
+
+	    break;
+	  locs->safe_push (BLOCK_SOURCE_LOCATION (block));
+	}
+      else if (TREE_CODE (ao) != BLOCK)
+	break;
+
+      block = BLOCK_SUPERCONTEXT (block);
+    }
+
+  m_loc = EXPR_LOCATION (m_expr);
+  /* Only consider macro expansion when the block traversal failed
+     to find a location.  Otherwise it's not relevant.  */
+  m_loc = expansion_point_location_if_in_system_header (m_loc);
+  if (locs)
+    locs->safe_push (m_loc);
+
+  if (di)
+    {
+      if (pp_ti_abstract_origin (&di->message))
+	*pp_ti_abstract_origin (&di->message) = m_ao;
+      di->message.set_location (0, m_loc, SHOW_RANGE_WITH_CARET);
+    }
+}
+
 /* Return true if NODE should be considered for inline expansion regardless
    of the optimization level.  This means whenever a function is invoked with
    its "internal" name, which normally contains the prefix "__builtin".  */
@@ -3931,7 +4019,7 @@ determine_block_size (tree len, rtx len_rtx,
    accessing an object with SIZE.  */
 
 static bool
-maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
+maybe_warn_for_bound (int opt, tree exp, tree func,
 		      tree bndrng[2], tree size, const access_data *pad = NULL)
 {
   if (!bndrng[0] || TREE_NO_WARNING (exp))
@@ -3939,6 +4027,8 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
 
   tree maxobjsize = max_object_size ();
 
+  diag_inlining_context dic (exp);
+
   bool warned = false;
 
   if (opt == OPT_Wstringop_overread)
@@ -3949,72 +4039,71 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
 	{
 	  if (bndrng[0] == bndrng[1])
 	    warned = (func
-		      ? warning_at (loc, opt,
-				    (maybe
-				     ? G_("%K%qD specified bound %E may "
-					  "exceed maximum object size %E")
-				     : G_("%K%qD specified bound %E "
-					  "exceeds maximum object size %E")),
-				    exp, func, bndrng[0], maxobjsize)
-		      : warning_at (loc, opt,
-				    (maybe
-				     ? G_("%Kspecified bound %E may "
-					  "exceed maximum object size %E")
-				     : G_("%Kspecified bound %E "
-					  "exceeds maximum object size %E")),
-				    exp, bndrng[0], maxobjsize));
+		      ? warning (dic, opt,
+				 (maybe
+				  ? G_("%qD specified bound %E may "
+				       "exceed maximum object size %E")
+				  : G_("%qD specified bound %E "
+				       "exceeds maximum object size %E")),
+				 func, bndrng[0], maxobjsize)
+		      : warning (dic, opt,
+				 (maybe
+				  ? G_("specified bound %E may "
+				       "exceed maximum object size %E")
+				  : G_("specified bound %E "
+				       "exceeds maximum object size %E")),
+				 bndrng[0], maxobjsize));
 	  else
 	    warned = (func
-		      ? warning_at (loc, opt,
-				    (maybe
-				     ? G_("%K%qD specified bound [%E, %E] may "
-					  "exceed maximum object size %E")
-				     : G_("%K%qD specified bound [%E, %E] "
-					  "exceeds maximum object size %E")),
-				    exp, func,
-				    bndrng[0], bndrng[1], maxobjsize)
-		      : warning_at (loc, opt,
-				    (maybe
-				     ? G_("%Kspecified bound [%E, %E] may "
-					  "exceed maximum object size %E")
-				     : G_("%Kspecified bound [%E, %E] "
-					  "exceeds maximum object size %E")),
-				    exp, bndrng[0], bndrng[1], maxobjsize));
+		      ? warning (dic, opt,
+				 (maybe
+				  ? G_("%qD specified bound [%E, %E] may "
+				       "exceed maximum object size %E")
+				  : G_("%qD specified bound [%E, %E] "
+				       "exceeds maximum object size %E")),
+				 func, bndrng[0], bndrng[1], maxobjsize)
+		      : warning (dic, opt,
+				 (maybe
+				  ? G_("specified bound [%E, %E] may "
+				       "exceed maximum object size %E")
+				  : G_("specified bound [%E, %E] "
+				       "exceeds maximum object size %E")),
+				 bndrng[0], bndrng[1], maxobjsize));
 	}
       else if (!size || tree_int_cst_le (bndrng[0], size))
 	return false;
       else if (tree_int_cst_equal (bndrng[0], bndrng[1]))
 	warned = (func
-		  ? warning_at (loc, opt,
-				(maybe
-				 ? G_("%K%qD specified bound %E may exceed "
-				      "source size %E")
-				 : G_("%K%qD specified bound %E exceeds "
-				      "source size %E")),
-				exp, func, bndrng[0], size)
-		  : warning_at (loc, opt,
-				(maybe
-				 ? G_("%Kspecified bound %E may exceed "
-				      "source size %E")
-				 : G_("%Kspecified bound %E exceeds "
-				      "source size %E")),
-				exp, bndrng[0], size));
+		  ? warning (dic, opt,
+			     (maybe
+			      ? G_("%qD specified bound %E may exceed "
+				   "source size %E")
+			      : G_("%qD specified bound %E exceeds "
+				   "source size %E")),
+			     func, bndrng[0], size)
+		  : warning (dic, opt,
+			     (maybe
+			      ? G_("specified bound %E may exceed "
+				   "source size %E")
+			      : G_("specified bound %E exceeds "
+				   "source size %E")),
+			     bndrng[0], size));
       else
 	warned = (func
-		  ? warning_at (loc, opt,
-				(maybe
-				 ? G_("%K%qD specified bound [%E, %E] may "
-				      "exceed source size %E")
-				 : G_("%K%qD specified bound [%E, %E] exceeds "
-				      "source size %E")),
-				exp, func, bndrng[0], bndrng[1], size)
-		  : warning_at (loc, opt,
-				(maybe
-				 ? G_("%Kspecified bound [%E, %E] may exceed "
-				      "source size %E")
-				 : G_("%Kspecified bound [%E, %E] exceeds "
-				      "source size %E")),
-				exp, bndrng[0], bndrng[1], size));
+		  ? warning (dic, opt,
+			     (maybe
+			      ? G_("%qD specified bound [%E, %E] may "
+				   "exceed source size %E")
+			      : G_("%qD specified bound [%E, %E] exceeds "
+				   "source size %E")),
+			     func, bndrng[0], bndrng[1], size)
+		  : warning (dic, opt,
+			     (maybe
+			      ? G_("specified bound [%E, %E] may exceed "
+				   "source size %E")
+			      : G_("specified bound [%E, %E] exceeds "
+				   "source size %E")),
+			     bndrng[0], bndrng[1], size));
       if (warned)
 	{
 	  if (pad && pad->src.ref)
@@ -4037,72 +4126,71 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
     {
       if (bndrng[0] == bndrng[1])
 	warned = (func
-		  ? warning_at (loc, opt,
-				(maybe
-				 ? G_("%K%qD specified size %E may "
-				      "exceed maximum object size %E")
-				 : G_("%K%qD specified size %E "
-				      "exceeds maximum object size %E")),
-				exp, func, bndrng[0], maxobjsize)
-		  : warning_at (loc, opt,
-				(maybe
-				 ? G_("%Kspecified size %E may exceed "
-				      "maximum object size %E")
-				 : G_("%Kspecified size %E exceeds "
-				      "maximum object size %E")),
-				exp, bndrng[0], maxobjsize));
+		  ? warning (dic, opt,
+			     (maybe
+			      ? G_("%qD specified size %E may "
+				   "exceed maximum object size %E")
+			      : G_("%qD specified size %E "
+				   "exceeds maximum object size %E")),
+			     func, bndrng[0], maxobjsize)
+		  : warning (dic, opt,
+			     (maybe
+			      ? G_("specified size %E may exceed "
+				   "maximum object size %E")
+			      : G_("specified size %E exceeds "
+				   "maximum object size %E")),
+			     bndrng[0], maxobjsize));
       else
 	warned = (func
-		  ? warning_at (loc, opt,
-				(maybe
-				 ? G_("%K%qD specified size between %E and %E "
-				      "may exceed maximum object size %E")
-				 : G_("%K%qD specified size between %E and %E "
-				      "exceeds maximum object size %E")),
-				exp, func,
-				bndrng[0], bndrng[1], maxobjsize)
-		  : warning_at (loc, opt,
-				(maybe
-				 ? G_("%Kspecified size between %E and %E "
-				      "may exceed maximum object size %E")
-				 : G_("%Kspecified size between %E and %E "
-				      "exceeds maximum object size %E")),
-				exp, bndrng[0], bndrng[1], maxobjsize));
+		  ? warning (dic, opt,
+			     (maybe
+			      ? G_("%qD specified size between %E and %E "
+				   "may exceed maximum object size %E")
+			      : G_("%qD specified size between %E and %E "
+				   "exceeds maximum object size %E")),
+			     func, bndrng[0], bndrng[1], maxobjsize)
+		  : warning (dic, opt,
+			     (maybe
+			      ? G_("specified size between %E and %E "
+				   "may exceed maximum object size %E")
+			      : G_("specified size between %E and %E "
+				   "exceeds maximum object size %E")),
+			     bndrng[0], bndrng[1], maxobjsize));
     }
   else if (!size || tree_int_cst_le (bndrng[0], size))
     return false;
   else if (tree_int_cst_equal (bndrng[0], bndrng[1]))
     warned = (func
-	      ? warning_at (loc, OPT_Wstringop_overflow_,
-			    (maybe
-			     ? G_("%K%qD specified bound %E may exceed "
-				  "destination size %E")
-			     : G_("%K%qD specified bound %E exceeds "
-				  "destination size %E")),
-			    exp, func, bndrng[0], size)
-	      : warning_at (loc, OPT_Wstringop_overflow_,
-			    (maybe
-			     ? G_("%Kspecified bound %E may exceed "
-				  "destination size %E")
-			     : G_("%Kspecified bound %E exceeds "
-				  "destination size %E")),
-			    exp, bndrng[0], size));
+	      ? warning (dic, OPT_Wstringop_overflow_,
+			 (maybe
+			  ? G_("%qD specified bound %E may exceed "
+			       "destination size %E")
+			  : G_("%qD specified bound %E exceeds "
+			       "destination size %E")),
+			 func, bndrng[0], size)
+	      : warning (dic, OPT_Wstringop_overflow_,
+			 (maybe
+			  ? G_("specified bound %E may exceed "
+			       "destination size %E")
+			  : G_("specified bound %E exceeds "
+			       "destination size %E")),
+			 bndrng[0], size));
   else
     warned = (func
-	      ? warning_at (loc, OPT_Wstringop_overflow_,
-			    (maybe
-			     ? G_("%K%qD specified bound [%E, %E] may exceed "
-				  "destination size %E")
-			     : G_("%K%qD specified bound [%E, %E] exceeds "
-				  "destination size %E")),
-			    exp, func, bndrng[0], bndrng[1], size)
-	      : warning_at (loc, OPT_Wstringop_overflow_,
-			    (maybe
-			     ? G_("%Kspecified bound [%E, %E] exceeds "
-				  "destination size %E")
-			     : G_("%Kspecified bound [%E, %E] exceeds "
-				  "destination size %E")),
-			    exp, bndrng[0], bndrng[1], size));
+	      ? warning (dic, OPT_Wstringop_overflow_,
+			 (maybe
+			  ? G_("%qD specified bound [%E, %E] may exceed "
+			       "destination size %E")
+			  : G_("%qD specified bound [%E, %E] exceeds "
+			       "destination size %E")),
+			 func, bndrng[0], bndrng[1], size)
+	      : warning (dic, OPT_Wstringop_overflow_,
+			 (maybe
+			  ? G_("specified bound [%E, %E] exceeds "
+			       "destination size %E")
+			  : G_("specified bound [%E, %E] exceeds "
+			       "destination size %E")),
+			 bndrng[0], bndrng[1], size));
 
   if (warned)
     {
@@ -4129,76 +4217,76 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
    Returns true when a warning has been issued.  */
 
 static bool
-warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
+warn_for_access (tree func, tree exp, int opt, tree range[2],
 		 tree size, bool write, bool read, bool maybe)
 {
+  diag_inlining_context dic (exp);
+
   bool warned = false;
 
   if (write && read)
     {
       if (tree_int_cst_equal (range[0], range[1]))
 	warned = (func
-		  ? warning_n (loc, opt, tree_to_uhwi (range[0]),
+		  ? warning_n (dic, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%K%qD may access %E byte in a region "
+				? G_("%qD may access %E byte in a region "
 				     "of size %E")
-				: G_("%K%qD accessing %E byte in a region "
+				: G_("%qD accessing %E byte in a region "
 				     "of size %E")),
-				(maybe
-				 ? G_ ("%K%qD may access %E bytes in a region "
-				       "of size %E")
-				 : G_ ("%K%qD accessing %E bytes in a region "
-				       "of size %E")),
-			       exp, func, range[0], size)
-		  : warning_n (loc, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%Kmay access %E byte in a region "
+				? G_ ("%qD may access %E bytes in a region "
+				      "of size %E")
+				: G_ ("%qD accessing %E bytes in a region "
+				      "of size %E")),
+			       func, range[0], size)
+		  : warning_n (dic, opt, tree_to_uhwi (range[0]),
+			       (maybe
+				? G_("may access %E byte in a region "
 				     "of size %E")
-				: G_("%Kaccessing %E byte in a region "
+				: G_("accessing %E byte in a region "
 				     "of size %E")),
 			       (maybe
-				? G_("%Kmay access %E bytes in a region "
+				? G_("may access %E bytes in a region "
 				     "of size %E")
-				: G_("%Kaccessing %E bytes in a region "
+				: G_("accessing %E bytes in a region "
 				     "of size %E")),
-			       exp, range[0], size));
+			       range[0], size));
       else if (tree_int_cst_sign_bit (range[1]))
 	{
 	  /* Avoid printing the upper bound if it's invalid.  */
 	  warned = (func
-		    ? warning_at (loc, opt,
-				  (maybe
-				   ? G_("%K%qD may access %E or more bytes "
-					"in a region of size %E")
-				   : G_("%K%qD accessing %E or more bytes "
-					"in a region of size %E")),
-				  exp, func, range[0], size)
-		    : warning_at (loc, opt,
-				  (maybe
-				   ? G_("%Kmay access %E or more bytes "
-					"in a region of size %E")
-				   : G_("%Kaccessing %E or more bytes "
-					"in a region of size %E")),
-				  exp, range[0], size));
+		    ? warning (dic, opt,
+			       (maybe
+				? G_("%qD may access %E or more bytes "
+				     "in a region of size %E")
+				: G_("%qD accessing %E or more bytes "
+				     "in a region of size %E")),
+			       func, range[0], size)
+		    : warning (dic, opt,
+			       (maybe
+				? G_("may access %E or more bytes "
+				     "in a region of size %E")
+				: G_("accessing %E or more bytes "
+				     "in a region of size %E")),
+			       range[0], size));
 	}
       else
 	warned = (func
-		  ? warning_at (loc, opt,
-				(maybe
-				 ? G_("%K%qD may access between %E and %E "
-				      "bytes in a region of size %E")
-				 : G_("%K%qD accessing between %E and %E "
-				      "bytes in a region of size %E")),
-				exp, func, range[0], range[1],
-				size)
-		  : warning_at (loc, opt,
-				(maybe
-				 ? G_("%Kmay access between %E and %E bytes "
-				      "in a region of size %E")
-				 : G_("%Kaccessing between %E and %E bytes "
-				      "in a region of size %E")),
-				exp, range[0], range[1],
-				size));
+		  ? warning (dic, opt,
+			     (maybe
+			      ? G_("%qD may access between %E and %E "
+				   "bytes in a region of size %E")
+			      : G_("%qD accessing between %E and %E "
+				   "bytes in a region of size %E")),
+			     func, range[0], range[1], size)
+		  : warning (dic, opt,
+			     (maybe
+			      ? G_("may access between %E and %E bytes "
+				   "in a region of size %E")
+			      : G_("accessing between %E and %E bytes "
+				   "in a region of size %E")),
+			     range[0], range[1], size));
       return warned;
     }
 
@@ -4206,72 +4294,70 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
     {
       if (tree_int_cst_equal (range[0], range[1]))
 	warned = (func
-		  ? warning_n (loc, opt, tree_to_uhwi (range[0]),
+		  ? warning_n (dic, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%K%qD may write %E byte into a region "
+				? G_("%qD may write %E byte into a region "
 				     "of size %E")
-				: G_("%K%qD writing %E byte into a region "
+				: G_("%qD writing %E byte into a region "
 				     "of size %E overflows the destination")),
 			       (maybe
-				? G_("%K%qD may write %E bytes into a region "
+				? G_("%qD may write %E bytes into a region "
 				     "of size %E")
-				: G_("%K%qD writing %E bytes into a region "
+				: G_("%qD writing %E bytes into a region "
 				     "of size %E overflows the destination")),
-			       exp, func, range[0], size)
-		  : warning_n (loc, opt, tree_to_uhwi (range[0]),
+			       func, range[0], size)
+		  : warning_n (dic, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%Kmay write %E byte into a region "
+				? G_("may write %E byte into a region "
 				     "of size %E")
-				: G_("%Kwriting %E byte into a region "
+				: G_("writing %E byte into a region "
 				     "of size %E overflows the destination")),
 			       (maybe
-				? G_("%Kmay write %E bytes into a region "
+				? G_("may write %E bytes into a region "
 				     "of size %E")
-				: G_("%Kwriting %E bytes into a region "
+				: G_("writing %E bytes into a region "
 				     "of size %E overflows the destination")),
-			       exp, range[0], size));
+			       range[0], size));
       else if (tree_int_cst_sign_bit (range[1]))
 	{
 	  /* Avoid printing the upper bound if it's invalid.  */
 	  warned = (func
-		    ? warning_at (loc, opt,
-				  (maybe
-				   ? G_("%K%qD may write %E or more bytes "
-					"into a region of size %E "
-					"the destination")
-				   : G_("%K%qD writing %E or more bytes "
-					"into a region of size %E overflows "
-					"the destination")),
-				  exp, func, range[0], size)
-		    : warning_at (loc, opt,
-				  (maybe
-				   ? G_("%Kmay write %E or more bytes into "
-					"a region of size %E")
-				   : G_("%Kwriting %E or more bytes into "
-					"a region of size %E overflows "
-					"the destination")),
-				  exp, range[0], size));
+		    ? warning (dic, opt,
+			       (maybe
+				? G_("%qD may write %E or more bytes "
+				     "into a region of size %E "
+				     "the destination")
+				: G_("%qD writing %E or more bytes "
+				     "into a region of size %E overflows "
+				     "the destination")),
+			       func, range[0], size)
+		    : warning (dic, opt,
+			       (maybe
+				? G_("may write %E or more bytes into "
+				     "a region of size %E")
+				: G_("writing %E or more bytes into "
+				     "a region of size %E overflows "
+				     "the destination")),
+			       range[0], size));
 	}
       else
 	warned = (func
-		  ? warning_at (loc, opt,
-				(maybe
-				 ? G_("%K%qD may write between %E and %E bytes "
-				      "into a region of size %E")
-				 : G_("%K%qD writing between %E and %E bytes "
-				      "into a region of size %E overflows "
-				      "the destination")),
-				exp, func, range[0], range[1],
-				size)
-		  : warning_at (loc, opt,
-				(maybe
-				 ? G_("%Kmay write between %E and %E bytes "
-				      "into a region of size %E")
-				 : G_("%Kwriting between %E and %E bytes "
-				      "into a region of size %E overflows "
-				      "the destination")),
-				exp, range[0], range[1],
-				size));
+		  ? warning (dic, opt,
+			     (maybe
+			      ? G_("%qD may write between %E and %E bytes "
+				   "into a region of size %E")
+			      : G_("%qD writing between %E and %E bytes "
+				   "into a region of size %E overflows "
+				   "the destination")),
+			     func, range[0], range[1], size)
+		  : warning (dic, opt,
+			     (maybe
+			      ? G_("may write between %E and %E bytes "
+				   "into a region of size %E")
+			      : G_("writing between %E and %E bytes "
+				   "into a region of size %E overflows "
+				   "the destination")),
+			     range[0], range[1], size));
       return warned;
     }
 
@@ -4279,67 +4365,67 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
     {
       if (tree_int_cst_equal (range[0], range[1]))
 	warned = (func
-		  ? warning_n (loc, OPT_Wstringop_overread,
+		  ? warning_n (dic, OPT_Wstringop_overread,
 			       tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%K%qD may reade %E byte from a region "
+				? G_("%qD may reade %E byte from a region "
 				     "of size %E")
-				: G_("%K%qD reading %E byte from a region "
+				: G_("%qD reading %E byte from a region "
 				     "of size %E")),
 			       (maybe
-				? G_("%K%qD may read %E bytes from a region "
+				? G_("%qD may read %E bytes from a region "
 				     "of size %E")
-				: G_("%K%qD reading %E bytes from a region "
+				: G_("%qD reading %E bytes from a region "
 				     "of size %E")),
-			       exp, func, range[0], size)
-		  : warning_n (loc, OPT_Wstringop_overread,
+			       func, range[0], size)
+		  : warning_n (dic, OPT_Wstringop_overread,
 			       tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%Kmay read %E byte from a region "
+				? G_("may read %E byte from a region "
 				     "of size %E")
-				: G_("%Kreading %E byte from a region "
+				: G_("reading %E byte from a region "
 				     "of size %E")),
 			       (maybe
-				? G_("%Kmay read %E bytes from a region "
+				? G_("may read %E bytes from a region "
 				     "of size %E")
-				: G_("%Kreading %E bytes from a region "
+				: G_("reading %E bytes from a region "
 				     "of size %E")),
-			       exp, range[0], size));
+			       range[0], size));
       else if (tree_int_cst_sign_bit (range[1]))
 	{
 	  /* Avoid printing the upper bound if it's invalid.  */
 	  warned = (func
-		    ? warning_at (loc, OPT_Wstringop_overread,
-				  (maybe
-				   ? G_("%K%qD may read %E or more bytes "
-					"from a region of size %E")
-				   : G_("%K%qD reading %E or more bytes "
-					"from a region of size %E")),
-				  exp, func, range[0], size)
-		    : warning_at (loc, OPT_Wstringop_overread,
-				  (maybe
-				   ? G_("%Kmay read %E or more bytes "
-					"from a region of size %E")
-				   : G_("%Kreading %E or more bytes "
-					"from a region of size %E")),
-				  exp, range[0], size));
+		    ? warning (dic, OPT_Wstringop_overread,
+			       (maybe
+				? G_("%qD may read %E or more bytes "
+				     "from a region of size %E")
+				: G_("%qD reading %E or more bytes "
+				     "from a region of size %E")),
+			       func, range[0], size)
+		    : warning (dic, OPT_Wstringop_overread,
+			       (maybe
+				? G_("may read %E or more bytes "
+				     "from a region of size %E")
+				: G_("reading %E or more bytes "
+				     "from a region of size %E")),
+			       range[0], size));
 	}
       else
 	warned = (func
-		  ? warning_at (loc, OPT_Wstringop_overread,
-				(maybe
-				 ? G_("%K%qD may read between %E and %E bytes "
-				      "from a region of size %E")
-				 : G_("%K%qD reading between %E and %E bytes "
-				      "from a region of size %E")),
-				exp, func, range[0], range[1], size)
-		  : warning_at (loc, opt,
-				(maybe
-				 ? G_("%Kmay read between %E and %E bytes "
-				      "from a region of size %E")
-				 : G_("%Kreading between %E and %E bytes "
-				      "from a region of size %E")),
-				exp, range[0], range[1], size));
+		  ? warning (dic, OPT_Wstringop_overread,
+			     (maybe
+			      ? G_("%qD may read between %E and %E bytes "
+				   "from a region of size %E")
+			      : G_("%qD reading between %E and %E bytes "
+				   "from a region of size %E")),
+			     func, range[0], range[1], size)
+		  : warning (dic, opt,
+			     (maybe
+			      ? G_("may read between %E and %E bytes "
+				   "from a region of size %E")
+			      : G_("reading between %E and %E bytes "
+				   "from a region of size %E")),
+			     range[0], range[1], size));
 
       if (warned)
 	TREE_NO_WARNING (exp) = true;
@@ -4350,39 +4436,39 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
   if (tree_int_cst_equal (range[0], range[1])
       || tree_int_cst_sign_bit (range[1]))
     warned = (func
-	      ? warning_n (loc, OPT_Wstringop_overread,
+	      ? warning_n (dic, OPT_Wstringop_overread,
 			   tree_to_uhwi (range[0]),
-			   "%K%qD epecting %E byte in a region of size %E",
-			   "%K%qD expecting %E bytes in a region of size %E",
-			   exp, func, range[0], size)
-	      : warning_n (loc, OPT_Wstringop_overread,
+			   "%qD epecting %E byte in a region of size %E",
+			   "%qD expecting %E bytes in a region of size %E",
+			   func, range[0], size)
+	      : warning_n (dic, OPT_Wstringop_overread,
 			   tree_to_uhwi (range[0]),
-			   "%Kexpecting %E byte in a region of size %E",
-			   "%Kexpecting %E bytes in a region of size %E",
-			   exp, range[0], size));
+			   "expecting %E byte in a region of size %E",
+			   "expecting %E bytes in a region of size %E",
+			   range[0], size));
   else if (tree_int_cst_sign_bit (range[1]))
     {
       /* Avoid printing the upper bound if it's invalid.  */
       warned = (func
-		? warning_at (loc, OPT_Wstringop_overread,
-			      "%K%qD expecting %E or more bytes in a region "
-			      "of size %E",
-			      exp, func, range[0], size)
-		: warning_at (loc, OPT_Wstringop_overread,
-			      "%Kexpecting %E or more bytes in a region "
-			      "of size %E",
-			      exp, range[0], size));
+		? warning (dic, OPT_Wstringop_overread,
+			   "%qD expecting %E or more bytes in a region "
+			   "of size %E",
+			   func, range[0], size)
+		: warning (dic, OPT_Wstringop_overread,
+			   "expecting %E or more bytes in a region "
+			   "of size %E",
+			   range[0], size));
     }
   else
     warned = (func
-	      ? warning_at (loc, OPT_Wstringop_overread,
-			    "%K%qD expecting between %E and %E bytes in "
-			    "a region of size %E",
-			    exp, func, range[0], range[1], size)
-	      : warning_at (loc, OPT_Wstringop_overread,
-			    "%Kexpectting between %E and %E bytes in "
-			    "a region of size %E",
-			    exp, range[0], range[1], size));
+	      ? warning (dic, OPT_Wstringop_overread,
+			 "%qD expecting between %E and %E bytes in "
+			 "a region of size %E",
+			 func, range[0], range[1], size)
+	      : warning (dic, OPT_Wstringop_overread,
+			 "expectting between %E and %E bytes in "
+			 "a region of size %E",
+			 range[0], range[1], size));
 
   if (warned)
     TREE_NO_WARNING (exp) = true;
@@ -4572,9 +4658,11 @@ access_ref::inform_access (access_mode mode) const
     inform (loc,
 	    "at offset %s into source object of size %s allocated by %qE",
 	    offstr, sizestr, allocfn);
-  else
+  else if (allocfn)
     inform (loc, "source object of size %s allocated by %qE",
 	    sizestr, allocfn);
+  else
+    inform (loc, "source object of size %s allocated here", sizestr);
 }
 
 /* Helper to set RANGE to the range of BOUND if it's nonnull, bounded
@@ -4739,8 +4827,7 @@ check_access (tree exp, tree dstwrite,
       && TREE_CODE (range[0]) == INTEGER_CST
       && tree_int_cst_lt (maxobjsize, range[0]))
     {
-      location_t loc = tree_inlined_location (exp);
-      maybe_warn_for_bound (OPT_Wstringop_overflow_, loc, exp, func, range,
+      maybe_warn_for_bound (OPT_Wstringop_overflow_, exp, func, range,
 			    NULL_TREE, pad);
       return false;
     }
@@ -4765,24 +4852,24 @@ check_access (tree exp, tree dstwrite,
 	      || (pad && pad->dst.ref && TREE_NO_WARNING (pad->dst.ref)))
 	    return false;
 
-	  location_t loc = tree_inlined_location (exp);
 	  bool warned = false;
 	  if (dstwrite == slen && at_least_one)
 	    {
+	      diag_inlining_context dic (exp);
 	      /* This is a call to strcpy with a destination of 0 size
 		 and a source of unknown length.  The call will write
 		 at least one byte past the end of the destination.  */
 	      warned = (func
-			? warning_at (loc, OPT_Wstringop_overflow_,
-				      "%K%qD writing %E or more bytes into "
-				      "a region of size %E overflows "
-				      "the destination",
-				      exp, func, range[0], dstsize)
-			: warning_at (loc, OPT_Wstringop_overflow_,
-				      "%Kwriting %E or more bytes into "
-				      "a region of size %E overflows "
-				      "the destination",
-				      exp, range[0], dstsize));
+			? warning (dic, OPT_Wstringop_overflow_,
+				   "%qD writing %E or more bytes into "
+				   "a region of size %E overflows "
+				   "the destination",
+				   func, range[0], dstsize)
+			: warning (dic, OPT_Wstringop_overflow_,
+				   "writing %E or more bytes into "
+				   "a region of size %E overflows "
+				   "the destination",
+				   range[0], dstsize));
 	    }
 	  else
 	    {
@@ -4791,8 +4878,7 @@ check_access (tree exp, tree dstwrite,
 	      const bool write
 		= mode == access_write_only || mode == access_read_write;
 	      const bool maybe = pad && pad->dst.parmarray;
-	      warned = warn_for_access (loc, func, exp,
-					OPT_Wstringop_overflow_,
+	      warned = warn_for_access (func, exp, OPT_Wstringop_overflow_,
 					range, dstsize,
 					write, read && !builtin, maybe);
 	    }
@@ -4818,7 +4904,6 @@ check_access (tree exp, tree dstwrite,
 	 PAD is nonnull and BNDRNG is valid.  */
       get_size_range (maxread, range, pad ? pad->src.bndrng : NULL);
 
-      location_t loc = tree_inlined_location (exp);
       tree size = dstsize;
       if (pad && pad->mode == access_read_only)
 	size = wide_int_to_tree (sizetype, pad->src.sizrng[1]);
@@ -4827,7 +4912,7 @@ check_access (tree exp, tree dstwrite,
 	{
 	  if (tree_int_cst_lt (maxobjsize, range[0]))
 	    {
-	      maybe_warn_for_bound (OPT_Wstringop_overread, loc, exp, func,
+	      maybe_warn_for_bound (OPT_Wstringop_overread, exp, func,
 				    range, size, pad);
 	      return false;
 	    }
@@ -4837,7 +4922,7 @@ check_access (tree exp, tree dstwrite,
 	      int opt = (dstwrite || mode != access_read_only
 			 ? OPT_Wstringop_overflow_
 			 : OPT_Wstringop_overread);
-	      maybe_warn_for_bound (opt, loc, exp, func, range, size, pad);
+	      maybe_warn_for_bound (opt, exp, func, range, size, pad);
 	      return false;
 	    }
 	}
@@ -4877,11 +4962,10 @@ check_access (tree exp, tree dstwrite,
 	  || (pad && pad->src.ref && TREE_NO_WARNING (pad->src.ref)))
 	return false;
 
-      location_t loc = tree_inlined_location (exp);
       const bool read
 	= mode == access_read_only || mode == access_read_write;
       const bool maybe = pad && pad->dst.parmarray;
-      if (warn_for_access (loc, func, exp, OPT_Wstringop_overread, range,
+      if (warn_for_access (func, exp, OPT_Wstringop_overread, range,
 			   slen, false, read, maybe))
 	{
 	  TREE_NO_WARNING (exp) = true;
@@ -7067,13 +7151,13 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
 	      offset_int rem1 = ref1.size_remaining ();
 	      offset_int rem2 = ref2.size_remaining ();
 	      if (rem1 == 0 || rem2 == 0)
-		maybe_warn_for_bound (OPT_Wstringop_overread, loc, exp, func,
+		maybe_warn_for_bound (OPT_Wstringop_overread, exp, func,
 				      bndrng, integer_zero_node);
 	      else
 		{
 		  offset_int maxrem = wi::max (rem1, rem2, UNSIGNED);
 		  if (maxrem < wi::to_offset (bndrng[0]))
-		    maybe_warn_for_bound (OPT_Wstringop_overread, loc, exp,
+		    maybe_warn_for_bound (OPT_Wstringop_overread, exp,
 					  func, bndrng,
 					  wide_int_to_tree (sizetype, maxrem));
 		}
@@ -7082,7 +7166,7 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
 		   && !integer_zerop (bndrng[0])
 		   && ((size1 && integer_zerop (size1))
 		       || (size2 && integer_zerop (size2))))
-	    maybe_warn_for_bound (OPT_Wstringop_overread, loc, exp, func,
+	    maybe_warn_for_bound (OPT_Wstringop_overread, exp, func,
 				  bndrng, integer_zero_node);
 	}
     }
@@ -13436,7 +13520,7 @@ matching_alloc_calls_p (gimple *alloc, tree dealloc_decl)
    the target pointer is unknown.  */
 
 static bool
-warn_dealloc_offset (location_t loc, tree exp, const access_ref &aref)
+warn_dealloc_offset (tree exp, const access_ref &aref)
 {
   if (aref.deref || aref.offrng[0] <= 0 || aref.offrng[1] <= 0)
     return false;
@@ -13477,9 +13561,10 @@ warn_dealloc_offset (location_t loc, tree exp, const access_ref &aref)
 		 (long long)aref.offrng[1].to_shwi ());
     }
 
-  if (!warning_at (loc, OPT_Wfree_nonheap_object,
-		   "%K%qD called on pointer %qE with nonzero offset%s",
-		   exp, dealloc_decl, aref.ref, offstr))
+  diag_inlining_context dic (exp);
+  if (!warning (dic, OPT_Wfree_nonheap_object,
+		"%qD called on pointer %qE with nonzero offset%s",
+		dealloc_decl, aref.ref, offstr))
     return false;
 
   if (DECL_P (aref.ref))
@@ -13534,19 +13619,20 @@ maybe_emit_free_warning (tree exp)
     return;
 
   tree dealloc_decl = get_callee_fndecl (exp);
-  location_t loc = tree_inlined_location (exp);
 
   if (DECL_P (ref) || EXPR_P (ref))
     {
+      diag_inlining_context dic (exp);
+
       /* Diagnose freeing a declared object.  */
       if (aref.ref_declared ()
-	  && warning_at (loc, OPT_Wfree_nonheap_object,
-			 "%K%qD called on unallocated object %qD",
-			 exp, dealloc_decl, ref))
+	  && warning (dic, OPT_Wfree_nonheap_object,
+		      "%qD called on unallocated object %qD",
+		      dealloc_decl, ref))
 	{
-	  loc = (DECL_P (ref)
-		 ? DECL_SOURCE_LOCATION (ref)
-		 : EXPR_LOCATION (ref));
+	  location_t loc = (DECL_P (ref)
+			    ? DECL_SOURCE_LOCATION (ref)
+			    : EXPR_LOCATION (ref));
 	  inform (loc, "declared here");
 	  return;
 	}
@@ -13555,14 +13641,15 @@ maybe_emit_free_warning (tree exp)
 	 Such a pointer cannot refer to the beginning of an allocated
 	 object.  A negative offset may refer to it.  */
       if (aref.sizrng[0] != aref.sizrng[1]
-	  && warn_dealloc_offset (loc, exp, aref))
+	  && warn_dealloc_offset (exp, aref))
 	return;
     }
   else if (CONSTANT_CLASS_P (ref))
     {
-      if (warning_at (loc, OPT_Wfree_nonheap_object,
-		      "%K%qD called on a pointer to an unallocated "
-		      "object %qE", exp, dealloc_decl, ref))
+      diag_inlining_context dic (exp);
+      if (warning (dic, OPT_Wfree_nonheap_object,
+		   "%qD called on a pointer to an unallocated "
+		   "object %qE", dealloc_decl, ref))
 	{
 	  if (TREE_CODE (ptr) == SSA_NAME)
 	    {
@@ -13588,7 +13675,7 @@ maybe_emit_free_warning (tree exp)
 	    {
 	      if (matching_alloc_calls_p (def_stmt, dealloc_decl))
 		{
-		  if (warn_dealloc_offset (loc, exp, aref))
+		  if (warn_dealloc_offset (exp, aref))
 		    return;
 		}
 	      else
@@ -13598,20 +13685,24 @@ maybe_emit_free_warning (tree exp)
 			     || DECL_IS_OPERATOR_DELETE_P (dealloc_decl)
 			     ? OPT_Wmismatched_new_delete
 			     : OPT_Wmismatched_dealloc);
-		  warned = warning_at (loc, opt,
-				       "%K%qD called on pointer returned "
-				       "from a mismatched allocation "
-				       "function", exp, dealloc_decl);
+		  diag_inlining_context dic (exp);
+		  warned = warning (dic, opt,
+				    "%qD called on pointer returned "
+				    "from a mismatched allocation "
+				    "function", dealloc_decl);
 		}
 	    }
 	  else if (gimple_call_builtin_p (def_stmt, BUILT_IN_ALLOCA)
 	    	   || gimple_call_builtin_p (def_stmt,
 	    				     BUILT_IN_ALLOCA_WITH_ALIGN))
-	    warned = warning_at (loc, OPT_Wfree_nonheap_object,
-				 "%K%qD called on pointer to "
-				 "an unallocated object",
-				 exp, dealloc_decl);
-	  else if (warn_dealloc_offset (loc, exp, aref))
+	    {
+	      diag_inlining_context dic (exp);
+	      warned = warning (dic, OPT_Wfree_nonheap_object,
+				"%qD called on pointer to "
+				"an unallocated object",
+				dealloc_decl);
+	    }
+	  else if (warn_dealloc_offset (exp, aref))
 	    return;
 
 	  if (warned)
@@ -13630,7 +13721,7 @@ maybe_emit_free_warning (tree exp)
 	      && !aref.deref
 	      && aref.sizrng[0] != aref.sizrng[1]
 	      && aref.offrng[0] > 0 && aref.offrng[1] > 0
-	      && warn_dealloc_offset (loc, exp, aref))
+	      && warn_dealloc_offset (exp, aref))
 	    return;
 	}
     }
diff --git a/gcc/cp/mapper-client.cc b/gcc/cp/mapper-client.cc
index a72b4b70664..368e88201fa 100644
--- a/gcc/cp/mapper-client.cc
+++ b/gcc/cp/mapper-client.cc
@@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.  If not see
 #define INCLUDE_STRING
 #define INCLUDE_VECTOR
 #include "system.h"
-
+#include "coretypes.h"
 #include "line-map.h"
 #include "diagnostic-core.h"
 #include "mapper-client.h"
diff --git a/gcc/diagnostic-core.h b/gcc/diagnostic-core.h
index 60fe8a27f44..cdf70ddfb46 100644
--- a/gcc/diagnostic-core.h
+++ b/gcc/diagnostic-core.h
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_DIAGNOSTIC_CORE_H
 
 #include "bversion.h"
+#include "diagnostic-metadata.h"
 
 /* Constants used to discriminate diagnostics.  */
 typedef enum
@@ -81,6 +82,16 @@ extern bool warning_at (location_t, int, const char *, ...)
     ATTRIBUTE_GCC_DIAG(3,4);
 extern bool warning_at (rich_location *, int, const char *, ...)
     ATTRIBUTE_GCC_DIAG(3,4);
+
+/* Same as warning_at but with contextual informaion provided by first
+   argument.  */
+extern bool warning (diagnostic_metadata::location_context&, int,
+		     const char *, ...)
+  ATTRIBUTE_GCC_DIAG (3, 4);
+extern bool warning_n (diagnostic_metadata::location_context&, int,
+		       unsigned HOST_WIDE_INT, const char *, const char *, ...)
+    ATTRIBUTE_GCC_DIAG (4, 6) ATTRIBUTE_GCC_DIAG (5, 6);
+
 extern bool warning_meta (rich_location *,
 			  const diagnostic_metadata &, int,
 			  const char *, ...)
diff --git a/gcc/diagnostic-metadata.h b/gcc/diagnostic-metadata.h
index fe10304e05e..db49cff72b9 100644
--- a/gcc/diagnostic-metadata.h
+++ b/gcc/diagnostic-metadata.h
@@ -21,22 +21,45 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_DIAGNOSTIC_METADATA_H
 #define GCC_DIAGNOSTIC_METADATA_H
 
+#include "vec.h"
+
 /* A bundle of additional metadata that can be associated with a
    diagnostic.
 
-   Currently this only supports associating a CWE identifier with a
-   diagnostic.  */
+   Currently this only supports associating a location context and
+   a CWE identifier with a diagnostic.  */
 
 class diagnostic_metadata
 {
  public:
-  diagnostic_metadata () : m_cwe (0) {}
+  class location_context;
+
+  diagnostic_metadata () : m_lctx (), m_cwe (0) {}
+
+  diagnostic_metadata (location_context &lctx)
+    : m_lctx (&lctx), m_cwe () {}
 
   void add_cwe (int cwe) { m_cwe = cwe; }
   int get_cwe () const { return m_cwe; }
 
+  location_context* location_ctx () const { return m_lctx; }
+
  private:
+  /* The context of the expression the diagnostic is issued for.  For
+     front end diagnostics it's empty.  For middle end diagnostics it
+     includes the inlining context (implemented in a derived class).  */
+  location_context *m_lctx;
   int m_cwe;
 };
 
+struct diagnostic_info;
+
+class diagnostic_metadata::location_context
+{
+public:
+  virtual void locations (vec<location_t> &, diagnostic_info *);
+  virtual void set_location (diagnostic_info *) { }
+};
+
+
 #endif /* ! GCC_DIAGNOSTIC_METADATA_H */
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 246d75256cf..abcd991b829 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "selftest-diagnostic.h"
 #include "opts.h"
 #include "cpplib.h"
+#include "tree.h"
 
 #ifdef HAVE_TERMIOS_H
 # include <termios.h>
@@ -991,51 +992,81 @@ print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
   pp_set_prefix (pp, saved_prefix);
 }
 
-/* Update the diag_class of DIAGNOSTIC based on its location
-   relative to any
+/* Add DIAGNOSTIC location to LOCS.  */
+
+/* virtual */ void
+diagnostic_metadata::
+location_context::locations (vec<location_t> &locs, diagnostic_info *di)
+{
+  locs.safe_push (diagnostic_location (di));
+}
+
+
+/* Update the kind of DIAGNOSTIC based on its location(s), including
+   any of those in its inlining context, relative to any
      #pragma GCC diagnostic
    directives recorded within CONTEXT.
 
-   Return the new diag_class of DIAGNOSTIC if it was updated, or
-   DK_UNSPECIFIED otherwise.  */
+   Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
+   otherwise.  */
 
 static diagnostic_t
 update_effective_level_from_pragmas (diagnostic_context *context,
 				     diagnostic_info *diagnostic)
 {
-  diagnostic_t diag_class = DK_UNSPECIFIED;
-
   if (context->n_classification_history > 0)
     {
-      location_t location = diagnostic_location (diagnostic);
-
-      /* FIXME: Stupid search.  Optimize later. */
-      for (int i = context->n_classification_history - 1; i >= 0; i --)
+      auto_vec<location_t, 8> locs;
+      diagnostic_metadata::location_context *lctx = NULL;
+      if (const diagnostic_metadata *mdata = diagnostic->metadata)
+	lctx = mdata->location_ctx ();
+
+      if (lctx)
+	/* Retrieve the locations into which the expression about to be
+	   diagnosed has been inlined, including those of all the callers
+	   all the way down the inlining stack.  */
+	lctx->locations (locs, diagnostic);
+      else
+	/* When there's no metadata use just the one location provided
+	   by the caller of the diagnostic function.  */
+	locs.safe_push (diagnostic_location (diagnostic));
+
+      /* Iterate over the locations, checking the diagnostic disposition
+	 for the diagnostic at each.  If it's explicitly set as opposed
+	 to unspecified, update the disposition for this instance of
+	 the diagnostic and return it.  */
+      for (unsigned idx = 0; idx < locs.length (); ++idx)
 	{
-	  if (linemap_location_before_p
-	      (line_table,
-	       context->classification_history[i].location,
-	       location))
+	  /* FIXME: Stupid search.  Optimize later. */
+	  for (int i = context->n_classification_history - 1; i >= 0; i --)
 	    {
-	      if (context->classification_history[i].kind == (int) DK_POP)
-		{
-		  i = context->classification_history[i].option;
-		  continue;
-		}
-	      int option = context->classification_history[i].option;
-	      /* The option 0 is for all the diagnostics.  */
-	      if (option == 0 || option == diagnostic->option_index)
+	      const diagnostic_classification_change_t &hist
+		= context->classification_history[i];
+
+	      location_t pragloc = hist.location;
+	      if (linemap_location_before_p (line_table, pragloc, locs[idx]))
 		{
-		  diag_class = context->classification_history[i].kind;
-		  if (diag_class != DK_UNSPECIFIED)
-		    diagnostic->kind = diag_class;
-		  break;
+		  if (hist.kind == (int) DK_POP)
+		    {
+		      /* Move on to the next region.  */
+		      i = hist.option;
+		      continue;
+		    }
+		  int option = hist.option;
+		  /* The option 0 is for all the diagnostics.  */
+		  if (option == 0 || option == diagnostic->option_index)
+		    {
+		      diagnostic_t kind = hist.kind;
+		      if (kind != DK_UNSPECIFIED)
+			diagnostic->kind = kind;
+		      return kind;
+		    }
 		}
 	    }
 	}
     }
 
-  return diag_class;
+  return DK_UNSPECIFIED;
 }
 
 /* Generate a URL string describing CWE.  The caller is responsible for
@@ -1239,8 +1270,14 @@ diagnostic_report_diagnostic (diagnostic_context *context,
     }
   context->diagnostic_group_emission_count++;
 
+  /* Move X_DATA into DIAGNOSTIC->MESSAGE before setting inlining context
+     abstract origin and location.  It uses X_DATA.  */
   diagnostic->message.x_data = &diagnostic->x_data;
   diagnostic->x_data = NULL;
+  if (const diagnostic_metadata *mdata = diagnostic->metadata)
+    if (diagnostic_metadata::location_context *lctx = mdata->location_ctx ())
+      lctx->set_location (diagnostic);
+
   pp_format (context->printer, &diagnostic->message);
   (*diagnostic_starter (context)) (context, diagnostic);
   pp_output_formatted_text (context->printer);
@@ -1616,6 +1653,46 @@ warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
   return ret;
 }
 
+/* A warning at location and context provided by first argument.  Same
+   as warning_at() with location_t except that it doesn't require %K (or
+   in the future %G).  */
+
+bool
+warning (diagnostic_metadata::location_context &lctx, int opt,
+	 const char *gmsgid, ...)
+{
+  auto_diagnostic_group d;
+  va_list ap;
+  va_start (ap, gmsgid);
+  rich_location richloc (line_table, UNKNOWN_LOCATION);
+  diagnostic_metadata mdata (lctx);
+  bool ret = diagnostic_impl (&richloc, &mdata, opt, gmsgid,
+			      &ap, DK_WARNING);
+  va_end (ap);
+  return ret;
+}
+
+/* A warning at location and context provided by first argument.  Same
+   as warning_n() with location_t except that it doesn't require %K (or
+   in the future %G).  */
+
+bool
+warning_n (diagnostic_metadata::location_context &lctx, int opt,
+	   unsigned HOST_WIDE_INT n,
+	   const char *singular_gmsgid, const char *plural_gmsgid, ...)
+{
+  auto_diagnostic_group d;
+  va_list ap;
+  va_start (ap, plural_gmsgid);
+  rich_location richloc (line_table, UNKNOWN_LOCATION);
+  diagnostic_metadata mdata (lctx);
+  bool ret = diagnostic_n_impl (&richloc, &mdata, opt, n,
+				singular_gmsgid, plural_gmsgid,
+				&ap, DK_WARNING);
+  va_end (ap);
+  return ret;
+}
+
 /* A "pedantic" warning at LOCATION: issues a warning unless
    -pedantic-errors was given on the command line, in which case it
    issues an error.  Use this for diagnostics required by the relevant
diff --git a/gcc/testsuite/gcc.dg/pragma-diag-9.c b/gcc/testsuite/gcc.dg/pragma-diag-9.c
new file mode 100644
index 00000000000..d7eac558128
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pragma-diag-9.c
@@ -0,0 +1,134 @@
+/* Verify that #pragma GCC diagnostic down the inlining stack suppresses
+   a warning that would otherwise be issued for inlined calls higher up
+   the inlining stack.
+   { dg-do compile }
+   { dg-options "-O2 -Wall -Wno-array-bounds" } */
+
+extern void* memset (void*, int, __SIZE_TYPE__);
+
+static void warn0 (int *p)
+{
+  memset (p, __LINE__, 3);    // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+static void warn1 (int *p)
+{
+  warn0 (p + 1);
+}
+
+static void warn2 (int *p)
+{
+  warn1 (p + 1);
+}
+
+int a2[2];                    // { dg-message "at offset 12 into destination object 'a2' of size 8" }
+
+void warn3 (void)
+{
+  warn2 (a2 + 1);
+}
+
+
+static void ignore0 (int *p)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  memset (p, __LINE__, 3);
+#pragma GCC diagnostic pop
+}
+
+static void nowarn1_ignore0 (int *p)
+{
+  ignore0 (p + 1);
+}
+
+static void nowarn2_ignore0 (int *p)
+{
+  nowarn1_ignore0 (p + 1);
+}
+
+int b2[2];
+
+void nowarn3_ignore0 (void)
+{
+  nowarn2_ignore0 (b2 + 1);
+}
+
+
+static void nowarn0_ignore1 (int *p)
+{
+  memset (p, __LINE__, 3);
+}
+
+static void ignore1 (int *p)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  nowarn0_ignore1 (p + 1);
+#pragma GCC diagnostic pop
+}
+
+void nowarn2_ignore1 (int *p)
+{
+  ignore1 (p + 1);
+}
+
+int c2[2];
+
+void nowarn3_ignore1 (void)
+{
+  nowarn2_ignore1 (c2 + 1);
+}
+
+
+static void nowarn0_ignore2 (int *p)
+{
+  memset (p, __LINE__, 3);
+}
+
+static void nowarn1_ignore2 (int *p)
+{
+  nowarn0_ignore2 (p + 1);
+}
+
+static void ignore2 (int *p)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  nowarn1_ignore2 (p + 1);
+#pragma GCC diagnostic pop
+}
+
+int d2[2];
+
+void nowarn3_ignore2 (void)
+{
+  ignore2 (c2 + 1);
+}
+
+
+
+static void nowarn0_ignore3 (int *p)
+{
+  memset (p, __LINE__, 3);
+}
+
+static void nowarn1_ignore3 (int *p)
+{
+  nowarn0_ignore3 (p + 1);
+}
+
+static void nowarn2_ignore3 (int *p)
+{
+  nowarn1_ignore3 (p + 1);
+}
+
+int e2[2];
+
+void ignore3 (void)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  nowarn2_ignore3 (e2 + 1);
+#pragma GCC diagnostic pop
+}
diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc
index 5beda8b829b..c3faa6bfde4 100644
--- a/libstdc++-v3/include/bits/basic_string.tcc
+++ b/libstdc++-v3/include/bits/basic_string.tcc
@@ -468,6 +468,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	    }
 	  else
 	    {
+	      /* Suppress false positives when GCC can't determine that
+		 __s doesn't alias _M_data().  */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+#pragma GCC diagnostic ignored "-Wstringop-overread"
 	      // Work in-place.
 	      if (__len2 && __len2 <= __len1)
 		this->_S_move(__p, __s, __len2);
@@ -488,6 +493,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		    }
 		}
 	    }
+#pragma GCC diagnostic pop
 	}
       else
 	this->_M_mutate(__pos, __len1, __s, __len2);
diff --git a/libstdc++-v3/testsuite/18_support/new_delete_placement.cc b/libstdc++-v3/testsuite/18_support/new_delete_placement.cc
index e4f747606cd..1d188f6edd8 100644
--- a/libstdc++-v3/testsuite/18_support/new_delete_placement.cc
+++ b/libstdc++-v3/testsuite/18_support/new_delete_placement.cc
@@ -32,6 +32,8 @@ void test01()
   operator delete[](p, tmp);
 }
 
+// { dg-prune-output "\\\[-Wfree-nonheap-object" }
+
 int main()
 {
   test01();
diff --git a/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/allocate.cc b/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/allocate.cc
index 95d512d4b82..55973992837 100644
--- a/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/allocate.cc
+++ b/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/allocate.cc
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17" }
+// { dg-options "-std=gnu++17 -Wno-alloc-size-larger-than" }
 // { dg-do run { target c++17 } }
 // { dg-require-cstdint "" }
 
diff --git a/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/allocate.cc b/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/allocate.cc
index 79fac01fb25..fab73838f38 100644
--- a/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/allocate.cc
+++ b/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/allocate.cc
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17" }
+// { dg-options "-std=gnu++17 -Wno-alloc-size-larger-than" }
 // { dg-do run { target c++17 } }
 
 #include <memory_resource>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] improve warning suppression for inlined functions (PR 98465,  98512)
  2021-01-19 18:58 [PATCH] improve warning suppression for inlined functions (PR 98465, 98512) Martin Sebor
@ 2021-01-21 17:34 ` Florian Weimer
  2021-01-21 18:24   ` Martin Sebor
  2021-01-21 23:46 ` Martin Sebor
  2021-02-19  4:28 ` [PATCH] improve warning suppression for inlined functions (PR 98465, 98512) Jeff Law
  2 siblings, 1 reply; 44+ messages in thread
From: Florian Weimer @ 2021-01-21 17:34 UTC (permalink / raw)
  To: Martin Sebor via Gcc-patches

* Martin Sebor via Gcc-patches:

> This patch depends on the fix for PR 98664 (already approved but
> not yet checked in).  I've tested it on x86_64-linux.
>
> To avoid fallout I tried to keep the changes to a minimum, and
> so the design isn't as robust as I'd like it ultimately to be.
> I plan to enhance it in stage 1.

I've tested this patch on top of 43705f3fa343e08b2fb030460f (so with the
PR98664 fix, I think), and the reproducer from PR98512 now ICEs:

void *
__rawmemchr_ppc (const void *s, int c)
{
#pragma GCC diagnostics push
#pragma GCC diagnostic ignored "-Wstringop-overflow="
#pragma GCC diagnostic ignored "-Wstringop-overread"
  if (c != 0)
    return __builtin_memchr (s, c, (unsigned long)-1);
#pragma GCC diagnostics pop
  return (char *)s + __builtin_strlen (s);
}
extern __typeof (__rawmemchr_ppc) __EI___rawmemchr_ppc
  __attribute__((alias ("__rawmemchr_ppc")));

during RTL pass: expand
t.c: In function ‘__rawmemchr_ppc’:
t.c:8:12: internal compiler error: Segmentation fault
    8 |     return __builtin_memchr (s, c, (unsigned long)-1);
      |            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0xde134f crash_signal
        /home/bmg/src/gcc/gcc/toplev.c:327
0x9181bd diag_inlining_context::set_locations(vec<unsigned int, va_heap, vl_ptr>*, diagnostic_info*)
        /home/bmg/src/gcc/gcc/builtins.c:835
0x17ce2da update_effective_level_from_pragmas
        /home/bmg/src/gcc/gcc/diagnostic.c:1028
0x17ce2da diagnostic_report_diagnostic(diagnostic_context*, diagnostic_info*)
        /home/bmg/src/gcc/gcc/diagnostic.c:1218
0x17ceb1e diagnostic_impl
        /home/bmg/src/gcc/gcc/diagnostic.c:1443
0x17cf144 warning(diagnostic_metadata::location_context&, int, char const*, ...)
        /home/bmg/src/gcc/gcc/diagnostic.c:1669
0x917ab0 maybe_warn_for_bound
        /home/bmg/src/gcc/gcc/builtins.c:4077
0x927eee maybe_warn_for_bound
        /home/bmg/src/gcc/gcc/builtins.c:4920
0x927eee check_access(tree_node*, tree_node*, tree_node*, tree_node*, tree_node*, access_mode, access_data const*)
        /home/bmg/src/gcc/gcc/builtins.c:4918
0x928b52 check_read_access
        /home/bmg/src/gcc/gcc/builtins.c:4996
0x92e19b check_read_access
        /home/bmg/src/gcc/gcc/builtins.c:9992
0x92e19b expand_builtin_memchr
        /home/bmg/src/gcc/gcc/builtins.c:5926
0x92e19b expand_builtin(tree_node*, rtx_def*, rtx_def*, machine_mode, int)
        /home/bmg/src/gcc/gcc/builtins.c:9992
0xa6d714 expand_expr_real_1(tree_node*, rtx_def*, machine_mode, expand_modifier, rtx_def**, bool)
        /home/bmg/src/gcc/gcc/expr.c:11275
0xa796fb store_expr(tree_node*, rtx_def*, int, bool, bool)
        /home/bmg/src/gcc/gcc/expr.c:5885
0xa7ab71 expand_assignment(tree_node*, tree_node*, bool)
        /home/bmg/src/gcc/gcc/expr.c:5621
0x9569bb expand_call_stmt
        /home/bmg/src/gcc/gcc/cfgexpand.c:2837
0x9569bb expand_gimple_stmt_1
        /home/bmg/src/gcc/gcc/cfgexpand.c:3843
0x9569bb expand_gimple_stmt
        /home/bmg/src/gcc/gcc/cfgexpand.c:4007
0x95c60f expand_gimple_basic_block
        /home/bmg/src/gcc/gcc/cfgexpand.c:6044

Thanks,
Florian
-- 
Red Hat GmbH, https://de.redhat.com/ , Registered seat: Grasbrunn,
Commercial register: Amtsgericht Muenchen, HRB 153243,
Managing Directors: Charles Cachera, Brian Klemm, Laurie Krebs, Michael O'Neill


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] improve warning suppression for inlined functions (PR 98465, 98512)
  2021-01-21 17:34 ` Florian Weimer
@ 2021-01-21 18:24   ` Martin Sebor
  2021-01-21 19:01     ` Florian Weimer
  0 siblings, 1 reply; 44+ messages in thread
From: Martin Sebor @ 2021-01-21 18:24 UTC (permalink / raw)
  To: Florian Weimer, Martin Sebor via Gcc-patches

On 1/21/21 10:34 AM, Florian Weimer wrote:
> * Martin Sebor via Gcc-patches:
> 
>> This patch depends on the fix for PR 98664 (already approved but
>> not yet checked in).  I've tested it on x86_64-linux.
>>
>> To avoid fallout I tried to keep the changes to a minimum, and
>> so the design isn't as robust as I'd like it ultimately to be.
>> I plan to enhance it in stage 1.
> 
> I've tested this patch on top of 43705f3fa343e08b2fb030460f (so with the
> PR98664 fix, I think), and the reproducer from PR98512 now ICEs:

Thanks for giving it a try!  I saw a similar ICE during my testing
-- it's caused by a couple of uninitialized variables.  I fixed
it in my tree (see below) but the fix didn't make it into the patch.

Please give this a try and let me know if it doesn't help:

index abcd991b829..d82a7eb67e5 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -1426,7 +1426,7 @@ diagnostic_impl (rich_location *richloc, const 
diagnostic_metadata *metadata,
                  int opt, const char *gmsgid,
                  va_list *ap, diagnostic_t kind)
  {
-  diagnostic_info diagnostic;
+  diagnostic_info diagnostic{ };
    if (kind == DK_PERMERROR)
      {
        diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
@@ -1452,7 +1452,7 @@ diagnostic_n_impl (rich_location *richloc, const 
diagnostic_metadata *metadata,
                    const char *plural_gmsgid,
                    va_list *ap, diagnostic_t kind)
  {
-  diagnostic_info diagnostic;
+  diagnostic_info diagnostic{ };
    unsigned long gtn;

    if (sizeof n <= sizeof gtn)

Martin

> 
> void *
> __rawmemchr_ppc (const void *s, int c)
> {
> #pragma GCC diagnostics push
> #pragma GCC diagnostic ignored "-Wstringop-overflow="
> #pragma GCC diagnostic ignored "-Wstringop-overread"
>    if (c != 0)
>      return __builtin_memchr (s, c, (unsigned long)-1);
> #pragma GCC diagnostics pop
>    return (char *)s + __builtin_strlen (s);
> }
> extern __typeof (__rawmemchr_ppc) __EI___rawmemchr_ppc
>    __attribute__((alias ("__rawmemchr_ppc")));
> 
> during RTL pass: expand
> t.c: In function ‘__rawmemchr_ppc’:
> t.c:8:12: internal compiler error: Segmentation fault
>      8 |     return __builtin_memchr (s, c, (unsigned long)-1);
>        |            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 0xde134f crash_signal
>          /home/bmg/src/gcc/gcc/toplev.c:327
> 0x9181bd diag_inlining_context::set_locations(vec<unsigned int, va_heap, vl_ptr>*, diagnostic_info*)
>          /home/bmg/src/gcc/gcc/builtins.c:835
> 0x17ce2da update_effective_level_from_pragmas
>          /home/bmg/src/gcc/gcc/diagnostic.c:1028
> 0x17ce2da diagnostic_report_diagnostic(diagnostic_context*, diagnostic_info*)
>          /home/bmg/src/gcc/gcc/diagnostic.c:1218
> 0x17ceb1e diagnostic_impl
>          /home/bmg/src/gcc/gcc/diagnostic.c:1443
> 0x17cf144 warning(diagnostic_metadata::location_context&, int, char const*, ...)
>          /home/bmg/src/gcc/gcc/diagnostic.c:1669
> 0x917ab0 maybe_warn_for_bound
>          /home/bmg/src/gcc/gcc/builtins.c:4077
> 0x927eee maybe_warn_for_bound
>          /home/bmg/src/gcc/gcc/builtins.c:4920
> 0x927eee check_access(tree_node*, tree_node*, tree_node*, tree_node*, tree_node*, access_mode, access_data const*)
>          /home/bmg/src/gcc/gcc/builtins.c:4918
> 0x928b52 check_read_access
>          /home/bmg/src/gcc/gcc/builtins.c:4996
> 0x92e19b check_read_access
>          /home/bmg/src/gcc/gcc/builtins.c:9992
> 0x92e19b expand_builtin_memchr
>          /home/bmg/src/gcc/gcc/builtins.c:5926
> 0x92e19b expand_builtin(tree_node*, rtx_def*, rtx_def*, machine_mode, int)
>          /home/bmg/src/gcc/gcc/builtins.c:9992
> 0xa6d714 expand_expr_real_1(tree_node*, rtx_def*, machine_mode, expand_modifier, rtx_def**, bool)
>          /home/bmg/src/gcc/gcc/expr.c:11275
> 0xa796fb store_expr(tree_node*, rtx_def*, int, bool, bool)
>          /home/bmg/src/gcc/gcc/expr.c:5885
> 0xa7ab71 expand_assignment(tree_node*, tree_node*, bool)
>          /home/bmg/src/gcc/gcc/expr.c:5621
> 0x9569bb expand_call_stmt
>          /home/bmg/src/gcc/gcc/cfgexpand.c:2837
> 0x9569bb expand_gimple_stmt_1
>          /home/bmg/src/gcc/gcc/cfgexpand.c:3843
> 0x9569bb expand_gimple_stmt
>          /home/bmg/src/gcc/gcc/cfgexpand.c:4007
> 0x95c60f expand_gimple_basic_block
>          /home/bmg/src/gcc/gcc/cfgexpand.c:6044
> 
> Thanks,
> Florian
> 


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] improve warning suppression for inlined functions (PR 98465, 98512)
  2021-01-21 18:24   ` Martin Sebor
@ 2021-01-21 19:01     ` Florian Weimer
  2021-01-21 20:24       ` Martin Sebor
  0 siblings, 1 reply; 44+ messages in thread
From: Florian Weimer @ 2021-01-21 19:01 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Martin Sebor via Gcc-patches

* Martin Sebor:

> On 1/21/21 10:34 AM, Florian Weimer wrote:
>> * Martin Sebor via Gcc-patches:
>> 
>>> This patch depends on the fix for PR 98664 (already approved but
>>> not yet checked in).  I've tested it on x86_64-linux.
>>>
>>> To avoid fallout I tried to keep the changes to a minimum, and
>>> so the design isn't as robust as I'd like it ultimately to be.
>>> I plan to enhance it in stage 1.
>> I've tested this patch on top of 43705f3fa343e08b2fb030460f (so with
>> the
>> PR98664 fix, I think), and the reproducer from PR98512 now ICEs:
>
> Thanks for giving it a try!  I saw a similar ICE during my testing
> -- it's caused by a couple of uninitialized variables.  I fixed
> it in my tree (see below) but the fix didn't make it into the patch.
>
> Please give this a try and let me know if it doesn't help:
>
> index abcd991b829..d82a7eb67e5 100644
> --- a/gcc/diagnostic.c
> +++ b/gcc/diagnostic.c
> @@ -1426,7 +1426,7 @@ diagnostic_impl (rich_location *richloc, const
> diagnostic_metadata *metadata,
>                  int opt, const char *gmsgid,
>                  va_list *ap, diagnostic_t kind)
>  {
> -  diagnostic_info diagnostic;
> +  diagnostic_info diagnostic{ };
>    if (kind == DK_PERMERROR)
>      {
>        diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
> @@ -1452,7 +1452,7 @@ diagnostic_n_impl (rich_location *richloc, const
> diagnostic_metadata *metadata,
>                    const char *plural_gmsgid,
>                    va_list *ap, diagnostic_t kind)
>  {
> -  diagnostic_info diagnostic;
> +  diagnostic_info diagnostic{ };
>    unsigned long gtn;
>
>    if (sizeof n <= sizeof gtn)

This fixes the crash for me, and the warnings is gone as well.

Thanks,
Florian
-- 
Red Hat GmbH, https://de.redhat.com/ , Registered seat: Grasbrunn,
Commercial register: Amtsgericht Muenchen, HRB 153243,
Managing Directors: Charles Cachera, Brian Klemm, Laurie Krebs, Michael O'Neill


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] improve warning suppression for inlined functions (PR 98465, 98512)
  2021-01-21 19:01     ` Florian Weimer
@ 2021-01-21 20:24       ` Martin Sebor
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Sebor @ 2021-01-21 20:24 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Martin Sebor via Gcc-patches

On 1/21/21 12:01 PM, Florian Weimer wrote:
> * Martin Sebor:
> 
>> On 1/21/21 10:34 AM, Florian Weimer wrote:
>>> * Martin Sebor via Gcc-patches:
>>>
>>>> This patch depends on the fix for PR 98664 (already approved but
>>>> not yet checked in).  I've tested it on x86_64-linux.
>>>>
>>>> To avoid fallout I tried to keep the changes to a minimum, and
>>>> so the design isn't as robust as I'd like it ultimately to be.
>>>> I plan to enhance it in stage 1.
>>> I've tested this patch on top of 43705f3fa343e08b2fb030460f (so with
>>> the
>>> PR98664 fix, I think), and the reproducer from PR98512 now ICEs:
>>
>> Thanks for giving it a try!  I saw a similar ICE during my testing
>> -- it's caused by a couple of uninitialized variables.  I fixed
>> it in my tree (see below) but the fix didn't make it into the patch.
>>
>> Please give this a try and let me know if it doesn't help:
>>
>> index abcd991b829..d82a7eb67e5 100644
>> --- a/gcc/diagnostic.c
>> +++ b/gcc/diagnostic.c
>> @@ -1426,7 +1426,7 @@ diagnostic_impl (rich_location *richloc, const
>> diagnostic_metadata *metadata,
>>                   int opt, const char *gmsgid,
>>                   va_list *ap, diagnostic_t kind)
>>   {
>> -  diagnostic_info diagnostic;
>> +  diagnostic_info diagnostic{ };
>>     if (kind == DK_PERMERROR)
>>       {
>>         diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
>> @@ -1452,7 +1452,7 @@ diagnostic_n_impl (rich_location *richloc, const
>> diagnostic_metadata *metadata,
>>                     const char *plural_gmsgid,
>>                     va_list *ap, diagnostic_t kind)
>>   {
>> -  diagnostic_info diagnostic;
>> +  diagnostic_info diagnostic{ };
>>     unsigned long gtn;
>>
>>     if (sizeof n <= sizeof gtn)
> 
> This fixes the crash for me, and the warnings is gone as well.

Great, thanks for the confirmation!  I'll post the updated patch
shortly.

Martin

> 
> Thanks,
> Florian
> 


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] improve warning suppression for inlined functions (PR 98465, 98512)
  2021-01-19 18:58 [PATCH] improve warning suppression for inlined functions (PR 98465, 98512) Martin Sebor
  2021-01-21 17:34 ` Florian Weimer
@ 2021-01-21 23:46 ` Martin Sebor
  2021-01-30  2:56   ` PING " Martin Sebor
  2021-05-19 13:41   ` David Malcolm
  2021-02-19  4:28 ` [PATCH] improve warning suppression for inlined functions (PR 98465, 98512) Jeff Law
  2 siblings, 2 replies; 44+ messages in thread
From: Martin Sebor @ 2021-01-21 23:46 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2505 bytes --]

The initial patch I posted is missing initialization for a couple
of locals.  I'd noticed it in testing but forgot to add the fix to
the patch before posting it.  I have corrected that in the updated
revision and also added the test case from pr98512, and retested
the whole thing on x86_64-linux.

On 1/19/21 11:58 AM, Martin Sebor wrote:
> std::string tends to trigger a class of false positive out of bounds
> access warnings for code GCC cannot prove is unreachable because of
> missing aliasing constrains, and that ends up expanded inline into
> user code.  Simply inserting the contents of a constant char array
> does that.  In GCC 10 these false positives are suppressed due to
> -Wno-system-headers, but in GCC 11, to help detect calls rendered
> invalid by user code passing in either incorrect or insufficiently
> constrained arguments, -Wno-system-header no longer has this effect
> on invalid access warnings.
> 
> To solve the problem without at least partially reverting the change
> and going back to the GCC 10 way of things for the affected subset
> of calls (just memcpy and memmove), the attached patch enhances
> the #pragma GCC diagnostic machinery to consider not just a single
> location for inlined code but all locations at which an expression
> and its callers are inlined all the way up the stack.  This gives
> each author of a function involved in inlining the ability to
> control a warning issued for the code, not just the user into whose
> code all the calls end up inlined.  To resolve PR 98465, it lets us
> suppress the false positives selectively in std::string rather
> than across the board in GCC.
> 
> The solution is to provide a new pair of overloads for warning
> functions that, instead of taking a single location argument, take
> a tree node from which the location(s) are determined.  The tree
> argument is indirect because the diagnostic machinery doesn't (and
> cannot without more intrusive changes) at the moment depend on
> the various tree definitions.  A nice feature of these overloads
> is that they do away with the need for the %K directive (and in
> the future also %G, with another enhancement to accept a gimple*
> argument).
> 
> This patch depends on the fix for PR 98664 (already approved but
> not yet checked in).  I've tested it on x86_64-linux.
> 
> To avoid fallout I tried to keep the changes to a minimum, and
> so the design isn't as robust as I'd like it ultimately to be.
> I plan to enhance it in stage 1.
> 
> Martin


[-- Attachment #2: gcc-98465.diff --]
[-- Type: text/x-patch, Size: 54918 bytes --]

PR middle-end/98465 - Bogus -Wstringop-overread in std::string
PR middle-end/98512 - “#pragma GCC diagnostic ignored” ineffective in conjunction with alias attribute

gcc/ChangeLog:

	PR middle-end/98465
	PR middle-end/98512
	* builtins.c (class diag_inlining_context): New class.
	(maybe_warn_for_bound): Adjust signature.  Use diag_inlining_context.
	(warn_for_access): Same.
	(check_access): Remove calls to tree_inlined_location.
	(expand_builtin_strncmp): Remove argument from calls to
	maybe_warn_for_bound.
	(warn_dealloc_offset): Adjust signature.  Use diag_inlining_context.
	(maybe_emit_free_warning): Remove calls to tree_inlined_location.
	* diagnostic-core.h (warning, warning_n): New overloads.
	* diagnostic-metadata.h (class diagnostic_metadata::location_context):
	New.
	(struct diagnostic_info): Declare.
	* diagnostic.c (location_context::locations): Define.
	(update_effective_level_from_pragmas): Use location_context to test
	inlinined locations.
	(diagnostic_report_diagnostic): Set location context.
	(warning, warning_n): Define new overloads.
	* diagnostic.h (diagnostic_inhibit_notes):

gcc/cp/ChangeLog:

	* mapper-client.cc: Include headers needed by others.

libstdc++-v3/ChangeLog:

	PR middle-end/98465
	* include/bits/basic_string.tcc (_M_replace): Suppress false positive
	warnings.
	* testsuite/18_support/new_delete_placement.cc: Suppress valid warnings.
	* testsuite/20_util/monotonic_buffer_resource/allocate.cc: Same.
	* testsuite/20_util/unsynchronized_pool_resource/allocate.cc: Same.

gcc/testsuite/ChangeLog:

	PR middle-end/98512	
	* gcc.dg/pragma-diag-9.c: New test.
	* gcc.dg/pragma-diag-10.c: New test.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 0aed008687c..39fe1d0a6e0 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -39,7 +39,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "optabs.h"
 #include "emit-rtl.h"
 #include "recog.h"
-#include "diagnostic-core.h"
+#include "diagnostic.h"
 #include "alias.h"
 #include "fold-const.h"
 #include "fold-const-call.h"
@@ -79,6 +79,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-outof-ssa.h"
 #include "attr-fnspec.h"
 #include "demangle.h"
+#include "tree-pretty-print.h"
 
 struct target_builtins default_target_builtins;
 #if SWITCHABLE_TARGET
@@ -749,6 +750,93 @@ is_builtin_name (const char *name)
   return false;
 }
 
+/* Class to override the base location context for an expression EXPR.  */
+
+class diag_inlining_context: public diagnostic_metadata::location_context
+{
+ public:
+  diag_inlining_context (tree expr): m_expr (expr), m_ao (), m_loc () { }
+
+  virtual void locations (vec<location_t> &locs, diagnostic_info *di)
+  {
+    set_locations (&locs, di);
+  }
+
+  virtual void set_location (diagnostic_info *);
+
+ private:
+  void set_locations (vec<location_t> *, diagnostic_info *);
+
+  /* The expression for which a diagnostic is being issued.  */
+  tree m_expr;
+  /* The "abstract origin" of the diagnosed expression, or the BLOCK
+     into which the function containing the expression is inlined.  */
+  tree m_ao;
+  /* The expression location.  */
+  location_t m_loc;
+};
+
+/* Lazily initialize the expression abstract origin and location.  */
+
+/* virtual */ void
+diag_inlining_context::set_location (diagnostic_info *di)
+{
+  if (m_ao
+      && pp_ti_abstract_origin (&di->message)
+      && m_loc != UNKNOWN_LOCATION)
+    {
+      *pp_ti_abstract_origin (&di->message) = m_ao;
+      di->message.set_location (0, m_loc, SHOW_RANGE_WITH_CARET);
+    }
+  else
+    set_locations (NULL, di);
+}
+
+/* If LOC is nonnull, fill *LOCS with the locations M_EXPR has been inlined
+   into and if DI is nonnull, set *DI's message abstract origin and location.
+   Set M_MO.  */
+
+/* virtual */ void
+diag_inlining_context::set_locations (vec<location_t> *locs,
+				      diagnostic_info *di)
+{
+  tree block = TREE_BLOCK (m_expr);
+
+  while (block && TREE_CODE (block) == BLOCK
+	 && BLOCK_ABSTRACT_ORIGIN (block))
+    {
+      tree ao = BLOCK_ABSTRACT_ORIGIN (block);
+      if (TREE_CODE (ao) == FUNCTION_DECL)
+	{
+	  if (!m_ao)
+	    m_ao = block;
+
+	  if (!locs)
+
+	    break;
+	  locs->safe_push (BLOCK_SOURCE_LOCATION (block));
+	}
+      else if (TREE_CODE (ao) != BLOCK)
+	break;
+
+      block = BLOCK_SUPERCONTEXT (block);
+    }
+
+  m_loc = EXPR_LOCATION (m_expr);
+  /* Only consider macro expansion when the block traversal failed
+     to find a location.  Otherwise it's not relevant.  */
+  m_loc = expansion_point_location_if_in_system_header (m_loc);
+  if (locs)
+    locs->safe_push (m_loc);
+
+  if (di)
+    {
+      if (pp_ti_abstract_origin (&di->message))
+	*pp_ti_abstract_origin (&di->message) = m_ao;
+      di->message.set_location (0, m_loc, SHOW_RANGE_WITH_CARET);
+    }
+}
+
 /* Return true if NODE should be considered for inline expansion regardless
    of the optimization level.  This means whenever a function is invoked with
    its "internal" name, which normally contains the prefix "__builtin".  */
@@ -3931,7 +4019,7 @@ determine_block_size (tree len, rtx len_rtx,
    accessing an object with SIZE.  */
 
 static bool
-maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
+maybe_warn_for_bound (int opt, tree exp, tree func,
 		      tree bndrng[2], tree size, const access_data *pad = NULL)
 {
   if (!bndrng[0] || TREE_NO_WARNING (exp))
@@ -3939,6 +4027,8 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
 
   tree maxobjsize = max_object_size ();
 
+  diag_inlining_context dic (exp);
+
   bool warned = false;
 
   if (opt == OPT_Wstringop_overread)
@@ -3949,72 +4039,71 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
 	{
 	  if (bndrng[0] == bndrng[1])
 	    warned = (func
-		      ? warning_at (loc, opt,
-				    (maybe
-				     ? G_("%K%qD specified bound %E may "
-					  "exceed maximum object size %E")
-				     : G_("%K%qD specified bound %E "
-					  "exceeds maximum object size %E")),
-				    exp, func, bndrng[0], maxobjsize)
-		      : warning_at (loc, opt,
-				    (maybe
-				     ? G_("%Kspecified bound %E may "
-					  "exceed maximum object size %E")
-				     : G_("%Kspecified bound %E "
-					  "exceeds maximum object size %E")),
-				    exp, bndrng[0], maxobjsize));
+		      ? warning (dic, opt,
+				 (maybe
+				  ? G_("%qD specified bound %E may "
+				       "exceed maximum object size %E")
+				  : G_("%qD specified bound %E "
+				       "exceeds maximum object size %E")),
+				 func, bndrng[0], maxobjsize)
+		      : warning (dic, opt,
+				 (maybe
+				  ? G_("specified bound %E may "
+				       "exceed maximum object size %E")
+				  : G_("specified bound %E "
+				       "exceeds maximum object size %E")),
+				 bndrng[0], maxobjsize));
 	  else
 	    warned = (func
-		      ? warning_at (loc, opt,
-				    (maybe
-				     ? G_("%K%qD specified bound [%E, %E] may "
-					  "exceed maximum object size %E")
-				     : G_("%K%qD specified bound [%E, %E] "
-					  "exceeds maximum object size %E")),
-				    exp, func,
-				    bndrng[0], bndrng[1], maxobjsize)
-		      : warning_at (loc, opt,
-				    (maybe
-				     ? G_("%Kspecified bound [%E, %E] may "
-					  "exceed maximum object size %E")
-				     : G_("%Kspecified bound [%E, %E] "
-					  "exceeds maximum object size %E")),
-				    exp, bndrng[0], bndrng[1], maxobjsize));
+		      ? warning (dic, opt,
+				 (maybe
+				  ? G_("%qD specified bound [%E, %E] may "
+				       "exceed maximum object size %E")
+				  : G_("%qD specified bound [%E, %E] "
+				       "exceeds maximum object size %E")),
+				 func, bndrng[0], bndrng[1], maxobjsize)
+		      : warning (dic, opt,
+				 (maybe
+				  ? G_("specified bound [%E, %E] may "
+				       "exceed maximum object size %E")
+				  : G_("specified bound [%E, %E] "
+				       "exceeds maximum object size %E")),
+				 bndrng[0], bndrng[1], maxobjsize));
 	}
       else if (!size || tree_int_cst_le (bndrng[0], size))
 	return false;
       else if (tree_int_cst_equal (bndrng[0], bndrng[1]))
 	warned = (func
-		  ? warning_at (loc, opt,
-				(maybe
-				 ? G_("%K%qD specified bound %E may exceed "
-				      "source size %E")
-				 : G_("%K%qD specified bound %E exceeds "
-				      "source size %E")),
-				exp, func, bndrng[0], size)
-		  : warning_at (loc, opt,
-				(maybe
-				 ? G_("%Kspecified bound %E may exceed "
-				      "source size %E")
-				 : G_("%Kspecified bound %E exceeds "
-				      "source size %E")),
-				exp, bndrng[0], size));
+		  ? warning (dic, opt,
+			     (maybe
+			      ? G_("%qD specified bound %E may exceed "
+				   "source size %E")
+			      : G_("%qD specified bound %E exceeds "
+				   "source size %E")),
+			     func, bndrng[0], size)
+		  : warning (dic, opt,
+			     (maybe
+			      ? G_("specified bound %E may exceed "
+				   "source size %E")
+			      : G_("specified bound %E exceeds "
+				   "source size %E")),
+			     bndrng[0], size));
       else
 	warned = (func
-		  ? warning_at (loc, opt,
-				(maybe
-				 ? G_("%K%qD specified bound [%E, %E] may "
-				      "exceed source size %E")
-				 : G_("%K%qD specified bound [%E, %E] exceeds "
-				      "source size %E")),
-				exp, func, bndrng[0], bndrng[1], size)
-		  : warning_at (loc, opt,
-				(maybe
-				 ? G_("%Kspecified bound [%E, %E] may exceed "
-				      "source size %E")
-				 : G_("%Kspecified bound [%E, %E] exceeds "
-				      "source size %E")),
-				exp, bndrng[0], bndrng[1], size));
+		  ? warning (dic, opt,
+			     (maybe
+			      ? G_("%qD specified bound [%E, %E] may "
+				   "exceed source size %E")
+			      : G_("%qD specified bound [%E, %E] exceeds "
+				   "source size %E")),
+			     func, bndrng[0], bndrng[1], size)
+		  : warning (dic, opt,
+			     (maybe
+			      ? G_("specified bound [%E, %E] may exceed "
+				   "source size %E")
+			      : G_("specified bound [%E, %E] exceeds "
+				   "source size %E")),
+			     bndrng[0], bndrng[1], size));
       if (warned)
 	{
 	  if (pad && pad->src.ref)
@@ -4037,72 +4126,71 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
     {
       if (bndrng[0] == bndrng[1])
 	warned = (func
-		  ? warning_at (loc, opt,
-				(maybe
-				 ? G_("%K%qD specified size %E may "
-				      "exceed maximum object size %E")
-				 : G_("%K%qD specified size %E "
-				      "exceeds maximum object size %E")),
-				exp, func, bndrng[0], maxobjsize)
-		  : warning_at (loc, opt,
-				(maybe
-				 ? G_("%Kspecified size %E may exceed "
-				      "maximum object size %E")
-				 : G_("%Kspecified size %E exceeds "
-				      "maximum object size %E")),
-				exp, bndrng[0], maxobjsize));
+		  ? warning (dic, opt,
+			     (maybe
+			      ? G_("%qD specified size %E may "
+				   "exceed maximum object size %E")
+			      : G_("%qD specified size %E "
+				   "exceeds maximum object size %E")),
+			     func, bndrng[0], maxobjsize)
+		  : warning (dic, opt,
+			     (maybe
+			      ? G_("specified size %E may exceed "
+				   "maximum object size %E")
+			      : G_("specified size %E exceeds "
+				   "maximum object size %E")),
+			     bndrng[0], maxobjsize));
       else
 	warned = (func
-		  ? warning_at (loc, opt,
-				(maybe
-				 ? G_("%K%qD specified size between %E and %E "
-				      "may exceed maximum object size %E")
-				 : G_("%K%qD specified size between %E and %E "
-				      "exceeds maximum object size %E")),
-				exp, func,
-				bndrng[0], bndrng[1], maxobjsize)
-		  : warning_at (loc, opt,
-				(maybe
-				 ? G_("%Kspecified size between %E and %E "
-				      "may exceed maximum object size %E")
-				 : G_("%Kspecified size between %E and %E "
-				      "exceeds maximum object size %E")),
-				exp, bndrng[0], bndrng[1], maxobjsize));
+		  ? warning (dic, opt,
+			     (maybe
+			      ? G_("%qD specified size between %E and %E "
+				   "may exceed maximum object size %E")
+			      : G_("%qD specified size between %E and %E "
+				   "exceeds maximum object size %E")),
+			     func, bndrng[0], bndrng[1], maxobjsize)
+		  : warning (dic, opt,
+			     (maybe
+			      ? G_("specified size between %E and %E "
+				   "may exceed maximum object size %E")
+			      : G_("specified size between %E and %E "
+				   "exceeds maximum object size %E")),
+			     bndrng[0], bndrng[1], maxobjsize));
     }
   else if (!size || tree_int_cst_le (bndrng[0], size))
     return false;
   else if (tree_int_cst_equal (bndrng[0], bndrng[1]))
     warned = (func
-	      ? warning_at (loc, OPT_Wstringop_overflow_,
-			    (maybe
-			     ? G_("%K%qD specified bound %E may exceed "
-				  "destination size %E")
-			     : G_("%K%qD specified bound %E exceeds "
-				  "destination size %E")),
-			    exp, func, bndrng[0], size)
-	      : warning_at (loc, OPT_Wstringop_overflow_,
-			    (maybe
-			     ? G_("%Kspecified bound %E may exceed "
-				  "destination size %E")
-			     : G_("%Kspecified bound %E exceeds "
-				  "destination size %E")),
-			    exp, bndrng[0], size));
+	      ? warning (dic, OPT_Wstringop_overflow_,
+			 (maybe
+			  ? G_("%qD specified bound %E may exceed "
+			       "destination size %E")
+			  : G_("%qD specified bound %E exceeds "
+			       "destination size %E")),
+			 func, bndrng[0], size)
+	      : warning (dic, OPT_Wstringop_overflow_,
+			 (maybe
+			  ? G_("specified bound %E may exceed "
+			       "destination size %E")
+			  : G_("specified bound %E exceeds "
+			       "destination size %E")),
+			 bndrng[0], size));
   else
     warned = (func
-	      ? warning_at (loc, OPT_Wstringop_overflow_,
-			    (maybe
-			     ? G_("%K%qD specified bound [%E, %E] may exceed "
-				  "destination size %E")
-			     : G_("%K%qD specified bound [%E, %E] exceeds "
-				  "destination size %E")),
-			    exp, func, bndrng[0], bndrng[1], size)
-	      : warning_at (loc, OPT_Wstringop_overflow_,
-			    (maybe
-			     ? G_("%Kspecified bound [%E, %E] exceeds "
-				  "destination size %E")
-			     : G_("%Kspecified bound [%E, %E] exceeds "
-				  "destination size %E")),
-			    exp, bndrng[0], bndrng[1], size));
+	      ? warning (dic, OPT_Wstringop_overflow_,
+			 (maybe
+			  ? G_("%qD specified bound [%E, %E] may exceed "
+			       "destination size %E")
+			  : G_("%qD specified bound [%E, %E] exceeds "
+			       "destination size %E")),
+			 func, bndrng[0], bndrng[1], size)
+	      : warning (dic, OPT_Wstringop_overflow_,
+			 (maybe
+			  ? G_("specified bound [%E, %E] exceeds "
+			       "destination size %E")
+			  : G_("specified bound [%E, %E] exceeds "
+			       "destination size %E")),
+			 bndrng[0], bndrng[1], size));
 
   if (warned)
     {
@@ -4129,76 +4217,76 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
    Returns true when a warning has been issued.  */
 
 static bool
-warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
+warn_for_access (tree func, tree exp, int opt, tree range[2],
 		 tree size, bool write, bool read, bool maybe)
 {
+  diag_inlining_context dic (exp);
+
   bool warned = false;
 
   if (write && read)
     {
       if (tree_int_cst_equal (range[0], range[1]))
 	warned = (func
-		  ? warning_n (loc, opt, tree_to_uhwi (range[0]),
+		  ? warning_n (dic, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%K%qD may access %E byte in a region "
+				? G_("%qD may access %E byte in a region "
 				     "of size %E")
-				: G_("%K%qD accessing %E byte in a region "
+				: G_("%qD accessing %E byte in a region "
 				     "of size %E")),
-				(maybe
-				 ? G_ ("%K%qD may access %E bytes in a region "
-				       "of size %E")
-				 : G_ ("%K%qD accessing %E bytes in a region "
-				       "of size %E")),
-			       exp, func, range[0], size)
-		  : warning_n (loc, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%Kmay access %E byte in a region "
+				? G_ ("%qD may access %E bytes in a region "
+				      "of size %E")
+				: G_ ("%qD accessing %E bytes in a region "
+				      "of size %E")),
+			       func, range[0], size)
+		  : warning_n (dic, opt, tree_to_uhwi (range[0]),
+			       (maybe
+				? G_("may access %E byte in a region "
 				     "of size %E")
-				: G_("%Kaccessing %E byte in a region "
+				: G_("accessing %E byte in a region "
 				     "of size %E")),
 			       (maybe
-				? G_("%Kmay access %E bytes in a region "
+				? G_("may access %E bytes in a region "
 				     "of size %E")
-				: G_("%Kaccessing %E bytes in a region "
+				: G_("accessing %E bytes in a region "
 				     "of size %E")),
-			       exp, range[0], size));
+			       range[0], size));
       else if (tree_int_cst_sign_bit (range[1]))
 	{
 	  /* Avoid printing the upper bound if it's invalid.  */
 	  warned = (func
-		    ? warning_at (loc, opt,
-				  (maybe
-				   ? G_("%K%qD may access %E or more bytes "
-					"in a region of size %E")
-				   : G_("%K%qD accessing %E or more bytes "
-					"in a region of size %E")),
-				  exp, func, range[0], size)
-		    : warning_at (loc, opt,
-				  (maybe
-				   ? G_("%Kmay access %E or more bytes "
-					"in a region of size %E")
-				   : G_("%Kaccessing %E or more bytes "
-					"in a region of size %E")),
-				  exp, range[0], size));
+		    ? warning (dic, opt,
+			       (maybe
+				? G_("%qD may access %E or more bytes "
+				     "in a region of size %E")
+				: G_("%qD accessing %E or more bytes "
+				     "in a region of size %E")),
+			       func, range[0], size)
+		    : warning (dic, opt,
+			       (maybe
+				? G_("may access %E or more bytes "
+				     "in a region of size %E")
+				: G_("accessing %E or more bytes "
+				     "in a region of size %E")),
+			       range[0], size));
 	}
       else
 	warned = (func
-		  ? warning_at (loc, opt,
-				(maybe
-				 ? G_("%K%qD may access between %E and %E "
-				      "bytes in a region of size %E")
-				 : G_("%K%qD accessing between %E and %E "
-				      "bytes in a region of size %E")),
-				exp, func, range[0], range[1],
-				size)
-		  : warning_at (loc, opt,
-				(maybe
-				 ? G_("%Kmay access between %E and %E bytes "
-				      "in a region of size %E")
-				 : G_("%Kaccessing between %E and %E bytes "
-				      "in a region of size %E")),
-				exp, range[0], range[1],
-				size));
+		  ? warning (dic, opt,
+			     (maybe
+			      ? G_("%qD may access between %E and %E "
+				   "bytes in a region of size %E")
+			      : G_("%qD accessing between %E and %E "
+				   "bytes in a region of size %E")),
+			     func, range[0], range[1], size)
+		  : warning (dic, opt,
+			     (maybe
+			      ? G_("may access between %E and %E bytes "
+				   "in a region of size %E")
+			      : G_("accessing between %E and %E bytes "
+				   "in a region of size %E")),
+			     range[0], range[1], size));
       return warned;
     }
 
@@ -4206,72 +4294,70 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
     {
       if (tree_int_cst_equal (range[0], range[1]))
 	warned = (func
-		  ? warning_n (loc, opt, tree_to_uhwi (range[0]),
+		  ? warning_n (dic, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%K%qD may write %E byte into a region "
+				? G_("%qD may write %E byte into a region "
 				     "of size %E")
-				: G_("%K%qD writing %E byte into a region "
+				: G_("%qD writing %E byte into a region "
 				     "of size %E overflows the destination")),
 			       (maybe
-				? G_("%K%qD may write %E bytes into a region "
+				? G_("%qD may write %E bytes into a region "
 				     "of size %E")
-				: G_("%K%qD writing %E bytes into a region "
+				: G_("%qD writing %E bytes into a region "
 				     "of size %E overflows the destination")),
-			       exp, func, range[0], size)
-		  : warning_n (loc, opt, tree_to_uhwi (range[0]),
+			       func, range[0], size)
+		  : warning_n (dic, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%Kmay write %E byte into a region "
+				? G_("may write %E byte into a region "
 				     "of size %E")
-				: G_("%Kwriting %E byte into a region "
+				: G_("writing %E byte into a region "
 				     "of size %E overflows the destination")),
 			       (maybe
-				? G_("%Kmay write %E bytes into a region "
+				? G_("may write %E bytes into a region "
 				     "of size %E")
-				: G_("%Kwriting %E bytes into a region "
+				: G_("writing %E bytes into a region "
 				     "of size %E overflows the destination")),
-			       exp, range[0], size));
+			       range[0], size));
       else if (tree_int_cst_sign_bit (range[1]))
 	{
 	  /* Avoid printing the upper bound if it's invalid.  */
 	  warned = (func
-		    ? warning_at (loc, opt,
-				  (maybe
-				   ? G_("%K%qD may write %E or more bytes "
-					"into a region of size %E "
-					"the destination")
-				   : G_("%K%qD writing %E or more bytes "
-					"into a region of size %E overflows "
-					"the destination")),
-				  exp, func, range[0], size)
-		    : warning_at (loc, opt,
-				  (maybe
-				   ? G_("%Kmay write %E or more bytes into "
-					"a region of size %E")
-				   : G_("%Kwriting %E or more bytes into "
-					"a region of size %E overflows "
-					"the destination")),
-				  exp, range[0], size));
+		    ? warning (dic, opt,
+			       (maybe
+				? G_("%qD may write %E or more bytes "
+				     "into a region of size %E "
+				     "the destination")
+				: G_("%qD writing %E or more bytes "
+				     "into a region of size %E overflows "
+				     "the destination")),
+			       func, range[0], size)
+		    : warning (dic, opt,
+			       (maybe
+				? G_("may write %E or more bytes into "
+				     "a region of size %E")
+				: G_("writing %E or more bytes into "
+				     "a region of size %E overflows "
+				     "the destination")),
+			       range[0], size));
 	}
       else
 	warned = (func
-		  ? warning_at (loc, opt,
-				(maybe
-				 ? G_("%K%qD may write between %E and %E bytes "
-				      "into a region of size %E")
-				 : G_("%K%qD writing between %E and %E bytes "
-				      "into a region of size %E overflows "
-				      "the destination")),
-				exp, func, range[0], range[1],
-				size)
-		  : warning_at (loc, opt,
-				(maybe
-				 ? G_("%Kmay write between %E and %E bytes "
-				      "into a region of size %E")
-				 : G_("%Kwriting between %E and %E bytes "
-				      "into a region of size %E overflows "
-				      "the destination")),
-				exp, range[0], range[1],
-				size));
+		  ? warning (dic, opt,
+			     (maybe
+			      ? G_("%qD may write between %E and %E bytes "
+				   "into a region of size %E")
+			      : G_("%qD writing between %E and %E bytes "
+				   "into a region of size %E overflows "
+				   "the destination")),
+			     func, range[0], range[1], size)
+		  : warning (dic, opt,
+			     (maybe
+			      ? G_("may write between %E and %E bytes "
+				   "into a region of size %E")
+			      : G_("writing between %E and %E bytes "
+				   "into a region of size %E overflows "
+				   "the destination")),
+			     range[0], range[1], size));
       return warned;
     }
 
@@ -4279,67 +4365,67 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
     {
       if (tree_int_cst_equal (range[0], range[1]))
 	warned = (func
-		  ? warning_n (loc, OPT_Wstringop_overread,
+		  ? warning_n (dic, OPT_Wstringop_overread,
 			       tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%K%qD may reade %E byte from a region "
+				? G_("%qD may reade %E byte from a region "
 				     "of size %E")
-				: G_("%K%qD reading %E byte from a region "
+				: G_("%qD reading %E byte from a region "
 				     "of size %E")),
 			       (maybe
-				? G_("%K%qD may read %E bytes from a region "
+				? G_("%qD may read %E bytes from a region "
 				     "of size %E")
-				: G_("%K%qD reading %E bytes from a region "
+				: G_("%qD reading %E bytes from a region "
 				     "of size %E")),
-			       exp, func, range[0], size)
-		  : warning_n (loc, OPT_Wstringop_overread,
+			       func, range[0], size)
+		  : warning_n (dic, OPT_Wstringop_overread,
 			       tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%Kmay read %E byte from a region "
+				? G_("may read %E byte from a region "
 				     "of size %E")
-				: G_("%Kreading %E byte from a region "
+				: G_("reading %E byte from a region "
 				     "of size %E")),
 			       (maybe
-				? G_("%Kmay read %E bytes from a region "
+				? G_("may read %E bytes from a region "
 				     "of size %E")
-				: G_("%Kreading %E bytes from a region "
+				: G_("reading %E bytes from a region "
 				     "of size %E")),
-			       exp, range[0], size));
+			       range[0], size));
       else if (tree_int_cst_sign_bit (range[1]))
 	{
 	  /* Avoid printing the upper bound if it's invalid.  */
 	  warned = (func
-		    ? warning_at (loc, OPT_Wstringop_overread,
-				  (maybe
-				   ? G_("%K%qD may read %E or more bytes "
-					"from a region of size %E")
-				   : G_("%K%qD reading %E or more bytes "
-					"from a region of size %E")),
-				  exp, func, range[0], size)
-		    : warning_at (loc, OPT_Wstringop_overread,
-				  (maybe
-				   ? G_("%Kmay read %E or more bytes "
-					"from a region of size %E")
-				   : G_("%Kreading %E or more bytes "
-					"from a region of size %E")),
-				  exp, range[0], size));
+		    ? warning (dic, OPT_Wstringop_overread,
+			       (maybe
+				? G_("%qD may read %E or more bytes "
+				     "from a region of size %E")
+				: G_("%qD reading %E or more bytes "
+				     "from a region of size %E")),
+			       func, range[0], size)
+		    : warning (dic, OPT_Wstringop_overread,
+			       (maybe
+				? G_("may read %E or more bytes "
+				     "from a region of size %E")
+				: G_("reading %E or more bytes "
+				     "from a region of size %E")),
+			       range[0], size));
 	}
       else
 	warned = (func
-		  ? warning_at (loc, OPT_Wstringop_overread,
-				(maybe
-				 ? G_("%K%qD may read between %E and %E bytes "
-				      "from a region of size %E")
-				 : G_("%K%qD reading between %E and %E bytes "
-				      "from a region of size %E")),
-				exp, func, range[0], range[1], size)
-		  : warning_at (loc, opt,
-				(maybe
-				 ? G_("%Kmay read between %E and %E bytes "
-				      "from a region of size %E")
-				 : G_("%Kreading between %E and %E bytes "
-				      "from a region of size %E")),
-				exp, range[0], range[1], size));
+		  ? warning (dic, OPT_Wstringop_overread,
+			     (maybe
+			      ? G_("%qD may read between %E and %E bytes "
+				   "from a region of size %E")
+			      : G_("%qD reading between %E and %E bytes "
+				   "from a region of size %E")),
+			     func, range[0], range[1], size)
+		  : warning (dic, opt,
+			     (maybe
+			      ? G_("may read between %E and %E bytes "
+				   "from a region of size %E")
+			      : G_("reading between %E and %E bytes "
+				   "from a region of size %E")),
+			     range[0], range[1], size));
 
       if (warned)
 	TREE_NO_WARNING (exp) = true;
@@ -4350,39 +4436,39 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
   if (tree_int_cst_equal (range[0], range[1])
       || tree_int_cst_sign_bit (range[1]))
     warned = (func
-	      ? warning_n (loc, OPT_Wstringop_overread,
+	      ? warning_n (dic, OPT_Wstringop_overread,
 			   tree_to_uhwi (range[0]),
-			   "%K%qD epecting %E byte in a region of size %E",
-			   "%K%qD expecting %E bytes in a region of size %E",
-			   exp, func, range[0], size)
-	      : warning_n (loc, OPT_Wstringop_overread,
+			   "%qD epecting %E byte in a region of size %E",
+			   "%qD expecting %E bytes in a region of size %E",
+			   func, range[0], size)
+	      : warning_n (dic, OPT_Wstringop_overread,
 			   tree_to_uhwi (range[0]),
-			   "%Kexpecting %E byte in a region of size %E",
-			   "%Kexpecting %E bytes in a region of size %E",
-			   exp, range[0], size));
+			   "expecting %E byte in a region of size %E",
+			   "expecting %E bytes in a region of size %E",
+			   range[0], size));
   else if (tree_int_cst_sign_bit (range[1]))
     {
       /* Avoid printing the upper bound if it's invalid.  */
       warned = (func
-		? warning_at (loc, OPT_Wstringop_overread,
-			      "%K%qD expecting %E or more bytes in a region "
-			      "of size %E",
-			      exp, func, range[0], size)
-		: warning_at (loc, OPT_Wstringop_overread,
-			      "%Kexpecting %E or more bytes in a region "
-			      "of size %E",
-			      exp, range[0], size));
+		? warning (dic, OPT_Wstringop_overread,
+			   "%qD expecting %E or more bytes in a region "
+			   "of size %E",
+			   func, range[0], size)
+		: warning (dic, OPT_Wstringop_overread,
+			   "expecting %E or more bytes in a region "
+			   "of size %E",
+			   range[0], size));
     }
   else
     warned = (func
-	      ? warning_at (loc, OPT_Wstringop_overread,
-			    "%K%qD expecting between %E and %E bytes in "
-			    "a region of size %E",
-			    exp, func, range[0], range[1], size)
-	      : warning_at (loc, OPT_Wstringop_overread,
-			    "%Kexpectting between %E and %E bytes in "
-			    "a region of size %E",
-			    exp, range[0], range[1], size));
+	      ? warning (dic, OPT_Wstringop_overread,
+			 "%qD expecting between %E and %E bytes in "
+			 "a region of size %E",
+			 func, range[0], range[1], size)
+	      : warning (dic, OPT_Wstringop_overread,
+			 "expectting between %E and %E bytes in "
+			 "a region of size %E",
+			 range[0], range[1], size));
 
   if (warned)
     TREE_NO_WARNING (exp) = true;
@@ -4575,9 +4661,11 @@ access_ref::inform_access (access_mode mode) const
     inform (loc,
 	    "at offset %s into source object of size %s allocated by %qE",
 	    offstr, sizestr, allocfn);
-  else
+  else if (allocfn)
     inform (loc, "source object of size %s allocated by %qE",
 	    sizestr, allocfn);
+  else
+    inform (loc, "source object of size %s allocated here", sizestr);
 }
 
 /* Helper to set RANGE to the range of BOUND if it's nonnull, bounded
@@ -4742,8 +4830,7 @@ check_access (tree exp, tree dstwrite,
       && TREE_CODE (range[0]) == INTEGER_CST
       && tree_int_cst_lt (maxobjsize, range[0]))
     {
-      location_t loc = tree_inlined_location (exp);
-      maybe_warn_for_bound (OPT_Wstringop_overflow_, loc, exp, func, range,
+      maybe_warn_for_bound (OPT_Wstringop_overflow_, exp, func, range,
 			    NULL_TREE, pad);
       return false;
     }
@@ -4768,24 +4855,24 @@ check_access (tree exp, tree dstwrite,
 	      || (pad && pad->dst.ref && TREE_NO_WARNING (pad->dst.ref)))
 	    return false;
 
-	  location_t loc = tree_inlined_location (exp);
 	  bool warned = false;
 	  if (dstwrite == slen && at_least_one)
 	    {
+	      diag_inlining_context dic (exp);
 	      /* This is a call to strcpy with a destination of 0 size
 		 and a source of unknown length.  The call will write
 		 at least one byte past the end of the destination.  */
 	      warned = (func
-			? warning_at (loc, OPT_Wstringop_overflow_,
-				      "%K%qD writing %E or more bytes into "
-				      "a region of size %E overflows "
-				      "the destination",
-				      exp, func, range[0], dstsize)
-			: warning_at (loc, OPT_Wstringop_overflow_,
-				      "%Kwriting %E or more bytes into "
-				      "a region of size %E overflows "
-				      "the destination",
-				      exp, range[0], dstsize));
+			? warning (dic, OPT_Wstringop_overflow_,
+				   "%qD writing %E or more bytes into "
+				   "a region of size %E overflows "
+				   "the destination",
+				   func, range[0], dstsize)
+			: warning (dic, OPT_Wstringop_overflow_,
+				   "writing %E or more bytes into "
+				   "a region of size %E overflows "
+				   "the destination",
+				   range[0], dstsize));
 	    }
 	  else
 	    {
@@ -4794,8 +4881,7 @@ check_access (tree exp, tree dstwrite,
 	      const bool write
 		= mode == access_write_only || mode == access_read_write;
 	      const bool maybe = pad && pad->dst.parmarray;
-	      warned = warn_for_access (loc, func, exp,
-					OPT_Wstringop_overflow_,
+	      warned = warn_for_access (func, exp, OPT_Wstringop_overflow_,
 					range, dstsize,
 					write, read && !builtin, maybe);
 	    }
@@ -4821,7 +4907,6 @@ check_access (tree exp, tree dstwrite,
 	 PAD is nonnull and BNDRNG is valid.  */
       get_size_range (maxread, range, pad ? pad->src.bndrng : NULL);
 
-      location_t loc = tree_inlined_location (exp);
       tree size = dstsize;
       if (pad && pad->mode == access_read_only)
 	size = wide_int_to_tree (sizetype, pad->src.sizrng[1]);
@@ -4830,7 +4915,7 @@ check_access (tree exp, tree dstwrite,
 	{
 	  if (tree_int_cst_lt (maxobjsize, range[0]))
 	    {
-	      maybe_warn_for_bound (OPT_Wstringop_overread, loc, exp, func,
+	      maybe_warn_for_bound (OPT_Wstringop_overread, exp, func,
 				    range, size, pad);
 	      return false;
 	    }
@@ -4840,7 +4925,7 @@ check_access (tree exp, tree dstwrite,
 	      int opt = (dstwrite || mode != access_read_only
 			 ? OPT_Wstringop_overflow_
 			 : OPT_Wstringop_overread);
-	      maybe_warn_for_bound (opt, loc, exp, func, range, size, pad);
+	      maybe_warn_for_bound (opt, exp, func, range, size, pad);
 	      return false;
 	    }
 	}
@@ -4880,11 +4965,10 @@ check_access (tree exp, tree dstwrite,
 	  || (pad && pad->src.ref && TREE_NO_WARNING (pad->src.ref)))
 	return false;
 
-      location_t loc = tree_inlined_location (exp);
       const bool read
 	= mode == access_read_only || mode == access_read_write;
       const bool maybe = pad && pad->dst.parmarray;
-      if (warn_for_access (loc, func, exp, OPT_Wstringop_overread, range,
+      if (warn_for_access (func, exp, OPT_Wstringop_overread, range,
 			   slen, false, read, maybe))
 	{
 	  TREE_NO_WARNING (exp) = true;
@@ -7070,13 +7154,13 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
 	      offset_int rem1 = ref1.size_remaining ();
 	      offset_int rem2 = ref2.size_remaining ();
 	      if (rem1 == 0 || rem2 == 0)
-		maybe_warn_for_bound (OPT_Wstringop_overread, loc, exp, func,
+		maybe_warn_for_bound (OPT_Wstringop_overread, exp, func,
 				      bndrng, integer_zero_node);
 	      else
 		{
 		  offset_int maxrem = wi::max (rem1, rem2, UNSIGNED);
 		  if (maxrem < wi::to_offset (bndrng[0]))
-		    maybe_warn_for_bound (OPT_Wstringop_overread, loc, exp,
+		    maybe_warn_for_bound (OPT_Wstringop_overread, exp,
 					  func, bndrng,
 					  wide_int_to_tree (sizetype, maxrem));
 		}
@@ -7085,7 +7169,7 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
 		   && !integer_zerop (bndrng[0])
 		   && ((size1 && integer_zerop (size1))
 		       || (size2 && integer_zerop (size2))))
-	    maybe_warn_for_bound (OPT_Wstringop_overread, loc, exp, func,
+	    maybe_warn_for_bound (OPT_Wstringop_overread, exp, func,
 				  bndrng, integer_zero_node);
 	}
     }
@@ -13439,7 +13523,7 @@ matching_alloc_calls_p (gimple *alloc, tree dealloc_decl)
    the target pointer is unknown.  */
 
 static bool
-warn_dealloc_offset (location_t loc, tree exp, const access_ref &aref)
+warn_dealloc_offset (tree exp, const access_ref &aref)
 {
   if (aref.deref || aref.offrng[0] <= 0 || aref.offrng[1] <= 0)
     return false;
@@ -13480,9 +13564,10 @@ warn_dealloc_offset (location_t loc, tree exp, const access_ref &aref)
 		 (long long)aref.offrng[1].to_shwi ());
     }
 
-  if (!warning_at (loc, OPT_Wfree_nonheap_object,
-		   "%K%qD called on pointer %qE with nonzero offset%s",
-		   exp, dealloc_decl, aref.ref, offstr))
+  diag_inlining_context dic (exp);
+  if (!warning (dic, OPT_Wfree_nonheap_object,
+		"%qD called on pointer %qE with nonzero offset%s",
+		dealloc_decl, aref.ref, offstr))
     return false;
 
   if (DECL_P (aref.ref))
@@ -13537,19 +13622,20 @@ maybe_emit_free_warning (tree exp)
     return;
 
   tree dealloc_decl = get_callee_fndecl (exp);
-  location_t loc = tree_inlined_location (exp);
 
   if (DECL_P (ref) || EXPR_P (ref))
     {
+      diag_inlining_context dic (exp);
+
       /* Diagnose freeing a declared object.  */
       if (aref.ref_declared ()
-	  && warning_at (loc, OPT_Wfree_nonheap_object,
-			 "%K%qD called on unallocated object %qD",
-			 exp, dealloc_decl, ref))
+	  && warning (dic, OPT_Wfree_nonheap_object,
+		      "%qD called on unallocated object %qD",
+		      dealloc_decl, ref))
 	{
-	  loc = (DECL_P (ref)
-		 ? DECL_SOURCE_LOCATION (ref)
-		 : EXPR_LOCATION (ref));
+	  location_t loc = (DECL_P (ref)
+			    ? DECL_SOURCE_LOCATION (ref)
+			    : EXPR_LOCATION (ref));
 	  inform (loc, "declared here");
 	  return;
 	}
@@ -13558,14 +13644,15 @@ maybe_emit_free_warning (tree exp)
 	 Such a pointer cannot refer to the beginning of an allocated
 	 object.  A negative offset may refer to it.  */
       if (aref.sizrng[0] != aref.sizrng[1]
-	  && warn_dealloc_offset (loc, exp, aref))
+	  && warn_dealloc_offset (exp, aref))
 	return;
     }
   else if (CONSTANT_CLASS_P (ref))
     {
-      if (warning_at (loc, OPT_Wfree_nonheap_object,
-		      "%K%qD called on a pointer to an unallocated "
-		      "object %qE", exp, dealloc_decl, ref))
+      diag_inlining_context dic (exp);
+      if (warning (dic, OPT_Wfree_nonheap_object,
+		   "%qD called on a pointer to an unallocated "
+		   "object %qE", dealloc_decl, ref))
 	{
 	  if (TREE_CODE (ptr) == SSA_NAME)
 	    {
@@ -13591,7 +13678,7 @@ maybe_emit_free_warning (tree exp)
 	    {
 	      if (matching_alloc_calls_p (def_stmt, dealloc_decl))
 		{
-		  if (warn_dealloc_offset (loc, exp, aref))
+		  if (warn_dealloc_offset (exp, aref))
 		    return;
 		}
 	      else
@@ -13601,20 +13688,24 @@ maybe_emit_free_warning (tree exp)
 			     || DECL_IS_OPERATOR_DELETE_P (dealloc_decl)
 			     ? OPT_Wmismatched_new_delete
 			     : OPT_Wmismatched_dealloc);
-		  warned = warning_at (loc, opt,
-				       "%K%qD called on pointer returned "
-				       "from a mismatched allocation "
-				       "function", exp, dealloc_decl);
+		  diag_inlining_context dic (exp);
+		  warned = warning (dic, opt,
+				    "%qD called on pointer returned "
+				    "from a mismatched allocation "
+				    "function", dealloc_decl);
 		}
 	    }
 	  else if (gimple_call_builtin_p (def_stmt, BUILT_IN_ALLOCA)
 	    	   || gimple_call_builtin_p (def_stmt,
 	    				     BUILT_IN_ALLOCA_WITH_ALIGN))
-	    warned = warning_at (loc, OPT_Wfree_nonheap_object,
-				 "%K%qD called on pointer to "
-				 "an unallocated object",
-				 exp, dealloc_decl);
-	  else if (warn_dealloc_offset (loc, exp, aref))
+	    {
+	      diag_inlining_context dic (exp);
+	      warned = warning (dic, OPT_Wfree_nonheap_object,
+				"%qD called on pointer to "
+				"an unallocated object",
+				dealloc_decl);
+	    }
+	  else if (warn_dealloc_offset (exp, aref))
 	    return;
 
 	  if (warned)
@@ -13633,7 +13724,7 @@ maybe_emit_free_warning (tree exp)
 	      && !aref.deref
 	      && aref.sizrng[0] != aref.sizrng[1]
 	      && aref.offrng[0] > 0 && aref.offrng[1] > 0
-	      && warn_dealloc_offset (loc, exp, aref))
+	      && warn_dealloc_offset (exp, aref))
 	    return;
 	}
     }
diff --git a/gcc/cp/mapper-client.cc b/gcc/cp/mapper-client.cc
index a72b4b70664..368e88201fa 100644
--- a/gcc/cp/mapper-client.cc
+++ b/gcc/cp/mapper-client.cc
@@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.  If not see
 #define INCLUDE_STRING
 #define INCLUDE_VECTOR
 #include "system.h"
-
+#include "coretypes.h"
 #include "line-map.h"
 #include "diagnostic-core.h"
 #include "mapper-client.h"
diff --git a/gcc/diagnostic-core.h b/gcc/diagnostic-core.h
index 60fe8a27f44..cdf70ddfb46 100644
--- a/gcc/diagnostic-core.h
+++ b/gcc/diagnostic-core.h
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_DIAGNOSTIC_CORE_H
 
 #include "bversion.h"
+#include "diagnostic-metadata.h"
 
 /* Constants used to discriminate diagnostics.  */
 typedef enum
@@ -81,6 +82,16 @@ extern bool warning_at (location_t, int, const char *, ...)
     ATTRIBUTE_GCC_DIAG(3,4);
 extern bool warning_at (rich_location *, int, const char *, ...)
     ATTRIBUTE_GCC_DIAG(3,4);
+
+/* Same as warning_at but with contextual informaion provided by first
+   argument.  */
+extern bool warning (diagnostic_metadata::location_context&, int,
+		     const char *, ...)
+  ATTRIBUTE_GCC_DIAG (3, 4);
+extern bool warning_n (diagnostic_metadata::location_context&, int,
+		       unsigned HOST_WIDE_INT, const char *, const char *, ...)
+    ATTRIBUTE_GCC_DIAG (4, 6) ATTRIBUTE_GCC_DIAG (5, 6);
+
 extern bool warning_meta (rich_location *,
 			  const diagnostic_metadata &, int,
 			  const char *, ...)
diff --git a/gcc/diagnostic-metadata.h b/gcc/diagnostic-metadata.h
index fe10304e05e..db49cff72b9 100644
--- a/gcc/diagnostic-metadata.h
+++ b/gcc/diagnostic-metadata.h
@@ -21,22 +21,45 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_DIAGNOSTIC_METADATA_H
 #define GCC_DIAGNOSTIC_METADATA_H
 
+#include "vec.h"
+
 /* A bundle of additional metadata that can be associated with a
    diagnostic.
 
-   Currently this only supports associating a CWE identifier with a
-   diagnostic.  */
+   Currently this only supports associating a location context and
+   a CWE identifier with a diagnostic.  */
 
 class diagnostic_metadata
 {
  public:
-  diagnostic_metadata () : m_cwe (0) {}
+  class location_context;
+
+  diagnostic_metadata () : m_lctx (), m_cwe (0) {}
+
+  diagnostic_metadata (location_context &lctx)
+    : m_lctx (&lctx), m_cwe () {}
 
   void add_cwe (int cwe) { m_cwe = cwe; }
   int get_cwe () const { return m_cwe; }
 
+  location_context* location_ctx () const { return m_lctx; }
+
  private:
+  /* The context of the expression the diagnostic is issued for.  For
+     front end diagnostics it's empty.  For middle end diagnostics it
+     includes the inlining context (implemented in a derived class).  */
+  location_context *m_lctx;
   int m_cwe;
 };
 
+struct diagnostic_info;
+
+class diagnostic_metadata::location_context
+{
+public:
+  virtual void locations (vec<location_t> &, diagnostic_info *);
+  virtual void set_location (diagnostic_info *) { }
+};
+
+
 #endif /* ! GCC_DIAGNOSTIC_METADATA_H */
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 246d75256cf..d82a7eb67e5 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "selftest-diagnostic.h"
 #include "opts.h"
 #include "cpplib.h"
+#include "tree.h"
 
 #ifdef HAVE_TERMIOS_H
 # include <termios.h>
@@ -991,51 +992,81 @@ print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
   pp_set_prefix (pp, saved_prefix);
 }
 
-/* Update the diag_class of DIAGNOSTIC based on its location
-   relative to any
+/* Add DIAGNOSTIC location to LOCS.  */
+
+/* virtual */ void
+diagnostic_metadata::
+location_context::locations (vec<location_t> &locs, diagnostic_info *di)
+{
+  locs.safe_push (diagnostic_location (di));
+}
+
+
+/* Update the kind of DIAGNOSTIC based on its location(s), including
+   any of those in its inlining context, relative to any
      #pragma GCC diagnostic
    directives recorded within CONTEXT.
 
-   Return the new diag_class of DIAGNOSTIC if it was updated, or
-   DK_UNSPECIFIED otherwise.  */
+   Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
+   otherwise.  */
 
 static diagnostic_t
 update_effective_level_from_pragmas (diagnostic_context *context,
 				     diagnostic_info *diagnostic)
 {
-  diagnostic_t diag_class = DK_UNSPECIFIED;
-
   if (context->n_classification_history > 0)
     {
-      location_t location = diagnostic_location (diagnostic);
-
-      /* FIXME: Stupid search.  Optimize later. */
-      for (int i = context->n_classification_history - 1; i >= 0; i --)
+      auto_vec<location_t, 8> locs;
+      diagnostic_metadata::location_context *lctx = NULL;
+      if (const diagnostic_metadata *mdata = diagnostic->metadata)
+	lctx = mdata->location_ctx ();
+
+      if (lctx)
+	/* Retrieve the locations into which the expression about to be
+	   diagnosed has been inlined, including those of all the callers
+	   all the way down the inlining stack.  */
+	lctx->locations (locs, diagnostic);
+      else
+	/* When there's no metadata use just the one location provided
+	   by the caller of the diagnostic function.  */
+	locs.safe_push (diagnostic_location (diagnostic));
+
+      /* Iterate over the locations, checking the diagnostic disposition
+	 for the diagnostic at each.  If it's explicitly set as opposed
+	 to unspecified, update the disposition for this instance of
+	 the diagnostic and return it.  */
+      for (unsigned idx = 0; idx < locs.length (); ++idx)
 	{
-	  if (linemap_location_before_p
-	      (line_table,
-	       context->classification_history[i].location,
-	       location))
+	  /* FIXME: Stupid search.  Optimize later. */
+	  for (int i = context->n_classification_history - 1; i >= 0; i --)
 	    {
-	      if (context->classification_history[i].kind == (int) DK_POP)
-		{
-		  i = context->classification_history[i].option;
-		  continue;
-		}
-	      int option = context->classification_history[i].option;
-	      /* The option 0 is for all the diagnostics.  */
-	      if (option == 0 || option == diagnostic->option_index)
+	      const diagnostic_classification_change_t &hist
+		= context->classification_history[i];
+
+	      location_t pragloc = hist.location;
+	      if (linemap_location_before_p (line_table, pragloc, locs[idx]))
 		{
-		  diag_class = context->classification_history[i].kind;
-		  if (diag_class != DK_UNSPECIFIED)
-		    diagnostic->kind = diag_class;
-		  break;
+		  if (hist.kind == (int) DK_POP)
+		    {
+		      /* Move on to the next region.  */
+		      i = hist.option;
+		      continue;
+		    }
+		  int option = hist.option;
+		  /* The option 0 is for all the diagnostics.  */
+		  if (option == 0 || option == diagnostic->option_index)
+		    {
+		      diagnostic_t kind = hist.kind;
+		      if (kind != DK_UNSPECIFIED)
+			diagnostic->kind = kind;
+		      return kind;
+		    }
 		}
 	    }
 	}
     }
 
-  return diag_class;
+  return DK_UNSPECIFIED;
 }
 
 /* Generate a URL string describing CWE.  The caller is responsible for
@@ -1239,8 +1270,14 @@ diagnostic_report_diagnostic (diagnostic_context *context,
     }
   context->diagnostic_group_emission_count++;
 
+  /* Move X_DATA into DIAGNOSTIC->MESSAGE before setting inlining context
+     abstract origin and location.  It uses X_DATA.  */
   diagnostic->message.x_data = &diagnostic->x_data;
   diagnostic->x_data = NULL;
+  if (const diagnostic_metadata *mdata = diagnostic->metadata)
+    if (diagnostic_metadata::location_context *lctx = mdata->location_ctx ())
+      lctx->set_location (diagnostic);
+
   pp_format (context->printer, &diagnostic->message);
   (*diagnostic_starter (context)) (context, diagnostic);
   pp_output_formatted_text (context->printer);
@@ -1389,7 +1426,7 @@ diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
 		 int opt, const char *gmsgid,
 		 va_list *ap, diagnostic_t kind)
 {
-  diagnostic_info diagnostic;
+  diagnostic_info diagnostic{ };
   if (kind == DK_PERMERROR)
     {
       diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
@@ -1415,7 +1452,7 @@ diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
 		   const char *plural_gmsgid,
 		   va_list *ap, diagnostic_t kind)
 {
-  diagnostic_info diagnostic;
+  diagnostic_info diagnostic{ };
   unsigned long gtn;
 
   if (sizeof n <= sizeof gtn)
@@ -1616,6 +1653,46 @@ warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
   return ret;
 }
 
+/* A warning at location and context provided by first argument.  Same
+   as warning_at() with location_t except that it doesn't require %K (or
+   in the future %G).  */
+
+bool
+warning (diagnostic_metadata::location_context &lctx, int opt,
+	 const char *gmsgid, ...)
+{
+  auto_diagnostic_group d;
+  va_list ap;
+  va_start (ap, gmsgid);
+  rich_location richloc (line_table, UNKNOWN_LOCATION);
+  diagnostic_metadata mdata (lctx);
+  bool ret = diagnostic_impl (&richloc, &mdata, opt, gmsgid,
+			      &ap, DK_WARNING);
+  va_end (ap);
+  return ret;
+}
+
+/* A warning at location and context provided by first argument.  Same
+   as warning_n() with location_t except that it doesn't require %K (or
+   in the future %G).  */
+
+bool
+warning_n (diagnostic_metadata::location_context &lctx, int opt,
+	   unsigned HOST_WIDE_INT n,
+	   const char *singular_gmsgid, const char *plural_gmsgid, ...)
+{
+  auto_diagnostic_group d;
+  va_list ap;
+  va_start (ap, plural_gmsgid);
+  rich_location richloc (line_table, UNKNOWN_LOCATION);
+  diagnostic_metadata mdata (lctx);
+  bool ret = diagnostic_n_impl (&richloc, &mdata, opt, n,
+				singular_gmsgid, plural_gmsgid,
+				&ap, DK_WARNING);
+  va_end (ap);
+  return ret;
+}
+
 /* A "pedantic" warning at LOCATION: issues a warning unless
    -pedantic-errors was given on the command line, in which case it
    issues an error.  Use this for diagnostics required by the relevant
diff --git a/gcc/testsuite/gcc.dg/pragma-diag-10.c b/gcc/testsuite/gcc.dg/pragma-diag-10.c
new file mode 100644
index 00000000000..127b299939a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pragma-diag-10.c
@@ -0,0 +1,20 @@
+/* PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective
+   in conjunction with alias attribute
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+void *
+__rawmemchr_ppc (const void *s, int c)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+#pragma GCC diagnostic ignored "-Wstringop-overread"
+  if (c != 0)
+    return __builtin_memchr (s, c, (unsigned long)-1);    // { dg-bogus "specified bound \\d+ exceeds maximum object size" }
+#pragma GCC diagnostic pop
+
+  return (char *)s + __builtin_strlen (s);
+}
+
+extern __typeof (__rawmemchr_ppc) __EI___rawmemchr_ppc
+  __attribute__((alias ("__rawmemchr_ppc")));
diff --git a/gcc/testsuite/gcc.dg/pragma-diag-9.c b/gcc/testsuite/gcc.dg/pragma-diag-9.c
new file mode 100644
index 00000000000..d7eac558128
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pragma-diag-9.c
@@ -0,0 +1,134 @@
+/* Verify that #pragma GCC diagnostic down the inlining stack suppresses
+   a warning that would otherwise be issued for inlined calls higher up
+   the inlining stack.
+   { dg-do compile }
+   { dg-options "-O2 -Wall -Wno-array-bounds" } */
+
+extern void* memset (void*, int, __SIZE_TYPE__);
+
+static void warn0 (int *p)
+{
+  memset (p, __LINE__, 3);    // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+static void warn1 (int *p)
+{
+  warn0 (p + 1);
+}
+
+static void warn2 (int *p)
+{
+  warn1 (p + 1);
+}
+
+int a2[2];                    // { dg-message "at offset 12 into destination object 'a2' of size 8" }
+
+void warn3 (void)
+{
+  warn2 (a2 + 1);
+}
+
+
+static void ignore0 (int *p)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  memset (p, __LINE__, 3);
+#pragma GCC diagnostic pop
+}
+
+static void nowarn1_ignore0 (int *p)
+{
+  ignore0 (p + 1);
+}
+
+static void nowarn2_ignore0 (int *p)
+{
+  nowarn1_ignore0 (p + 1);
+}
+
+int b2[2];
+
+void nowarn3_ignore0 (void)
+{
+  nowarn2_ignore0 (b2 + 1);
+}
+
+
+static void nowarn0_ignore1 (int *p)
+{
+  memset (p, __LINE__, 3);
+}
+
+static void ignore1 (int *p)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  nowarn0_ignore1 (p + 1);
+#pragma GCC diagnostic pop
+}
+
+void nowarn2_ignore1 (int *p)
+{
+  ignore1 (p + 1);
+}
+
+int c2[2];
+
+void nowarn3_ignore1 (void)
+{
+  nowarn2_ignore1 (c2 + 1);
+}
+
+
+static void nowarn0_ignore2 (int *p)
+{
+  memset (p, __LINE__, 3);
+}
+
+static void nowarn1_ignore2 (int *p)
+{
+  nowarn0_ignore2 (p + 1);
+}
+
+static void ignore2 (int *p)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  nowarn1_ignore2 (p + 1);
+#pragma GCC diagnostic pop
+}
+
+int d2[2];
+
+void nowarn3_ignore2 (void)
+{
+  ignore2 (c2 + 1);
+}
+
+
+
+static void nowarn0_ignore3 (int *p)
+{
+  memset (p, __LINE__, 3);
+}
+
+static void nowarn1_ignore3 (int *p)
+{
+  nowarn0_ignore3 (p + 1);
+}
+
+static void nowarn2_ignore3 (int *p)
+{
+  nowarn1_ignore3 (p + 1);
+}
+
+int e2[2];
+
+void ignore3 (void)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  nowarn2_ignore3 (e2 + 1);
+#pragma GCC diagnostic pop
+}
diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc
index 5beda8b829b..c3faa6bfde4 100644
--- a/libstdc++-v3/include/bits/basic_string.tcc
+++ b/libstdc++-v3/include/bits/basic_string.tcc
@@ -468,6 +468,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	    }
 	  else
 	    {
+	      /* Suppress false positives when GCC can't determine that
+		 __s doesn't alias _M_data().  */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+#pragma GCC diagnostic ignored "-Wstringop-overread"
 	      // Work in-place.
 	      if (__len2 && __len2 <= __len1)
 		this->_S_move(__p, __s, __len2);
@@ -488,6 +493,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		    }
 		}
 	    }
+#pragma GCC diagnostic pop
 	}
       else
 	this->_M_mutate(__pos, __len1, __s, __len2);
diff --git a/libstdc++-v3/testsuite/18_support/new_delete_placement.cc b/libstdc++-v3/testsuite/18_support/new_delete_placement.cc
index e4f747606cd..1d188f6edd8 100644
--- a/libstdc++-v3/testsuite/18_support/new_delete_placement.cc
+++ b/libstdc++-v3/testsuite/18_support/new_delete_placement.cc
@@ -32,6 +32,8 @@ void test01()
   operator delete[](p, tmp);
 }
 
+// { dg-prune-output "\\\[-Wfree-nonheap-object" }
+
 int main()
 {
   test01();
diff --git a/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/allocate.cc b/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/allocate.cc
index 95d512d4b82..55973992837 100644
--- a/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/allocate.cc
+++ b/libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/allocate.cc
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17" }
+// { dg-options "-std=gnu++17 -Wno-alloc-size-larger-than" }
 // { dg-do run { target c++17 } }
 // { dg-require-cstdint "" }
 
diff --git a/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/allocate.cc b/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/allocate.cc
index 79fac01fb25..fab73838f38 100644
--- a/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/allocate.cc
+++ b/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/allocate.cc
@@ -15,7 +15,7 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++17" }
+// { dg-options "-std=gnu++17 -Wno-alloc-size-larger-than" }
 // { dg-do run { target c++17 } }
 
 #include <memory_resource>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* PING [PATCH] improve warning suppression for inlined functions (PR 98465, 98512)
  2021-01-21 23:46 ` Martin Sebor
@ 2021-01-30  2:56   ` Martin Sebor
  2021-02-06 17:12     ` PING 2 " Martin Sebor
  2021-05-19 13:41   ` David Malcolm
  1 sibling, 1 reply; 44+ messages in thread
From: Martin Sebor @ 2021-01-30  2:56 UTC (permalink / raw)
  To: gcc-patches

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-January/564060.html

On 1/21/21 4:46 PM, Martin Sebor wrote:
> The initial patch I posted is missing initialization for a couple
> of locals.  I'd noticed it in testing but forgot to add the fix to
> the patch before posting it.  I have corrected that in the updated
> revision and also added the test case from pr98512, and retested
> the whole thing on x86_64-linux.
> 
> On 1/19/21 11:58 AM, Martin Sebor wrote:
>> std::string tends to trigger a class of false positive out of bounds
>> access warnings for code GCC cannot prove is unreachable because of
>> missing aliasing constrains, and that ends up expanded inline into
>> user code.  Simply inserting the contents of a constant char array
>> does that.  In GCC 10 these false positives are suppressed due to
>> -Wno-system-headers, but in GCC 11, to help detect calls rendered
>> invalid by user code passing in either incorrect or insufficiently
>> constrained arguments, -Wno-system-header no longer has this effect
>> on invalid access warnings.
>>
>> To solve the problem without at least partially reverting the change
>> and going back to the GCC 10 way of things for the affected subset
>> of calls (just memcpy and memmove), the attached patch enhances
>> the #pragma GCC diagnostic machinery to consider not just a single
>> location for inlined code but all locations at which an expression
>> and its callers are inlined all the way up the stack.  This gives
>> each author of a function involved in inlining the ability to
>> control a warning issued for the code, not just the user into whose
>> code all the calls end up inlined.  To resolve PR 98465, it lets us
>> suppress the false positives selectively in std::string rather
>> than across the board in GCC.
>>
>> The solution is to provide a new pair of overloads for warning
>> functions that, instead of taking a single location argument, take
>> a tree node from which the location(s) are determined.  The tree
>> argument is indirect because the diagnostic machinery doesn't (and
>> cannot without more intrusive changes) at the moment depend on
>> the various tree definitions.  A nice feature of these overloads
>> is that they do away with the need for the %K directive (and in
>> the future also %G, with another enhancement to accept a gimple*
>> argument).
>>
>> This patch depends on the fix for PR 98664 (already approved but
>> not yet checked in).  I've tested it on x86_64-linux.
>>
>> To avoid fallout I tried to keep the changes to a minimum, and
>> so the design isn't as robust as I'd like it ultimately to be.
>> I plan to enhance it in stage 1.
>>
>> Martin
> 


^ permalink raw reply	[flat|nested] 44+ messages in thread

* PING 2 [PATCH] improve warning suppression for inlined functions (PR 98465, 98512)
  2021-01-30  2:56   ` PING " Martin Sebor
@ 2021-02-06 17:12     ` Martin Sebor
  2021-02-15  0:40       ` PING 3 " Martin Sebor
  0 siblings, 1 reply; 44+ messages in thread
From: Martin Sebor @ 2021-02-06 17:12 UTC (permalink / raw)
  To: gcc-patches

Ping 2:
   https://gcc.gnu.org/pipermail/gcc-patches/2021-January/564060.html

On 1/29/21 7:56 PM, Martin Sebor wrote:
> Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-January/564060.html
> 
> On 1/21/21 4:46 PM, Martin Sebor wrote:
>> The initial patch I posted is missing initialization for a couple
>> of locals.  I'd noticed it in testing but forgot to add the fix to
>> the patch before posting it.  I have corrected that in the updated
>> revision and also added the test case from pr98512, and retested
>> the whole thing on x86_64-linux.
>>
>> On 1/19/21 11:58 AM, Martin Sebor wrote:
>>> std::string tends to trigger a class of false positive out of bounds
>>> access warnings for code GCC cannot prove is unreachable because of
>>> missing aliasing constrains, and that ends up expanded inline into
>>> user code.  Simply inserting the contents of a constant char array
>>> does that.  In GCC 10 these false positives are suppressed due to
>>> -Wno-system-headers, but in GCC 11, to help detect calls rendered
>>> invalid by user code passing in either incorrect or insufficiently
>>> constrained arguments, -Wno-system-header no longer has this effect
>>> on invalid access warnings.
>>>
>>> To solve the problem without at least partially reverting the change
>>> and going back to the GCC 10 way of things for the affected subset
>>> of calls (just memcpy and memmove), the attached patch enhances
>>> the #pragma GCC diagnostic machinery to consider not just a single
>>> location for inlined code but all locations at which an expression
>>> and its callers are inlined all the way up the stack.  This gives
>>> each author of a function involved in inlining the ability to
>>> control a warning issued for the code, not just the user into whose
>>> code all the calls end up inlined.  To resolve PR 98465, it lets us
>>> suppress the false positives selectively in std::string rather
>>> than across the board in GCC.
>>>
>>> The solution is to provide a new pair of overloads for warning
>>> functions that, instead of taking a single location argument, take
>>> a tree node from which the location(s) are determined.  The tree
>>> argument is indirect because the diagnostic machinery doesn't (and
>>> cannot without more intrusive changes) at the moment depend on
>>> the various tree definitions.  A nice feature of these overloads
>>> is that they do away with the need for the %K directive (and in
>>> the future also %G, with another enhancement to accept a gimple*
>>> argument).
>>>
>>> This patch depends on the fix for PR 98664 (already approved but
>>> not yet checked in).  I've tested it on x86_64-linux.
>>>
>>> To avoid fallout I tried to keep the changes to a minimum, and
>>> so the design isn't as robust as I'd like it ultimately to be.
>>> I plan to enhance it in stage 1.
>>>
>>> Martin
>>
> 


^ permalink raw reply	[flat|nested] 44+ messages in thread

* PING 3 [PATCH] improve warning suppression for inlined functions (PR 98465, 98512)
  2021-02-06 17:12     ` PING 2 " Martin Sebor
@ 2021-02-15  0:40       ` Martin Sebor
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Sebor @ 2021-02-15  0:40 UTC (permalink / raw)
  To: gcc-patches, Jeff Law

Ping 3:
https://gcc.gnu.org/pipermail/gcc-patches/2021-January/564060.html

I submitted this as a fix for a fair number of false positives
reported by Fedora package maintainers.  Last week Jakub committed
r11-7146, which is an alternate workaround for the same problem,
but one isolated to libstdc++.  That might make this patch less
pressing but not less relevant since it also fixes pr98512 (a bug
impacting Glibc) and adds the infrastructure for resolving pr98871
and other bugs about the #pragma diagnostic's inability to suppress
warnings in inlined code.

Jeff (or anyone else who cares about this) if you consider this
patch too intrusive at this point let me know and I'll stop pinging
it and resubmit it for GCC 12.

On 2/6/21 10:12 AM, Martin Sebor wrote:
> Ping 2:
>    https://gcc.gnu.org/pipermail/gcc-patches/2021-January/564060.html
> 
> On 1/29/21 7:56 PM, Martin Sebor wrote:
>> Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-January/564060.html
>>
>> On 1/21/21 4:46 PM, Martin Sebor wrote:
>>> The initial patch I posted is missing initialization for a couple
>>> of locals.  I'd noticed it in testing but forgot to add the fix to
>>> the patch before posting it.  I have corrected that in the updated
>>> revision and also added the test case from pr98512, and retested
>>> the whole thing on x86_64-linux.
>>>
>>> On 1/19/21 11:58 AM, Martin Sebor wrote:
>>>> std::string tends to trigger a class of false positive out of bounds
>>>> access warnings for code GCC cannot prove is unreachable because of
>>>> missing aliasing constrains, and that ends up expanded inline into
>>>> user code.  Simply inserting the contents of a constant char array
>>>> does that.  In GCC 10 these false positives are suppressed due to
>>>> -Wno-system-headers, but in GCC 11, to help detect calls rendered
>>>> invalid by user code passing in either incorrect or insufficiently
>>>> constrained arguments, -Wno-system-header no longer has this effect
>>>> on invalid access warnings.
>>>>
>>>> To solve the problem without at least partially reverting the change
>>>> and going back to the GCC 10 way of things for the affected subset
>>>> of calls (just memcpy and memmove), the attached patch enhances
>>>> the #pragma GCC diagnostic machinery to consider not just a single
>>>> location for inlined code but all locations at which an expression
>>>> and its callers are inlined all the way up the stack.  This gives
>>>> each author of a function involved in inlining the ability to
>>>> control a warning issued for the code, not just the user into whose
>>>> code all the calls end up inlined.  To resolve PR 98465, it lets us
>>>> suppress the false positives selectively in std::string rather
>>>> than across the board in GCC.
>>>>
>>>> The solution is to provide a new pair of overloads for warning
>>>> functions that, instead of taking a single location argument, take
>>>> a tree node from which the location(s) are determined.  The tree
>>>> argument is indirect because the diagnostic machinery doesn't (and
>>>> cannot without more intrusive changes) at the moment depend on
>>>> the various tree definitions.  A nice feature of these overloads
>>>> is that they do away with the need for the %K directive (and in
>>>> the future also %G, with another enhancement to accept a gimple*
>>>> argument).
>>>>
>>>> This patch depends on the fix for PR 98664 (already approved but
>>>> not yet checked in).  I've tested it on x86_64-linux.
>>>>
>>>> To avoid fallout I tried to keep the changes to a minimum, and
>>>> so the design isn't as robust as I'd like it ultimately to be.
>>>> I plan to enhance it in stage 1.
>>>>
>>>> Martin
>>>
>>
> 


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] improve warning suppression for inlined functions (PR 98465, 98512)
  2021-01-19 18:58 [PATCH] improve warning suppression for inlined functions (PR 98465, 98512) Martin Sebor
  2021-01-21 17:34 ` Florian Weimer
  2021-01-21 23:46 ` Martin Sebor
@ 2021-02-19  4:28 ` Jeff Law
  2021-02-19 10:57   ` Florian Weimer
  2 siblings, 1 reply; 44+ messages in thread
From: Jeff Law @ 2021-02-19  4:28 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches



On 1/19/21 11:58 AM, Martin Sebor via Gcc-patches wrote:
> std::string tends to trigger a class of false positive out of bounds
> access warnings for code GCC cannot prove is unreachable because of
> missing aliasing constrains, and that ends up expanded inline into
> user code.  Simply inserting the contents of a constant char array
> does that.  In GCC 10 these false positives are suppressed due to
> -Wno-system-headers, but in GCC 11, to help detect calls rendered
> invalid by user code passing in either incorrect or insufficiently
> constrained arguments, -Wno-system-header no longer has this effect
> on invalid access warnings.
>
> To solve the problem without at least partially reverting the change
> and going back to the GCC 10 way of things for the affected subset
> of calls (just memcpy and memmove), the attached patch enhances
> the #pragma GCC diagnostic machinery to consider not just a single
> location for inlined code but all locations at which an expression
> and its callers are inlined all the way up the stack.  This gives
> each author of a function involved in inlining the ability to
> control a warning issued for the code, not just the user into whose
> code all the calls end up inlined.  To resolve PR 98465, it lets us
> suppress the false positives selectively in std::string rather
> than across the board in GCC.
>
> The solution is to provide a new pair of overloads for warning
> functions that, instead of taking a single location argument, take
> a tree node from which the location(s) are determined.  The tree
> argument is indirect because the diagnostic machinery doesn't (and
> cannot without more intrusive changes) at the moment depend on
> the various tree definitions.  A nice feature of these overloads
> is that they do away with the need for the %K directive (and in
> the future also %G, with another enhancement to accept a gimple*
> argument).
>
> This patch depends on the fix for PR 98664 (already approved but
> not yet checked in).  I've tested it on x86_64-linux.
>
> To avoid fallout I tried to keep the changes to a minimum, and
> so the design isn't as robust as I'd like it ultimately to be.
> I plan to enhance it in stage 1.
I'd lean towards deferring to gcc12 stage1 given the libstdc++ hack is
in place.  That does mean that glibc will need to work around the
instance they've stumbled over in ppc's rawmemchr.

If there are other BZs where this would help our ability to "cleanly"
suppress diagnosics with our pragmas, then we probably should link them
together with 98512/98465 and defer them all to gcc-12.

Jeff


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] improve warning suppression for inlined functions (PR 98465, 98512)
  2021-02-19  4:28 ` [PATCH] improve warning suppression for inlined functions (PR 98465, 98512) Jeff Law
@ 2021-02-19 10:57   ` Florian Weimer
  0 siblings, 0 replies; 44+ messages in thread
From: Florian Weimer @ 2021-02-19 10:57 UTC (permalink / raw)
  To: Jeff Law via Gcc-patches

* Jeff Law via Gcc-patches:

> I'd lean towards deferring to gcc12 stage1 given the libstdc++ hack is
> in place.  That does mean that glibc will need to work around the
> instance they've stumbled over in ppc's rawmemchr.

We'll need to work around this in the glibc build, too.  I'll check if
the suggested alternative (have the alias covered by the pragma) works
there as well.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] improve warning suppression for inlined functions (PR 98465, 98512)
  2021-01-21 23:46 ` Martin Sebor
  2021-01-30  2:56   ` PING " Martin Sebor
@ 2021-05-19 13:41   ` David Malcolm
  2021-06-10 23:24     ` [PATCH 0/4] improve warning suppression for inlined functions (PR 98512) Martin Sebor
  1 sibling, 1 reply; 44+ messages in thread
From: David Malcolm @ 2021-05-19 13:41 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches

On Thu, 2021-01-21 at 16:46 -0700, Martin Sebor via Gcc-patches wrote:

Martin and I had a chat about this patch, but it's best to discuss code
on the mailing list rather than in a silo, so here goes...


> The initial patch I posted is missing initialization for a couple
> of locals.  I'd noticed it in testing but forgot to add the fix to
> the patch before posting it.  I have corrected that in the updated
> revision and also added the test case from pr98512, and retested
> the whole thing on x86_64-linux.
> 
> On 1/19/21 11:58 AM, Martin Sebor wrote:
> > std::string tends to trigger a class of false positive out of bounds
> > access warnings for code GCC cannot prove is unreachable because of
> > missing aliasing constrains, and that ends up expanded inline into
> > user code.  Simply inserting the contents of a constant char array
> > does that.  In GCC 10 these false positives are suppressed due to
> > -Wno-system-headers, but in GCC 11, to help detect calls rendered
> > invalid by user code passing in either incorrect or insufficiently
> > constrained arguments, -Wno-system-header no longer has this effect
> > on invalid access warnings.
> > 
> > To solve the problem without at least partially reverting the change
> > and going back to the GCC 10 way of things for the affected subset
> > of calls (just memcpy and memmove), the attached patch enhances
> > the #pragma GCC diagnostic machinery to consider not just a single
> > location for inlined code but all locations at which an expression
> > and its callers are inlined all the way up the stack.  This gives
> > each author of a function involved in inlining the ability to
> > control a warning issued for the code, not just the user into whose
> > code all the calls end up inlined.  To resolve PR 98465, it lets us
> > suppress the false positives selectively in std::string rather
> > than across the board in GCC.

I like the idea of checking the whole of the inlining stack for
pragmas, but I don't like the way the patch implements it.

The patch provides a hook for getting a vec of locations for a
diagnostic for use when checking for pragmas, and uses it the hook on a
few specific diagnostics.

Why wouldn’t we always do this?  It seems to me like something we
should always do when there's inlining information associated with a
location, rather than being a per-diagnostic thing - but maybe there's
something I'm missing here.  The patch adds diag_inlining_context
instances on the stack in various places, and doing that feels to me
like a special-case hack, when it should be fixed more generally in
diagnostics.c

I don't like attaching the "override the location" hook to the
diagnostic_metadata; I intended the latter to be about diagnostic
taxonomies (CWE, coding standards, etc), rather than a place to stash
location overrides.

One issue is that the core of the diagnostics subsystem doesn't have
knowledge of "tree", but the inlining information requires tree-ish
knowledge.

It's still possible to get at the inlining information from the
diagnostics.c, but only as a void *:

input.h's has:

#define LOCATION_BLOCK(LOC) \
  ((tree) ((IS_ADHOC_LOC (LOC)) ? get_data_from_adhoc_loc (line_table,
(LOC)) \
   : NULL))

Without knowing about "tree", diagnostic.c could still query a
location_t to get at the data as a void *:

  if (IS_ADHOC_LOC (loc)
    return get_data_from_adhoc_loc (line_table, loc);
  else
    return NULL;


If we make the "get all the pertinent locations" hook a part of the
diagnostic_context, we could have diagnostic_report_diagnostic check to
see if there's ad-hoc data associated with the location and a non-NULL
hook on the context, and if so, call it.  This avoids adding an
indirect call for the common case where there isn't any inlining
information, and lets us stash the implementation of the hook in the
tree-diagnostic.c, keeping the separation of trees from diagnostic.c

One design question here is: what if there are multiple pragmas on the
inlining stack, e.g. explicitly enabling a warning at one place, and
explicitly ignoring that warning in another?  I don't think it would
happen in the cases you're interested in, but it seems worth
considering.  Perhaps the closest place to the user's code "wins".

> > 
> > The solution is to provide a new pair of overloads for warning
> > functions that, instead of taking a single location argument, take
> > a tree node from which the location(s) are determined.  The tree
> > argument is indirect because the diagnostic machinery doesn't (and
> > cannot without more intrusive changes) at the moment depend on
> > the various tree definitions.  A nice feature of these overloads
> > is that they do away with the need for the %K directive (and in
> > the future also %G, with another enhancement to accept a gimple*
> > argument).

We were chatting about this, and I believe we don't need the new
overloads or the %K and %G directives: all of the information about
inlining can be got from the location_t via the line_table (albeit as a
void *) as seen above.  

  gimple_block (const gimple *g)

is merely:

  return LOCATION_BLOCK (g->location);

and is thus merely looking up the information from the location_t and
line_table; it doesn't actually use anything else about the gimple
stmt.


Does the above make sense?

Hope this is constructive
Dave

> > 
> > This patch depends on the fix for PR 98664 (already approved but
> > not yet checked in).  I've tested it on x86_64-linux.
> > 
> > To avoid fallout I tried to keep the changes to a minimum, and
> > so the design isn't as robust as I'd like it ultimately to be.
> > I plan to enhance it in stage 1.
> > 
> > Martin
> 



^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 0/4] improve warning suppression for inlined functions (PR 98512)
  2021-05-19 13:41   ` David Malcolm
@ 2021-06-10 23:24     ` Martin Sebor
  2021-06-10 23:26       ` [PATCH 1/4] introduce diagnostic infrastructure changes " Martin Sebor
                         ` (3 more replies)
  0 siblings, 4 replies; 44+ messages in thread
From: Martin Sebor @ 2021-06-10 23:24 UTC (permalink / raw)
  To: David Malcolm, gcc-patches, Martin Sebor

David, this is a revised patch set based on your feedback below
and our discussion.  It works with the existing warning_at()
interface without introducing any new overloads (for now).  It
resolves PR middle-end/98871 and 98512.  PR 98465 was handled
in GCC 11 differently so this has no impact on that problem
anymore.

The first diff in the series introduces the diagnostic
infrastructure changes.

The second one removes the uses of %G and %K from all warning_at()
calls throughout GCC front end and middle end.  The inlining context
is included in diagnostic output whenever it's present.

The third removes the uses of %K from error() calls in the arm and
aarch64 back end.

The fourth and final diff then removes the handlers from the pretty
printer and the support for the directives from c-format.c.

On 5/19/21 7:41 AM, David Malcolm wrote:
> On Thu, 2021-01-21 at 16:46 -0700, Martin Sebor via Gcc-patches wrote:
> 
> Martin and I had a chat about this patch, but it's best to discuss code
> on the mailing list rather than in a silo, so here goes...
> 
> 
>> The initial patch I posted is missing initialization for a couple
>> of locals.  I'd noticed it in testing but forgot to add the fix to
>> the patch before posting it.  I have corrected that in the updated
>> revision and also added the test case from pr98512, and retested
>> the whole thing on x86_64-linux.
>>
>> On 1/19/21 11:58 AM, Martin Sebor wrote:
>>> std::string tends to trigger a class of false positive out of bounds
>>> access warnings for code GCC cannot prove is unreachable because of
>>> missing aliasing constrains, and that ends up expanded inline into
>>> user code.  Simply inserting the contents of a constant char array
>>> does that.  In GCC 10 these false positives are suppressed due to
>>> -Wno-system-headers, but in GCC 11, to help detect calls rendered
>>> invalid by user code passing in either incorrect or insufficiently
>>> constrained arguments, -Wno-system-header no longer has this effect
>>> on invalid access warnings.
>>>
>>> To solve the problem without at least partially reverting the change
>>> and going back to the GCC 10 way of things for the affected subset
>>> of calls (just memcpy and memmove), the attached patch enhances
>>> the #pragma GCC diagnostic machinery to consider not just a single
>>> location for inlined code but all locations at which an expression
>>> and its callers are inlined all the way up the stack.  This gives
>>> each author of a function involved in inlining the ability to
>>> control a warning issued for the code, not just the user into whose
>>> code all the calls end up inlined.  To resolve PR 98465, it lets us
>>> suppress the false positives selectively in std::string rather
>>> than across the board in GCC.
> 
> I like the idea of checking the whole of the inlining stack for
> pragmas, but I don't like the way the patch implements it.
> 
> The patch provides a hook for getting a vec of locations for a
> diagnostic for use when checking for pragmas, and uses it the hook on a
> few specific diagnostics.
> 
> Why wouldn’t we always do this?  It seems to me like something we
> should always do when there's inlining information associated with a
> location, rather than being a per-diagnostic thing - but maybe there's
> something I'm missing here.  The patch adds diag_inlining_context
> instances on the stack in various places, and doing that feels to me
> like a special-case hack, when it should be fixed more generally in
> diagnostics.c
> 
> I don't like attaching the "override the location" hook to the
> diagnostic_metadata; I intended the latter to be about diagnostic
> taxonomies (CWE, coding standards, etc), rather than a place to stash
> location overrides.
> 
> One issue is that the core of the diagnostics subsystem doesn't have
> knowledge of "tree", but the inlining information requires tree-ish
> knowledge.
> 
> It's still possible to get at the inlining information from the
> diagnostics.c, but only as a void *:
> 
> input.h's has:
> 
> #define LOCATION_BLOCK(LOC) \
>    ((tree) ((IS_ADHOC_LOC (LOC)) ? get_data_from_adhoc_loc (line_table,
> (LOC)) \
>     : NULL))
> 
> Without knowing about "tree", diagnostic.c could still query a
> location_t to get at the data as a void *:
> 
>    if (IS_ADHOC_LOC (loc)
>      return get_data_from_adhoc_loc (line_table, loc);
>    else
>      return NULL;
> 
> 
> If we make the "get all the pertinent locations" hook a part of the
> diagnostic_context, we could have diagnostic_report_diagnostic check to
> see if there's ad-hoc data associated with the location and a non-NULL
> hook on the context, and if so, call it.  This avoids adding an
> indirect call for the common case where there isn't any inlining
> information, and lets us stash the implementation of the hook in the
> tree-diagnostic.c, keeping the separation of trees from diagnostic.c
> 
> One design question here is: what if there are multiple pragmas on the
> inlining stack, e.g. explicitly enabling a warning at one place, and
> explicitly ignoring that warning in another?  I don't think it would
> happen in the cases you're interested in, but it seems worth
> considering.  Perhaps the closest place to the user's code "wins".
> 
>>>
>>> The solution is to provide a new pair of overloads for warning
>>> functions that, instead of taking a single location argument, take
>>> a tree node from which the location(s) are determined.  The tree
>>> argument is indirect because the diagnostic machinery doesn't (and
>>> cannot without more intrusive changes) at the moment depend on
>>> the various tree definitions.  A nice feature of these overloads
>>> is that they do away with the need for the %K directive (and in
>>> the future also %G, with another enhancement to accept a gimple*
>>> argument).
> 
> We were chatting about this, and I believe we don't need the new
> overloads or the %K and %G directives: all of the information about
> inlining can be got from the location_t via the line_table (albeit as a
> void *) as seen above.
> 
>    gimple_block (const gimple *g)
> 
> is merely:
> 
>    return LOCATION_BLOCK (g->location);
> 
> and is thus merely looking up the information from the location_t and
> line_table; it doesn't actually use anything else about the gimple
> stmt.
> 
> 
> Does the above make sense?
> 
> Hope this is constructive
> Dave
> 
>>>
>>> This patch depends on the fix for PR 98664 (already approved but
>>> not yet checked in).  I've tested it on x86_64-linux.
>>>
>>> To avoid fallout I tried to keep the changes to a minimum, and
>>> so the design isn't as robust as I'd like it ultimately to be.
>>> I plan to enhance it in stage 1.
>>>
>>> Martin
>>
> 
> 


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 1/4] introduce diagnostic infrastructure changes (PR 98512)
  2021-06-10 23:24     ` [PATCH 0/4] improve warning suppression for inlined functions (PR 98512) Martin Sebor
@ 2021-06-10 23:26       ` Martin Sebor
  2021-06-11 17:04         ` David Malcolm
  2021-06-10 23:27       ` [PATCH 2/4] remove %G and %K from calls in front end and middle end " Martin Sebor
                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 44+ messages in thread
From: Martin Sebor @ 2021-06-10 23:26 UTC (permalink / raw)
  To: David Malcolm, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 198 bytes --]

This diff introduces the diagnostic infrastructure changes to support
controlling warnings at any call site in the inlining stack and printing
the inlining context without the %K and %G directives.

[-- Attachment #2: gcc-98512-1.diff --]
[-- Type: text/x-patch, Size: 12259 bytes --]

Improve warning suppression for inlined functions.

Resolves:
PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at declaration site
PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective in conjunction with alias attribute

gcc/ChangeLog:

	* diagnostic.c (update_inlining_context): New.
	(update_effective_level_from_pragmas): Handle inlining context.
	(diagnostic_report_diagnostic): Same.
	* diagnostic.h (struct diagnostic_info): Add ctor.
	(struct diagnostic_context): Add members.
	* tree-diagnostic.c (get_inlining_locations): New.
	(set_inlining_location): New.
	(tree_diagnostics_defaults): Set new callback pointers.

diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index d58586f2526..d1c8c655f7a 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -991,51 +991,92 @@ print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
   pp_set_prefix (pp, saved_prefix);
 }
 
-/* Update the diag_class of DIAGNOSTIC based on its location
-   relative to any
+/* Update the inlininig context in CONTEXT for a DIAGNOSTIC.  */
+
+static void
+update_inlining_context (diagnostic_context *context,
+			 diagnostic_info *diagnostic)
+{
+  context->ictx.reset ();
+
+  auto &ilocs = context->ictx.ilocs;
+
+  if (context->get_locations_cb)
+    /* Retrieve the locations into which the expression about to be
+       diagnosed has been inlined, including those of all the callers
+       all the way down the inlining stack.  */
+    context->get_locations_cb (context, diagnostic);
+  else
+    {
+      /* When there's no metadata use just the one location provided
+	 by the caller of the diagnostic function.  */
+      location_t loc = diagnostic_location (diagnostic);
+      ilocs.safe_push (loc);
+      context->ictx.allsyslocs = in_system_header_at (loc);
+    }
+}
+
+/* Update the kind of DIAGNOSTIC based on its location(s), including
+   any of those in its inlining context, relative to any
      #pragma GCC diagnostic
    directives recorded within CONTEXT.
 
-   Return the new diag_class of DIAGNOSTIC if it was updated, or
-   DK_UNSPECIFIED otherwise.  */
+   Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
+   otherwise.  */
 
 static diagnostic_t
 update_effective_level_from_pragmas (diagnostic_context *context,
 				     diagnostic_info *diagnostic)
 {
-  diagnostic_t diag_class = DK_UNSPECIFIED;
-
-  if (context->n_classification_history > 0)
+  if (context->ictx.allsyslocs && !context->dc_warn_system_headers)
     {
-      location_t location = diagnostic_location (diagnostic);
+      /* Ignore the diagnostic if all the inlined locations are
+	 in system headers and -Wno-system-headers is in effect.  */
+      diagnostic->kind = DK_IGNORED;
+      return DK_IGNORED;
+    }
+
+  if (context->n_classification_history <= 0)
+    return DK_UNSPECIFIED;
+
+  auto &ilocs = context->ictx.ilocs;
 
+  /* Iterate over the locations, checking the diagnostic disposition
+     for the diagnostic at each.  If it's explicitly set as opposed
+     to unspecified, update the disposition for this instance of
+     the diagnostic and return it.  */
+  for (unsigned idx = 0; idx < ilocs.length (); ++idx)
+    {
       /* FIXME: Stupid search.  Optimize later. */
       for (int i = context->n_classification_history - 1; i >= 0; i --)
 	{
-	  if (linemap_location_before_p
-	      (line_table,
-	       context->classification_history[i].location,
-	       location))
+	  const diagnostic_classification_change_t &hist
+	    = context->classification_history[i];
+
+	  location_t pragloc = hist.location;
+	  if (!linemap_location_before_p (line_table, pragloc, ilocs[idx]))
+	    continue;
+
+	  if (hist.kind == (int) DK_POP)
 	    {
-	      if (context->classification_history[i].kind == (int) DK_POP)
-		{
-		  i = context->classification_history[i].option;
-		  continue;
-		}
-	      int option = context->classification_history[i].option;
-	      /* The option 0 is for all the diagnostics.  */
-	      if (option == 0 || option == diagnostic->option_index)
-		{
-		  diag_class = context->classification_history[i].kind;
-		  if (diag_class != DK_UNSPECIFIED)
-		    diagnostic->kind = diag_class;
-		  break;
-		}
+	      /* Move on to the next region.  */
+	      i = hist.option;
+	      continue;
+	    }
+
+	  int option = hist.option;
+	  /* The option 0 is for all the diagnostics.  */
+	  if (option == 0 || option == diagnostic->option_index)
+	    {
+	      diagnostic_t kind = hist.kind;
+	      if (kind != DK_UNSPECIFIED)
+		diagnostic->kind = kind;
+	      return kind;
 	    }
 	}
     }
 
-  return diag_class;
+  return DK_UNSPECIFIED;
 }
 
 /* Generate a URL string describing CWE.  The caller is responsible for
@@ -1129,6 +1170,9 @@ static bool
 diagnostic_enabled (diagnostic_context *context,
 		    diagnostic_info *diagnostic)
 {
+  /* Update the inlining context for this diagnostic.  */
+  update_inlining_context (context, diagnostic);
+
   /* Diagnostics with no option or -fpermissive are always enabled.  */
   if (!diagnostic->option_index
       || diagnostic->option_index == permissive_error_option (context))
@@ -1194,9 +1238,17 @@ diagnostic_report_diagnostic (diagnostic_context *context,
 
   /* Give preference to being able to inhibit warnings, before they
      get reclassified to something else.  */
-  if ((diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
-      && !diagnostic_report_warnings_p (context, location))
-    return false;
+  bool report_warning_p = true;
+  if (diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
+    {
+      if (context->dc_inhibit_warnings)
+	return false;
+      /* Remember the result of the overall system header warning setting
+	 but proceed to also check the inlining context.  */
+      report_warning_p = diagnostic_report_warnings_p (context, location);
+      if (!report_warning_p && diagnostic->kind == DK_PEDWARN)
+	return false;
+    }
 
   if (diagnostic->kind == DK_PEDWARN)
     {
@@ -1204,7 +1256,7 @@ diagnostic_report_diagnostic (diagnostic_context *context,
       /* We do this to avoid giving the message for -pedantic-errors.  */
       orig_diag_kind = diagnostic->kind;
     }
- 
+
   if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
     return false;
 
@@ -1228,9 +1280,17 @@ diagnostic_report_diagnostic (diagnostic_context *context,
       && diagnostic->kind == DK_WARNING)
     diagnostic->kind = DK_ERROR;
 
+  /* Check to see if the diagnostic is enabled at the location and
+     not disabled by #pragma GCC diagnostic anywhere along the inlining
+     stack.  .  */
   if (!diagnostic_enabled (context, diagnostic))
     return false;
 
+  if (!report_warning_p && context->ictx.allsyslocs)
+    /* Bail if the warning is not to be reported because all locations
+       in the inlining stack (if there is one) are in system headers.  */
+    return false;
+
   if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
     diagnostic_check_max_errors (context);
 
@@ -1270,8 +1330,14 @@ diagnostic_report_diagnostic (diagnostic_context *context,
     }
   context->diagnostic_group_emission_count++;
 
+  /* Move X_DATA into DIAGNOSTIC->MESSAGE before setting inlining context
+     abstract origin and location.  It uses X_DATA.  */
   diagnostic->message.x_data = &diagnostic->x_data;
   diagnostic->x_data = NULL;
+
+  if (context->set_location_cb)
+    context->set_location_cb (context, diagnostic);
+
   pp_format (context->printer, &diagnostic->message);
   (*diagnostic_starter (context)) (context, diagnostic);
   pp_output_formatted_text (context->printer);
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 1b9d6b1f64d..b95ee23dda0 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -87,6 +87,10 @@ enum diagnostics_extra_output_kind
    list in diagnostic.def.  */
 struct diagnostic_info
 {
+  diagnostic_info ()
+    : message (), richloc (), metadata (), x_data (), kind (), option_index ()
+  { }
+
   /* Text to be formatted.  */
   text_info message;
 
@@ -343,6 +347,32 @@ struct diagnostic_context
 
   /* Callback for final cleanup.  */
   void (*final_cb) (diagnostic_context *context);
+
+  /* The inlining context of the diagnostic (may have just one
+     element if a diagnostic is not for an inlined expression).  */
+  struct inlining_ctx
+  {
+    void reset ()
+    {
+      ilocs.release ();
+      loc = UNKNOWN_LOCATION;
+      ao = NULL;
+      allsyslocs = false;
+    }
+
+    /* Locations along the inlining stack.  */
+    auto_vec<location_t, 8> ilocs;
+    /* The locus of the diagnostic. */
+    location_t loc;
+    /* The abstract origin of the location.  */
+    void *ao;
+    /* Set of every ILOCS element is in a system header.  */
+    bool allsyslocs;
+  } ictx;
+
+  /* Callbacks to get and set the inlining context.  */
+  void (*get_locations_cb)(diagnostic_context *, diagnostic_info *);
+  void (*set_location_cb)(const diagnostic_context *, diagnostic_info *);
 };
 
 static inline void
diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
index 95b8ef30070..a8c5484849a 100644
--- a/gcc/tree-diagnostic.c
+++ b/gcc/tree-diagnostic.c
@@ -305,6 +305,84 @@ default_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
   return true;
 }
 
+/* Get the inlining stack corresponding to the DIAGNOSTIC location.  */
+
+static void
+get_inlining_locations (diagnostic_context *context,
+			diagnostic_info *diagnostic)
+{
+  context->ictx.reset ();
+
+  location_t loc = diagnostic_location (diagnostic);
+  tree block = LOCATION_BLOCK (loc);
+
+  /* Count the number of locations in system headers.  When all are,
+     warnings are suppressed by -Wno-system-headers.  Otherwise, they
+     involve some user code, possibly inlined into a function in a system
+     header, and are not treated as coming from system headers.  */
+  unsigned nsyslocs = 0;
+
+  while (block && TREE_CODE (block) == BLOCK
+	 && BLOCK_ABSTRACT_ORIGIN (block))
+    {
+      tree ao = BLOCK_ABSTRACT_ORIGIN (block);
+      if (TREE_CODE (ao) == FUNCTION_DECL)
+	{
+	  if (!context->ictx.ao)
+	    context->ictx.ao = block;
+
+	  location_t loc = BLOCK_SOURCE_LOCATION (block);
+	  context->ictx.ilocs.safe_push (loc);
+	  if (in_system_header_at (loc))
+	    ++nsyslocs;
+	}
+      else if (TREE_CODE (ao) != BLOCK)
+	break;
+
+      block = BLOCK_SUPERCONTEXT (block);
+    }
+
+  if (context->ictx.ilocs.length ())
+    {
+      /* When there is an inlining context use the macro expansion
+	 location for the original location and bump up NSYSLOCS if
+	 it's in a system header since it's not counted above.  */
+      context->ictx.loc = expansion_point_location_if_in_system_header (loc);
+      if (context->ictx.loc != loc)
+	++nsyslocs;
+    }
+  else
+    {
+      /* When there's no inlining context use the original location
+	 and set NSYSLOCS accordingly.  */
+      context->ictx.loc = loc;
+      nsyslocs = in_system_header_at (loc) != 0;
+    }
+
+  context->ictx.ilocs.safe_push (context->ictx.loc);
+
+  /* Set if all locations are in a system header.  */
+  context->ictx.allsyslocs = nsyslocs == context->ictx.ilocs.length ();;
+}
+
+/* Set the inlining location for to the DIAGNOSTIC based on the saved
+   inlining context.  */
+
+static void
+set_inlining_location (const diagnostic_context *context,
+		       diagnostic_info *diagnostic)
+{
+  if (!pp_ti_abstract_origin (&diagnostic->message)
+      || !context->ictx.ao
+      || context->ictx.loc == UNKNOWN_LOCATION)
+    /* Do nothing when there's no inlining context.  */
+    return;
+
+  *pp_ti_abstract_origin (&diagnostic->message) = (tree)context->ictx.ao;
+  diagnostic->message.set_location (0, context->ictx.loc,
+				    SHOW_RANGE_WITH_CARET);
+}
+
 /* Sets CONTEXT to use language independent diagnostics.  */
 void
 tree_diagnostics_defaults (diagnostic_context *context)
@@ -314,4 +392,6 @@ tree_diagnostics_defaults (diagnostic_context *context)
   diagnostic_format_decoder (context) = default_tree_printer;
   context->print_path = default_tree_diagnostic_path_printer;
   context->make_json_for_path = default_tree_make_json_for_path;
+  context->get_locations_cb = get_inlining_locations;
+  context->set_location_cb = set_inlining_location;
 }

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 2/4] remove %G and %K from calls in front end and middle end (PR 98512)
  2021-06-10 23:24     ` [PATCH 0/4] improve warning suppression for inlined functions (PR 98512) Martin Sebor
  2021-06-10 23:26       ` [PATCH 1/4] introduce diagnostic infrastructure changes " Martin Sebor
@ 2021-06-10 23:27       ` Martin Sebor
  2021-06-30 15:39         ` [PING][PATCH " Martin Sebor
  2021-06-10 23:28       ` [PATCH 3/4] remove %K from error() calls in the aarch64/arm back ends " Martin Sebor
  2021-06-10 23:30       ` [PATCH 4/4] remove %G and %K support from pretty printer and -Wformat " Martin Sebor
  3 siblings, 1 reply; 44+ messages in thread
From: Martin Sebor @ 2021-06-10 23:27 UTC (permalink / raw)
  To: David Malcolm, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 187 bytes --]

This diff removes the uses of %G and %K from all warning_at() calls
throughout GCC front end and middle end.  The inlining context is
included in diagnostic output whenever it's present.

[-- Attachment #2: gcc-98512-2.diff --]
[-- Type: text/x-patch, Size: 83887 bytes --]

Improve warning suppression for inlined functions.

Resolves:
PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at declaration site
PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective in conjunction with alias attribute

gcc/ChangeLog:

	* builtins.c (warn_string_no_nul): Remove %G.
	(maybe_warn_for_bound): Same.
	(warn_for_access): Same.
	(check_access): Same.
	(check_strncat_sizes): Same.
	(expand_builtin_strncat): Same.
	(expand_builtin_strncmp): Same.
	(expand_builtin): Same.
	(expand_builtin_object_size): Same.
	(warn_dealloc_offset): Same.
	(maybe_emit_free_warning): Same.
	* calls.c (maybe_warn_alloc_args_overflow): Same.
	(maybe_warn_nonstring_arg): Same.
	(maybe_warn_rdwr_sizes): Same.
	* expr.c (expand_expr_real_1): Remove %K.
	* gimple-fold.c (gimple_fold_builtin_strncpy): Remove %G.
	(gimple_fold_builtin_strncat): Same.
	* gimple-ssa-sprintf.c (format_directive): Same.
	(handle_printf_call): Same.
	* gimple-ssa-warn-alloca.c (pass_walloca::execute): Same.
	* gimple-ssa-warn-restrict.c (maybe_diag_overlap): Same.
	(maybe_diag_access_bounds): Same.  Call gimple_location.
	(check_bounds_or_overlap): Same.
	* trans-mem.c (ipa_tm_scan_irr_block): Remove %K.  Simplify.
	* tree-ssa-ccp.c (pass_post_ipa_warn::execute): Remove %G.
	* tree-ssa-strlen.c (maybe_warn_overflow): Same.
	(maybe_diag_stxncpy_trunc): Same.
	(handle_builtin_stxncpy_strncat): Same.
	(maybe_warn_pointless_strcmp): Same.
	* tree-ssa-uninit.c (maybe_warn_operand): Same.

gcc/testsuite/ChangeLog:

	* gcc.dg/Wfree-nonheap-object-4.c: Tighten up.
	* gcc.dg/Wobjsize-1.c: Prune expected output.
	* gcc.dg/Warray-bounds-71.c: New test.
	* gcc.dg/Warray-bounds-71.h: New test.
	* gcc.dg/Warray-bounds-72.c: New test.
	* gcc.dg/Warray-bounds-73.c: New test.
	* gcc.dg/Warray-bounds-74.c: New test.
	* gcc.dg/Warray-bounds-75.c: New test.
	* gcc.dg/Wfree-nonheap-object-5.c: New test.
	* gcc.dg/pragma-diag-10.c: New test.
	* gcc.dg/pragma-diag-9.c: New test.
	* gcc.dg/uninit-suppress_3.c: New test.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index af1fe49bb48..96997b7edc8 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -1124,30 +1124,30 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
 	{
 	  if (wi::ltu_p (maxsiz, bndrng[0]))
 	    warned = warning_at (loc, OPT_Wstringop_overread,
-				 "%K%qD specified bound %s exceeds "
+				 "%qD specified bound %s exceeds "
 				 "maximum object size %E",
-				 expr, func, bndstr, maxobjsize);
+				 func, bndstr, maxobjsize);
 	  else
 	    {
 	      bool maybe = wi::to_wide (size) == bndrng[0];
 	      warned = warning_at (loc, OPT_Wstringop_overread,
 				   exact
-				   ? G_("%K%qD specified bound %s exceeds "
+				   ? G_("%qD specified bound %s exceeds "
 					"the size %E of unterminated array")
 				   : (maybe
-				      ? G_("%K%qD specified bound %s may "
+				      ? G_("%qD specified bound %s may "
 					   "exceed the size of at most %E "
 					   "of unterminated array")
-				      : G_("%K%qD specified bound %s exceeds "
+				      : G_("%qD specified bound %s exceeds "
 					   "the size of at most %E "
 					   "of unterminated array")),
-				   expr, func, bndstr, size);
+				   func, bndstr, size);
 	    }
 	}
       else
 	warned = warning_at (loc, OPT_Wstringop_overread,
-			     "%K%qD argument missing terminating nul",
-			     expr, func);
+			     "%qD argument missing terminating nul",
+			     func);
     }
   else
     {
@@ -3967,35 +3967,34 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
 	    warned = (func
 		      ? warning_at (loc, opt,
 				    (maybe
-				     ? G_("%K%qD specified bound %E may "
+				     ? G_("%qD specified bound %E may "
 					  "exceed maximum object size %E")
-				     : G_("%K%qD specified bound %E "
+				     : G_("%qD specified bound %E "
 					  "exceeds maximum object size %E")),
-				    exp, func, bndrng[0], maxobjsize)
+				    func, bndrng[0], maxobjsize)
 		      : warning_at (loc, opt,
 				    (maybe
-				     ? G_("%Kspecified bound %E may "
+				     ? G_("specified bound %E may "
 					  "exceed maximum object size %E")
-				     : G_("%Kspecified bound %E "
+				     : G_("specified bound %E "
 					  "exceeds maximum object size %E")),
-				    exp, bndrng[0], maxobjsize));
+				    bndrng[0], maxobjsize));
 	  else
 	    warned = (func
 		      ? warning_at (loc, opt,
 				    (maybe
-				     ? G_("%K%qD specified bound [%E, %E] may "
+				     ? G_("%qD specified bound [%E, %E] may "
 					  "exceed maximum object size %E")
-				     : G_("%K%qD specified bound [%E, %E] "
+				     : G_("%qD specified bound [%E, %E] "
 					  "exceeds maximum object size %E")),
-				    exp, func,
-				    bndrng[0], bndrng[1], maxobjsize)
+				    func, bndrng[0], bndrng[1], maxobjsize)
 		      : warning_at (loc, opt,
 				    (maybe
-				     ? G_("%Kspecified bound [%E, %E] may "
+				     ? G_("specified bound [%E, %E] may "
 					  "exceed maximum object size %E")
-				     : G_("%Kspecified bound [%E, %E] "
+				     : G_("specified bound [%E, %E] "
 					  "exceeds maximum object size %E")),
-				    exp, bndrng[0], bndrng[1], maxobjsize));
+				    bndrng[0], bndrng[1], maxobjsize));
 	}
       else if (!size || tree_int_cst_le (bndrng[0], size))
 	return false;
@@ -4003,34 +4002,34 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD specified bound %E may exceed "
+				 ? G_("%qD specified bound %E may exceed "
 				      "source size %E")
-				 : G_("%K%qD specified bound %E exceeds "
+				 : G_("%qD specified bound %E exceeds "
 				      "source size %E")),
-				exp, func, bndrng[0], size)
+				func, bndrng[0], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kspecified bound %E may exceed "
+				 ? G_("specified bound %E may exceed "
 				      "source size %E")
-				 : G_("%Kspecified bound %E exceeds "
+				 : G_("specified bound %E exceeds "
 				      "source size %E")),
-				exp, bndrng[0], size));
+				bndrng[0], size));
       else
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD specified bound [%E, %E] may "
+				 ? G_("%qD specified bound [%E, %E] may "
 				      "exceed source size %E")
-				 : G_("%K%qD specified bound [%E, %E] exceeds "
+				 : G_("%qD specified bound [%E, %E] exceeds "
 				      "source size %E")),
-				exp, func, bndrng[0], bndrng[1], size)
+				func, bndrng[0], bndrng[1], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kspecified bound [%E, %E] may exceed "
+				 ? G_("specified bound [%E, %E] may exceed "
 				      "source size %E")
-				 : G_("%Kspecified bound [%E, %E] exceeds "
+				 : G_("specified bound [%E, %E] exceeds "
 				      "source size %E")),
-				exp, bndrng[0], bndrng[1], size));
+				bndrng[0], bndrng[1], size));
       if (warned)
 	{
 	  if (pad && pad->src.ref)
@@ -4055,35 +4054,34 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD specified size %E may "
+				 ? G_("%qD specified size %E may "
 				      "exceed maximum object size %E")
-				 : G_("%K%qD specified size %E "
+				 : G_("%qD specified size %E "
 				      "exceeds maximum object size %E")),
-				exp, func, bndrng[0], maxobjsize)
+				func, bndrng[0], maxobjsize)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kspecified size %E may exceed "
+				 ? G_("specified size %E may exceed "
 				      "maximum object size %E")
-				 : G_("%Kspecified size %E exceeds "
+				 : G_("specified size %E exceeds "
 				      "maximum object size %E")),
-				exp, bndrng[0], maxobjsize));
+				bndrng[0], maxobjsize));
       else
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD specified size between %E and %E "
+				 ? G_("%qD specified size between %E and %E "
 				      "may exceed maximum object size %E")
-				 : G_("%K%qD specified size between %E and %E "
+				 : G_("%qD specified size between %E and %E "
 				      "exceeds maximum object size %E")),
-				exp, func,
-				bndrng[0], bndrng[1], maxobjsize)
+				func, bndrng[0], bndrng[1], maxobjsize)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kspecified size between %E and %E "
+				 ? G_("specified size between %E and %E "
 				      "may exceed maximum object size %E")
-				 : G_("%Kspecified size between %E and %E "
+				 : G_("specified size between %E and %E "
 				      "exceeds maximum object size %E")),
-				exp, bndrng[0], bndrng[1], maxobjsize));
+				bndrng[0], bndrng[1], maxobjsize));
     }
   else if (!size || tree_int_cst_le (bndrng[0], size))
     return false;
@@ -4091,34 +4089,34 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
     warned = (func
 	      ? warning_at (loc, OPT_Wstringop_overflow_,
 			    (maybe
-			     ? G_("%K%qD specified bound %E may exceed "
+			     ? G_("%qD specified bound %E may exceed "
 				  "destination size %E")
-			     : G_("%K%qD specified bound %E exceeds "
+			     : G_("%qD specified bound %E exceeds "
 				  "destination size %E")),
-			    exp, func, bndrng[0], size)
+			    func, bndrng[0], size)
 	      : warning_at (loc, OPT_Wstringop_overflow_,
 			    (maybe
-			     ? G_("%Kspecified bound %E may exceed "
+			     ? G_("specified bound %E may exceed "
 				  "destination size %E")
-			     : G_("%Kspecified bound %E exceeds "
+			     : G_("specified bound %E exceeds "
 				  "destination size %E")),
-			    exp, bndrng[0], size));
+			    bndrng[0], size));
   else
     warned = (func
 	      ? warning_at (loc, OPT_Wstringop_overflow_,
 			    (maybe
-			     ? G_("%K%qD specified bound [%E, %E] may exceed "
+			     ? G_("%qD specified bound [%E, %E] may exceed "
 				  "destination size %E")
-			     : G_("%K%qD specified bound [%E, %E] exceeds "
+			     : G_("%qD specified bound [%E, %E] exceeds "
 				  "destination size %E")),
-			    exp, func, bndrng[0], bndrng[1], size)
+			    func, bndrng[0], bndrng[1], size)
 	      : warning_at (loc, OPT_Wstringop_overflow_,
 			    (maybe
-			     ? G_("%Kspecified bound [%E, %E] exceeds "
+			     ? G_("specified bound [%E, %E] exceeds "
 				  "destination size %E")
-			     : G_("%Kspecified bound [%E, %E] exceeds "
+			     : G_("specified bound [%E, %E] exceeds "
 				  "destination size %E")),
-			    exp, bndrng[0], bndrng[1], size));
+			    bndrng[0], bndrng[1], size));
 
   if (warned)
     {
@@ -4156,65 +4154,63 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
 	warned = (func
 		  ? warning_n (loc, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%K%qD may access %E byte in a region "
+				? G_("%qD may access %E byte in a region "
 				     "of size %E")
-				: G_("%K%qD accessing %E byte in a region "
+				: G_("%qD accessing %E byte in a region "
 				     "of size %E")),
 				(maybe
-				 ? G_ ("%K%qD may access %E bytes in a region "
+				 ? G_ ("%qD may access %E bytes in a region "
 				       "of size %E")
-				 : G_ ("%K%qD accessing %E bytes in a region "
+				 : G_ ("%qD accessing %E bytes in a region "
 				       "of size %E")),
-			       exp, func, range[0], size)
+			       func, range[0], size)
 		  : warning_n (loc, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%Kmay access %E byte in a region "
+				? G_("may access %E byte in a region "
 				     "of size %E")
-				: G_("%Kaccessing %E byte in a region "
+				: G_("accessing %E byte in a region "
 				     "of size %E")),
 			       (maybe
-				? G_("%Kmay access %E bytes in a region "
+				? G_("may access %E bytes in a region "
 				     "of size %E")
-				: G_("%Kaccessing %E bytes in a region "
+				: G_("accessing %E bytes in a region "
 				     "of size %E")),
-			       exp, range[0], size));
+			       range[0], size));
       else if (tree_int_cst_sign_bit (range[1]))
 	{
 	  /* Avoid printing the upper bound if it's invalid.  */
 	  warned = (func
 		    ? warning_at (loc, opt,
 				  (maybe
-				   ? G_("%K%qD may access %E or more bytes "
+				   ? G_("%qD may access %E or more bytes "
 					"in a region of size %E")
-				   : G_("%K%qD accessing %E or more bytes "
+				   : G_("%qD accessing %E or more bytes "
 					"in a region of size %E")),
-				  exp, func, range[0], size)
+				  func, range[0], size)
 		    : warning_at (loc, opt,
 				  (maybe
-				   ? G_("%Kmay access %E or more bytes "
+				   ? G_("may access %E or more bytes "
 					"in a region of size %E")
-				   : G_("%Kaccessing %E or more bytes "
+				   : G_("accessing %E or more bytes "
 					"in a region of size %E")),
-				  exp, range[0], size));
+				  range[0], size));
 	}
       else
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD may access between %E and %E "
+				 ? G_("%qD may access between %E and %E "
 				      "bytes in a region of size %E")
-				 : G_("%K%qD accessing between %E and %E "
+				 : G_("%qD accessing between %E and %E "
 				      "bytes in a region of size %E")),
-				exp, func, range[0], range[1],
-				size)
+				func, range[0], range[1], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kmay access between %E and %E bytes "
+				 ? G_("may access between %E and %E bytes "
 				      "in a region of size %E")
-				 : G_("%Kaccessing between %E and %E bytes "
+				 : G_("accessing between %E and %E bytes "
 				      "in a region of size %E")),
-				exp, range[0], range[1],
-				size));
+				range[0], range[1], size));
       return warned;
     }
 
@@ -4224,69 +4220,67 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
 	warned = (func
 		  ? warning_n (loc, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%K%qD may write %E byte into a region "
+				? G_("%qD may write %E byte into a region "
 				     "of size %E")
-				: G_("%K%qD writing %E byte into a region "
+				: G_("%qD writing %E byte into a region "
 				     "of size %E overflows the destination")),
 			       (maybe
-				? G_("%K%qD may write %E bytes into a region "
+				? G_("%qD may write %E bytes into a region "
 				     "of size %E")
-				: G_("%K%qD writing %E bytes into a region "
+				: G_("%qD writing %E bytes into a region "
 				     "of size %E overflows the destination")),
-			       exp, func, range[0], size)
+			       func, range[0], size)
 		  : warning_n (loc, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%Kmay write %E byte into a region "
+				? G_("may write %E byte into a region "
 				     "of size %E")
-				: G_("%Kwriting %E byte into a region "
+				: G_("writing %E byte into a region "
 				     "of size %E overflows the destination")),
 			       (maybe
-				? G_("%Kmay write %E bytes into a region "
+				? G_("may write %E bytes into a region "
 				     "of size %E")
-				: G_("%Kwriting %E bytes into a region "
+				: G_("writing %E bytes into a region "
 				     "of size %E overflows the destination")),
-			       exp, range[0], size));
+			       range[0], size));
       else if (tree_int_cst_sign_bit (range[1]))
 	{
 	  /* Avoid printing the upper bound if it's invalid.  */
 	  warned = (func
 		    ? warning_at (loc, opt,
 				  (maybe
-				   ? G_("%K%qD may write %E or more bytes "
+				   ? G_("%qD may write %E or more bytes "
 					"into a region of size %E")
-				   : G_("%K%qD writing %E or more bytes "
+				   : G_("%qD writing %E or more bytes "
 					"into a region of size %E overflows "
 					"the destination")),
-				  exp, func, range[0], size)
+				  func, range[0], size)
 		    : warning_at (loc, opt,
 				  (maybe
-				   ? G_("%Kmay write %E or more bytes into "
+				   ? G_("may write %E or more bytes into "
 					"a region of size %E")
-				   : G_("%Kwriting %E or more bytes into "
+				   : G_("writing %E or more bytes into "
 					"a region of size %E overflows "
 					"the destination")),
-				  exp, range[0], size));
+				  range[0], size));
 	}
       else
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD may write between %E and %E bytes "
+				 ? G_("%qD may write between %E and %E bytes "
 				      "into a region of size %E")
-				 : G_("%K%qD writing between %E and %E bytes "
+				 : G_("%qD writing between %E and %E bytes "
 				      "into a region of size %E overflows "
 				      "the destination")),
-				exp, func, range[0], range[1],
-				size)
+				func, range[0], range[1], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kmay write between %E and %E bytes "
+				 ? G_("may write between %E and %E bytes "
 				      "into a region of size %E")
-				 : G_("%Kwriting between %E and %E bytes "
+				 : G_("writing between %E and %E bytes "
 				      "into a region of size %E overflows "
 				      "the destination")),
-				exp, range[0], range[1],
-				size));
+				range[0], range[1], size));
       return warned;
     }
 
@@ -4297,64 +4291,64 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
 		  ? warning_n (loc, OPT_Wstringop_overread,
 			       tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%K%qD may read %E byte from a region "
+				? G_("%qD may read %E byte from a region "
 				     "of size %E")
-				: G_("%K%qD reading %E byte from a region "
+				: G_("%qD reading %E byte from a region "
 				     "of size %E")),
 			       (maybe
-				? G_("%K%qD may read %E bytes from a region "
+				? G_("%qD may read %E bytes from a region "
 				     "of size %E")
-				: G_("%K%qD reading %E bytes from a region "
+				: G_("%qD reading %E bytes from a region "
 				     "of size %E")),
-			       exp, func, range[0], size)
+			       func, range[0], size)
 		  : warning_n (loc, OPT_Wstringop_overread,
 			       tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%Kmay read %E byte from a region "
+				? G_("may read %E byte from a region "
 				     "of size %E")
-				: G_("%Kreading %E byte from a region "
+				: G_("reading %E byte from a region "
 				     "of size %E")),
 			       (maybe
-				? G_("%Kmay read %E bytes from a region "
+				? G_("may read %E bytes from a region "
 				     "of size %E")
-				: G_("%Kreading %E bytes from a region "
+				: G_("reading %E bytes from a region "
 				     "of size %E")),
-			       exp, range[0], size));
+			       range[0], size));
       else if (tree_int_cst_sign_bit (range[1]))
 	{
 	  /* Avoid printing the upper bound if it's invalid.  */
 	  warned = (func
 		    ? warning_at (loc, OPT_Wstringop_overread,
 				  (maybe
-				   ? G_("%K%qD may read %E or more bytes "
+				   ? G_("%qD may read %E or more bytes "
 					"from a region of size %E")
-				   : G_("%K%qD reading %E or more bytes "
+				   : G_("%qD reading %E or more bytes "
 					"from a region of size %E")),
-				  exp, func, range[0], size)
+				  func, range[0], size)
 		    : warning_at (loc, OPT_Wstringop_overread,
 				  (maybe
-				   ? G_("%Kmay read %E or more bytes "
+				   ? G_("may read %E or more bytes "
 					"from a region of size %E")
-				   : G_("%Kreading %E or more bytes "
+				   : G_("reading %E or more bytes "
 					"from a region of size %E")),
-				  exp, range[0], size));
+				  range[0], size));
 	}
       else
 	warned = (func
 		  ? warning_at (loc, OPT_Wstringop_overread,
 				(maybe
-				 ? G_("%K%qD may read between %E and %E bytes "
+				 ? G_("%qD may read between %E and %E bytes "
 				      "from a region of size %E")
-				 : G_("%K%qD reading between %E and %E bytes "
+				 : G_("%qD reading between %E and %E bytes "
 				      "from a region of size %E")),
-				exp, func, range[0], range[1], size)
+				func, range[0], range[1], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kmay read between %E and %E bytes "
+				 ? G_("may read between %E and %E bytes "
 				      "from a region of size %E")
-				 : G_("%Kreading between %E and %E bytes "
+				 : G_("reading between %E and %E bytes "
 				      "from a region of size %E")),
-				exp, range[0], range[1], size));
+				range[0], range[1], size));
 
       if (warned)
 	TREE_NO_WARNING (exp) = true;
@@ -4367,37 +4361,37 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
     warned = (func
 	      ? warning_n (loc, OPT_Wstringop_overread,
 			   tree_to_uhwi (range[0]),
-			   "%K%qD expecting %E byte in a region of size %E",
-			   "%K%qD expecting %E bytes in a region of size %E",
-			   exp, func, range[0], size)
+			   "%qD expecting %E byte in a region of size %E",
+			   "%qD expecting %E bytes in a region of size %E",
+			   func, range[0], size)
 	      : warning_n (loc, OPT_Wstringop_overread,
 			   tree_to_uhwi (range[0]),
-			   "%Kexpecting %E byte in a region of size %E",
-			   "%Kexpecting %E bytes in a region of size %E",
-			   exp, range[0], size));
+			   "expecting %E byte in a region of size %E",
+			   "expecting %E bytes in a region of size %E",
+			   range[0], size));
   else if (tree_int_cst_sign_bit (range[1]))
     {
       /* Avoid printing the upper bound if it's invalid.  */
       warned = (func
 		? warning_at (loc, OPT_Wstringop_overread,
-			      "%K%qD expecting %E or more bytes in a region "
+			      "%qD expecting %E or more bytes in a region "
 			      "of size %E",
-			      exp, func, range[0], size)
+			      func, range[0], size)
 		: warning_at (loc, OPT_Wstringop_overread,
-			      "%Kexpecting %E or more bytes in a region "
+			      "expecting %E or more bytes in a region "
 			      "of size %E",
-			      exp, range[0], size));
+			      range[0], size));
     }
   else
     warned = (func
 	      ? warning_at (loc, OPT_Wstringop_overread,
-			    "%K%qD expecting between %E and %E bytes in "
+			    "%qD expecting between %E and %E bytes in "
 			    "a region of size %E",
-			    exp, func, range[0], range[1], size)
+			    func, range[0], range[1], size)
 	      : warning_at (loc, OPT_Wstringop_overread,
-			    "%Kexpecting between %E and %E bytes in "
+			    "expecting between %E and %E bytes in "
 			    "a region of size %E",
-			    exp, range[0], range[1], size));
+			    range[0], range[1], size));
 
   if (warned)
     TREE_NO_WARNING (exp) = true;
@@ -4757,7 +4751,7 @@ check_access (tree exp, tree dstwrite,
       && TREE_CODE (range[0]) == INTEGER_CST
       && tree_int_cst_lt (maxobjsize, range[0]))
     {
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       maybe_warn_for_bound (OPT_Wstringop_overflow_, loc, exp, func, range,
 			    NULL_TREE, pad);
       return false;
@@ -4783,7 +4777,7 @@ check_access (tree exp, tree dstwrite,
 	      || (pad && pad->dst.ref && TREE_NO_WARNING (pad->dst.ref)))
 	    return false;
 
-	  location_t loc = tree_inlined_location (exp);
+	  location_t loc = EXPR_LOCATION (exp);
 	  bool warned = false;
 	  if (dstwrite == slen && at_least_one)
 	    {
@@ -4792,15 +4786,15 @@ check_access (tree exp, tree dstwrite,
 		 at least one byte past the end of the destination.  */
 	      warned = (func
 			? warning_at (loc, OPT_Wstringop_overflow_,
-				      "%K%qD writing %E or more bytes into "
+				      "%qD writing %E or more bytes into "
 				      "a region of size %E overflows "
 				      "the destination",
-				      exp, func, range[0], dstsize)
+				      func, range[0], dstsize)
 			: warning_at (loc, OPT_Wstringop_overflow_,
-				      "%Kwriting %E or more bytes into "
+				      "writing %E or more bytes into "
 				      "a region of size %E overflows "
 				      "the destination",
-				      exp, range[0], dstsize));
+				      range[0], dstsize));
 	    }
 	  else
 	    {
@@ -4836,7 +4830,7 @@ check_access (tree exp, tree dstwrite,
 	 PAD is nonnull and BNDRNG is valid.  */
       get_size_range (maxread, range, pad ? pad->src.bndrng : NULL);
 
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       tree size = dstsize;
       if (pad && pad->mode == access_read_only)
 	size = wide_int_to_tree (sizetype, pad->src.sizrng[1]);
@@ -4895,7 +4889,7 @@ check_access (tree exp, tree dstwrite,
 	  || (pad && pad->src.ref && TREE_NO_WARNING (pad->src.ref)))
 	return false;
 
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       const bool read
 	= mode == access_read_only || mode == access_read_write;
       const bool maybe = pad && pad->dst.parmarray;
@@ -6440,10 +6434,10 @@ check_strncat_sizes (tree exp, tree objsize)
   if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (objsize)
       && tree_int_cst_equal (objsize, maxread))
     {
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       warning_at (loc, OPT_Wstringop_overflow_,
-		  "%K%qD specified bound %E equals destination size",
-		  exp, get_callee_fndecl (exp), maxread);
+		  "%qD specified bound %E equals destination size",
+		  get_callee_fndecl (exp), maxread);
 
       return false;
     }
@@ -6513,10 +6507,10 @@ expand_builtin_strncat (tree exp, rtx)
   if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (destsize)
       && tree_int_cst_equal (destsize, maxread))
     {
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       warning_at (loc, OPT_Wstringop_overflow_,
-		  "%K%qD specified bound %E equals destination size",
-		  exp, get_callee_fndecl (exp), maxread);
+		  "%qD specified bound %E equals destination size",
+		  get_callee_fndecl (exp), maxread);
 
       return NULL_RTX;
     }
@@ -7289,7 +7283,7 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
       || !check_nul_terminated_array (exp, arg2, arg3))
     return NULL_RTX;
 
-  location_t loc = tree_inlined_location (exp);
+  location_t loc = EXPR_LOCATION (exp);
   tree len1 = c_strlen (arg1, 1);
   tree len2 = c_strlen (arg2, 1);
 
@@ -9966,13 +9960,13 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
     case BUILT_IN_VA_ARG_PACK:
       /* All valid uses of __builtin_va_arg_pack () are removed during
 	 inlining.  */
-      error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
+      error ("invalid use of %<__builtin_va_arg_pack ()%>");
       return const0_rtx;
 
     case BUILT_IN_VA_ARG_PACK_LEN:
       /* All valid uses of __builtin_va_arg_pack_len () are removed during
 	 inlining.  */
-      error ("%Kinvalid use of %<__builtin_va_arg_pack_len ()%>", exp);
+      error ("invalid use of %<__builtin_va_arg_pack_len ()%>");
       return const0_rtx;
 
       /* Return the address of the first anonymous stack arg.  */
@@ -12921,8 +12915,8 @@ expand_builtin_object_size (tree exp)
 
   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
     {
-      error ("%Kfirst argument of %qD must be a pointer, second integer constant",
-	     exp, fndecl);
+      error ("first argument of %qD must be a pointer, second integer constant",
+	     fndecl);
       expand_builtin_trap ();
       return const0_rtx;
     }
@@ -12934,8 +12928,8 @@ expand_builtin_object_size (tree exp)
       || tree_int_cst_sgn (ost) < 0
       || compare_tree_int (ost, 3) > 0)
     {
-      error ("%Klast argument of %qD is not integer constant between 0 and 3",
-	     exp, fndecl);
+      error ("last argument of %qD is not integer constant between 0 and 3",
+	      fndecl);
       expand_builtin_trap ();
       return const0_rtx;
     }
@@ -13737,8 +13731,8 @@ warn_dealloc_offset (location_t loc, tree exp, const access_ref &aref)
     }
 
   if (!warning_at (loc, OPT_Wfree_nonheap_object,
-		   "%K%qD called on pointer %qE with nonzero offset%s",
-		   exp, dealloc_decl, aref.ref, offstr))
+		   "%qD called on pointer %qE with nonzero offset%s",
+		   dealloc_decl, aref.ref, offstr))
     return false;
 
   if (DECL_P (aref.ref))
@@ -13793,15 +13787,15 @@ maybe_emit_free_warning (tree exp)
     return;
 
   tree dealloc_decl = get_callee_fndecl (exp);
-  location_t loc = tree_inlined_location (exp);
+  location_t loc = EXPR_LOCATION (exp);
 
   if (DECL_P (ref) || EXPR_P (ref))
     {
       /* Diagnose freeing a declared object.  */
       if (aref.ref_declared ()
 	  && warning_at (loc, OPT_Wfree_nonheap_object,
-			 "%K%qD called on unallocated object %qD",
-			 exp, dealloc_decl, ref))
+			 "%qD called on unallocated object %qD",
+			 dealloc_decl, ref))
 	{
 	  loc = (DECL_P (ref)
 		 ? DECL_SOURCE_LOCATION (ref)
@@ -13820,8 +13814,8 @@ maybe_emit_free_warning (tree exp)
   else if (CONSTANT_CLASS_P (ref))
     {
       if (warning_at (loc, OPT_Wfree_nonheap_object,
-		      "%K%qD called on a pointer to an unallocated "
-		      "object %qE", exp, dealloc_decl, ref))
+		      "%qD called on a pointer to an unallocated "
+		      "object %qE", dealloc_decl, ref))
 	{
 	  if (TREE_CODE (ptr) == SSA_NAME)
 	    {
@@ -13858,18 +13852,18 @@ maybe_emit_free_warning (tree exp)
 			     ? OPT_Wmismatched_new_delete
 			     : OPT_Wmismatched_dealloc);
 		  warned = warning_at (loc, opt,
-				       "%K%qD called on pointer returned "
+				       "%qD called on pointer returned "
 				       "from a mismatched allocation "
-				       "function", exp, dealloc_decl);
+				       "function", dealloc_decl);
 		}
 	    }
 	  else if (gimple_call_builtin_p (def_stmt, BUILT_IN_ALLOCA)
 	    	   || gimple_call_builtin_p (def_stmt,
 	    				     BUILT_IN_ALLOCA_WITH_ALIGN))
 	    warned = warning_at (loc, OPT_Wfree_nonheap_object,
-				 "%K%qD called on pointer to "
+				 "%qD called on pointer to "
 				 "an unallocated object",
-				 exp, dealloc_decl);
+				 dealloc_decl);
 	  else if (warn_dealloc_offset (loc, exp, aref))
 	    return;
 
diff --git a/gcc/calls.c b/gcc/calls.c
index a7c78ed9c16..fd088c0b972 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1435,8 +1435,8 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 	  if (tree_int_cst_lt (args[i], integer_zero_node))
 	    {
 	      warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-				   "%Kargument %i value %qE is negative",
-				   exp, idx[i] + 1, args[i]);
+				   "argument %i value %qE is negative",
+				   idx[i] + 1, args[i]);
 	    }
 	  else if (integer_zerop (args[i]))
 	    {
@@ -1452,8 +1452,8 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 		  : !lookup_attribute ("returns_nonnull",
 				       TYPE_ATTRIBUTES (fntype)))
 		warned = warning_at (loc, OPT_Walloc_zero,
-				     "%Kargument %i value is zero",
-				     exp, idx[i] + 1);
+				     "argument %i value is zero",
+				     idx[i] + 1);
 	    }
 	  else if (tree_int_cst_lt (maxobjsize, args[i]))
 	    {
@@ -1470,9 +1470,9 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 		continue;
 
 	      warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-				   "%Kargument %i value %qE exceeds "
+				   "argument %i value %qE exceeds "
 				   "maximum object size %E",
-				   exp, idx[i] + 1, args[i], maxobjsize);
+				   idx[i] + 1, args[i], maxobjsize);
 	    }
 	}
       else if (TREE_CODE (args[i]) == SSA_NAME
@@ -1484,16 +1484,16 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 	      && tree_int_cst_le (argrange[i][1], integer_zero_node))
 	    {
 	      warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-				   "%Kargument %i range [%E, %E] is negative",
-				   exp, idx[i] + 1,
+				   "argument %i range [%E, %E] is negative",
+				   idx[i] + 1,
 				   argrange[i][0], argrange[i][1]);
 	    }
 	  else if (tree_int_cst_lt (maxobjsize, argrange[i][0]))
 	    {
 	      warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-				   "%Kargument %i range [%E, %E] exceeds "
+				   "argument %i range [%E, %E] exceeds "
 				   "maximum object size %E",
-				   exp, idx[i] + 1,
+				   idx[i] + 1,
 				   argrange[i][0], argrange[i][1],
 				   maxobjsize);
 	    }
@@ -1521,15 +1521,15 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 
       if (vflow)
 	warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-			     "%Kproduct %<%E * %E%> of arguments %i and %i "
+			     "product %<%E * %E%> of arguments %i and %i "
 			     "exceeds %<SIZE_MAX%>",
-			     exp, argrange[0][0], argrange[1][0],
+			     argrange[0][0], argrange[1][0],
 			     idx[0] + 1, idx[1] + 1);
       else if (wi::ltu_p (wi::to_wide (maxobjsize, szprec), prod))
 	warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-			     "%Kproduct %<%E * %E%> of arguments %i and %i "
+			     "product %<%E * %E%> of arguments %i and %i "
 			     "exceeds maximum object size %E",
-			     exp, argrange[0][0], argrange[1][0],
+			     argrange[0][0], argrange[1][0],
 			     idx[0] + 1, idx[1] + 1,
 			     maxobjsize);
 
@@ -1729,14 +1729,14 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
 	  bool warned = false;
 	  if (tree_int_cst_equal (bndrng[0], bndrng[1]))
 	    warned = warning_at (loc, OPT_Wstringop_overread,
-				 "%K%qD specified bound %E "
+				 "%qD specified bound %E "
 				 "exceeds maximum object size %E",
-				 exp, fndecl, bndrng[0], maxobjsize);
+				 fndecl, bndrng[0], maxobjsize);
 	  else
 	    warned = warning_at (loc, OPT_Wstringop_overread,
-				 "%K%qD specified bound [%E, %E] "
+				 "%qD specified bound [%E, %E] "
 				 "exceeds maximum object size %E",
-				 exp, fndecl, bndrng[0], bndrng[1],
+				 fndecl, bndrng[0], bndrng[1],
 				 maxobjsize);
 	  if (warned)
 	    TREE_NO_WARNING (exp) = true;
@@ -2068,16 +2068,16 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 		= access.second.array_as_string (ptrtype);
 
 	      arg_warned = warning_at (loc, OPT_Wstringop_overflow_,
-				       "%Kbound argument %i value %s is "
+				       "bound argument %i value %s is "
 				       "negative for a variable length array "
 				       "argument %i of type %s",
-				       exp, sizidx + 1, sizstr,
+				       sizidx + 1, sizstr,
 				       ptridx + 1, argtypestr.c_str ());
 	    }
 	  else
 	    arg_warned = warning_at (loc, OPT_Wstringop_overflow_,
-				     "%Kargument %i value %s is negative",
-				     exp, sizidx + 1, sizstr);
+				     "argument %i value %s is negative",
+				     sizidx + 1, sizstr);
 
 	  if (arg_warned)
 	    {
@@ -2123,19 +2123,19 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 		    = access.second.array_as_string (ptrtype);
 
 		  arg_warned = warning_at (loc, OPT_Wnonnull,
-					   "%Kargument %i of variable length "
+					   "argument %i of variable length "
 					   "array %s is null but "
 					   "the corresponding bound argument "
 					   "%i value is %s",
-					   exp, sizidx + 1, argtypestr.c_str (),
+					   sizidx + 1, argtypestr.c_str (),
 					   ptridx + 1, sizstr);
 		}
 	      else
 		arg_warned = warning_at (loc, OPT_Wnonnull,
-					 "%Kargument %i is null but "
+					 "argument %i is null but "
 					 "the corresponding size argument "
 					 "%i value is %s",
-					 exp, ptridx + 1, sizidx + 1,
+					 ptridx + 1, sizidx + 1,
 					 sizstr);
 	    }
 	  else if (access_size && access.second.static_p)
@@ -2143,9 +2143,9 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 	      /* Warn about null pointers for [static N] array arguments
 		 but do not warn for ordinary (i.e., nonstatic) arrays.  */
 	      arg_warned = warning_at (loc, OPT_Wnonnull,
-				       "%Kargument %i to %<%T[static %E]%> "
+				       "argument %i to %<%T[static %E]%> "
 				       "is null where non-null expected",
-				       exp, ptridx + 1, argtype,
+				       ptridx + 1, argtype,
 				       access_size);
 	    }
 
diff --git a/gcc/expr.c b/gcc/expr.c
index e4660f0e90a..c8e61d38323 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -11391,7 +11391,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
       /* All valid uses of __builtin_va_arg_pack () are removed during
 	 inlining.  */
       if (CALL_EXPR_VA_ARG_PACK (exp))
-	error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
+	error ("invalid use of %<__builtin_va_arg_pack ()%>");
       {
 	tree fndecl = get_callee_fndecl (exp), attr;
 
@@ -11403,7 +11403,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 					 DECL_ATTRIBUTES (fndecl))) != NULL)
 	  {
 	    const char *ident = lang_hooks.decl_printable_name (fndecl, 1);
-	    error ("%Kcall to %qs declared with attribute error: %s", exp,
+	    error ("call to %qs declared with attribute error: %s",
 		   identifier_to_locale (ident),
 		   TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
 	  }
@@ -11415,10 +11415,10 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 					 DECL_ATTRIBUTES (fndecl))) != NULL)
 	  {
 	    const char *ident = lang_hooks.decl_printable_name (fndecl, 1);
-	    warning_at (tree_nonartificial_location (exp),
+	    warning_at (EXPR_LOCATION (exp),
 			OPT_Wattribute_warning,
-			"%Kcall to %qs declared with attribute warning: %s",
-			exp, identifier_to_locale (ident),
+			"call to %qs declared with attribute warning: %s",
+			identifier_to_locale (ident),
 			TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
 	  }
 
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 1c0e930aba5..b4020ba5ba2 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -2115,13 +2115,13 @@ gimple_fold_builtin_strncpy (gimple_stmt_iterator *gsi,
 	  tree slen = get_maxval_strlen (src, SRK_STRLEN);
 	  if (slen && !integer_zerop (slen))
 	    warning_at (loc, OPT_Wstringop_truncation,
-			"%G%qD destination unchanged after copying no bytes "
+			"%qD destination unchanged after copying no bytes "
 			"from a string of length %E",
-			stmt, fndecl, slen);
+			fndecl, slen);
 	  else
 	    warning_at (loc, OPT_Wstringop_truncation,
-			"%G%qD destination unchanged after copying no bytes",
-			stmt, fndecl);
+			"%qD destination unchanged after copying no bytes",
+			fndecl);
 	}
 
       replace_call_with_value (gsi, dest);
@@ -2498,11 +2498,11 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
 	  location_t loc = gimple_location (stmt);
 	  nowarn = warning_at (loc, OPT_Wstringop_overflow_,
 			       cmpdst == 0
-			       ? G_("%G%qD specified bound %E equals "
+			       ? G_("%qD specified bound %E equals "
 				    "destination size")
-			       : G_("%G%qD specified bound %E exceeds "
+			       : G_("%qD specified bound %E exceeds "
 				    "destination size %wu"),
-			       stmt, fndecl, len, dstsize);
+			       fndecl, len, dstsize);
 	  if (nowarn)
 	    gimple_set_no_warning (stmt, true);
 	}
@@ -2518,8 +2518,8 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
 	 of the destination is unknown (it's not an uncommon mistake
 	 to specify as the bound to strncpy the length of the source).  */
       if (warning_at (loc, OPT_Wstringop_overflow_,
-		      "%G%qD specified bound %E equals source length",
-		      stmt, fndecl, len))
+		      "%qD specified bound %E equals source length",
+		      fndecl, len))
 	gimple_set_no_warning (stmt, true);
     }
 
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index fc744669e4b..dae8cfaa8e4 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -3113,9 +3113,8 @@ format_directive (const call_info &info,
   if (fmtres.nullp)
     {
       fmtwarn (dirloc, argloc, NULL, info.warnopt (),
-	       "%G%<%.*s%> directive argument is null",
-	       info.callstmt, dirlen,
-	       target_to_host (hostdir, sizeof hostdir, dir.beg));
+	       "%<%.*s%> directive argument is null",
+	       dirlen, target_to_host (hostdir, sizeof hostdir, dir.beg));
 
       /* Don't bother processing the rest of the format string.  */
       res->warned = true;
@@ -4618,8 +4617,7 @@ handle_printf_call (gimple_stmt_iterator *gsi, pointer_query &ptr_qry)
 	     is not constant.  */
 	  location_t loc = gimple_location (info.callstmt);
 	  warning_at (EXPR_LOC_OR_LOC (dstptr, loc),
-		      info.warnopt (), "%Gnull destination pointer",
-		      info.callstmt);
+		      info.warnopt (), "null destination pointer");
 	  return false;
 	}
 
@@ -4648,8 +4646,7 @@ handle_printf_call (gimple_stmt_iterator *gsi, pointer_query &ptr_qry)
     {
       location_t loc = gimple_location (info.callstmt);
       warning_at (EXPR_LOC_OR_LOC (info.format, loc),
-		  info.warnopt (), "%Gnull format string",
-		  info.callstmt);
+		  info.warnopt (), "null format string");
       return false;
     }
 
diff --git a/gcc/gimple-ssa-warn-alloca.c b/gcc/gimple-ssa-warn-alloca.c
index 72480f1d8cb..4fc7125d378 100644
--- a/gcc/gimple-ssa-warn-alloca.c
+++ b/gcc/gimple-ssa-warn-alloca.c
@@ -283,7 +283,7 @@ pass_walloca::execute (function *fun)
 	    }
 	  else if (warn_alloca)
 	    {
-	      warning_at (loc, OPT_Walloca, "%Guse of %<alloca%>", stmt);
+	      warning_at (loc, OPT_Walloca, "use of %<alloca%>");
 	      continue;
 	    }
 	  else if (warn_alloca_limit < 0)
@@ -322,11 +322,10 @@ pass_walloca::execute (function *fun)
 		auto_diagnostic_group d;
 		if (warning_at (loc, wcode,
 				(is_vla
-				 ? G_("%Gargument to variable-length "
+				 ? G_("argument to variable-length "
 				      "array may be too large")
-				 : G_("%Gargument to %<alloca%> may be too "
-				      "large")),
-				stmt)
+				 : G_("argument to %<alloca%> may be too "
+				      "large")))
 		    && t.limit != 0)
 		  {
 		    print_decu (t.limit, buff);
@@ -342,10 +341,9 @@ pass_walloca::execute (function *fun)
 		auto_diagnostic_group d;
 		if (warning_at (loc, wcode,
 				(is_vla
-				 ? G_("%Gargument to variable-length"
+				 ? G_("argument to variable-length"
 				      " array is too large")
-				 : G_("%Gargument to %<alloca%> is too large")),
-				stmt)
+				 : G_("argument to %<alloca%> is too large")))
 		    && t.limit != 0)
 		  {
 		    print_decu (t.limit, buff);
@@ -361,22 +359,20 @@ pass_walloca::execute (function *fun)
 
 	      warning_at (loc, wcode,
 			  (is_vla
-			   ? G_("%Gunbounded use of variable-length array")
-			   : G_("%Gunbounded use of %<alloca%>")),
-			  stmt);
+			   ? G_("unbounded use of variable-length array")
+			   : G_("unbounded use of %<alloca%>")));
 	      break;
 	    case ALLOCA_IN_LOOP:
 	      gcc_assert (!is_vla);
 	      warning_at (loc, wcode,
-			  "%Guse of %<alloca%> within a loop", stmt);
+			  "use of %<alloca%> within a loop");
 	      break;
 	    case ALLOCA_ARG_IS_ZERO:
 	      warning_at (loc, wcode,
 			  (is_vla
-			   ? G_("%Gargument to variable-length array "
+			   ? G_("argument to variable-length array "
 				"is zero")
-			   : G_("%Gargument to %<alloca%> is zero")),
-			  stmt);
+			   : G_("argument to %<alloca%> is zero")));
 	      break;
 	    default:
 	      gcc_unreachable ();
diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c
index c8c9f9581a8..87b0ae04111 100644
--- a/gcc/gimple-ssa-warn-restrict.c
+++ b/gcc/gimple-ssa-warn-restrict.c
@@ -1494,36 +1494,36 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
 	    warning_at (loc, OPT_Wrestrict,
 			sizrange[0] == 1
 			? (ovlsiz[0] == 1
-			   ? G_("%G%qD accessing %wu byte at offsets %s "
+			   ? G_("%qD accessing %wu byte at offsets %s "
 				"and %s overlaps %wu byte at offset %s")
-			   :  G_("%G%qD accessing %wu byte at offsets %s "
+			   :  G_("%qD accessing %wu byte at offsets %s "
 				 "and %s overlaps %wu bytes at offset "
 				 "%s"))
 			: (ovlsiz[0] == 1
-			   ? G_("%G%qD accessing %wu bytes at offsets %s "
+			   ? G_("%qD accessing %wu bytes at offsets %s "
 				"and %s overlaps %wu byte at offset %s")
-			   : G_("%G%qD accessing %wu bytes at offsets %s "
+			   : G_("%qD accessing %wu bytes at offsets %s "
 				"and %s overlaps %wu bytes at offset "
 				"%s")),
-			call, func, sizrange[0],
+			func, sizrange[0],
 			offstr[0], offstr[1], ovlsiz[0], offstr[2]);
 	  else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
 	    warning_n (loc, OPT_Wrestrict, sizrange[0],
-		       "%G%qD accessing %wu byte at offsets %s "
+		       "%qD accessing %wu byte at offsets %s "
 		       "and %s overlaps between %wu and %wu bytes "
 		       "at offset %s",
-		       "%G%qD accessing %wu bytes at offsets %s "
+		       "%qD accessing %wu bytes at offsets %s "
 		       "and %s overlaps between %wu and %wu bytes "
 		       "at offset %s",
-		       call, func, sizrange[0], offstr[0], offstr[1],
+		       func, sizrange[0], offstr[0], offstr[1],
 		       ovlsiz[0], ovlsiz[1], offstr[2]);
 	  else
 	    warning_n (loc, OPT_Wrestrict, sizrange[0],
-		       "%G%qD accessing %wu byte at offsets %s and "
+		       "%qD accessing %wu byte at offsets %s and "
 		       "%s overlaps %wu or more bytes at offset %s",
-		       "%G%qD accessing %wu bytes at offsets %s and "
+		       "%qD accessing %wu bytes at offsets %s and "
 		       "%s overlaps %wu or more bytes at offset %s",
-		       call, func, sizrange[0],
+		       func, sizrange[0],
 		       offstr[0], offstr[1], ovlsiz[0], offstr[2]);
 	  return true;
 	}
@@ -1532,28 +1532,28 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
 	{
 	  if (ovlsiz[0] == ovlsiz[1])
 	    warning_n (loc, OPT_Wrestrict, ovlsiz[0],
-		       "%G%qD accessing between %wu and %wu bytes "
+		       "%qD accessing between %wu and %wu bytes "
 		       "at offsets %s and %s overlaps %wu byte at "
 		       "offset %s",
-		       "%G%qD accessing between %wu and %wu bytes "
+		       "%qD accessing between %wu and %wu bytes "
 		       "at offsets %s and %s overlaps %wu bytes "
 		       "at offset %s",
-		       call, func, sizrange[0], sizrange[1],
+		       func, sizrange[0], sizrange[1],
 		       offstr[0], offstr[1], ovlsiz[0], offstr[2]);
 	  else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
 	    warning_at (loc, OPT_Wrestrict,
-			"%G%qD accessing between %wu and %wu bytes at "
+			"%qD accessing between %wu and %wu bytes at "
 			"offsets %s and %s overlaps between %wu and %wu "
 			"bytes at offset %s",
-			call, func, sizrange[0], sizrange[1],
+			func, sizrange[0], sizrange[1],
 			offstr[0], offstr[1], ovlsiz[0], ovlsiz[1],
 			offstr[2]);
 	  else
 	    warning_at (loc, OPT_Wrestrict,
-			"%G%qD accessing between %wu and %wu bytes at "
+			"%qD accessing between %wu and %wu bytes at "
 			"offsets %s and %s overlaps %wu or more bytes "
 			"at offset %s",
-			call, func, sizrange[0], sizrange[1],
+			func, sizrange[0], sizrange[1],
 			offstr[0], offstr[1], ovlsiz[0], offstr[2]);
 	  return true;
 	}
@@ -1563,24 +1563,24 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
 
       if (ovlsiz[0] == ovlsiz[1])
 	warning_n (loc, OPT_Wrestrict, ovlsiz[0],
-		   "%G%qD accessing %wu or more bytes at offsets "
+		   "%qD accessing %wu or more bytes at offsets "
 		   "%s and %s overlaps %wu byte at offset %s",
-		   "%G%qD accessing %wu or more bytes at offsets "
+		   "%qD accessing %wu or more bytes at offsets "
 		   "%s and %s overlaps %wu bytes at offset %s",
-		   call, func, sizrange[0], offstr[0], offstr[1],
+		   func, sizrange[0], offstr[0], offstr[1],
 		   ovlsiz[0], offstr[2]);
       else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
 	warning_at (loc, OPT_Wrestrict,
-		    "%G%qD accessing %wu or more bytes at offsets %s "
+		    "%qD accessing %wu or more bytes at offsets %s "
 		    "and %s overlaps between %wu and %wu bytes "
 		    "at offset %s",
-		    call, func, sizrange[0], offstr[0], offstr[1],
+		    func, sizrange[0], offstr[0], offstr[1],
 		    ovlsiz[0], ovlsiz[1], offstr[2]);
       else
 	warning_at (loc, OPT_Wrestrict,
-		    "%G%qD accessing %wu or more bytes at offsets %s "
+		    "%qD accessing %wu or more bytes at offsets %s "
 		    "and %s overlaps %wu or more bytes at offset %s",
-		    call, func, sizrange[0], offstr[0], offstr[1],
+		    func, sizrange[0], offstr[0], offstr[1],
 		    ovlsiz[0], offstr[2]);
       return true;
     }
@@ -1606,36 +1606,36 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
 	{
 	  if (open_range)
 	    warning_n (loc, OPT_Wrestrict, sizrange[1],
-		       "%G%qD accessing %wu byte may overlap "
+		       "%qD accessing %wu byte may overlap "
 		       "%wu byte",
-		       "%G%qD accessing %wu bytes may overlap "
+		       "%qD accessing %wu bytes may overlap "
 		       "%wu byte",
-		       call, func, sizrange[1], ovlsiz[1]);
+		       func, sizrange[1], ovlsiz[1]);
 	  else
 	    warning_n (loc, OPT_Wrestrict, sizrange[1],
-		       "%G%qD accessing %wu byte at offsets %s "
+		       "%qD accessing %wu byte at offsets %s "
 		       "and %s may overlap %wu byte at offset %s",
-		       "%G%qD accessing %wu bytes at offsets %s "
+		       "%qD accessing %wu bytes at offsets %s "
 		       "and %s may overlap %wu byte at offset %s",
-		       call, func, sizrange[1], offstr[0], offstr[1],
+		       func, sizrange[1], offstr[0], offstr[1],
 		       ovlsiz[1], offstr[2]);
 	  return true;
 	}
 
       if (open_range)
 	warning_n (loc, OPT_Wrestrict, sizrange[1],
-		   "%G%qD accessing %wu byte may overlap "
+		   "%qD accessing %wu byte may overlap "
 		   "up to %wu bytes",
-		   "%G%qD accessing %wu bytes may overlap "
+		   "%qD accessing %wu bytes may overlap "
 		   "up to %wu bytes",
-		   call, func, sizrange[1], ovlsiz[1]);
+		   func, sizrange[1], ovlsiz[1]);
       else
 	warning_n (loc, OPT_Wrestrict, sizrange[1],
-		   "%G%qD accessing %wu byte at offsets %s and "
+		   "%qD accessing %wu byte at offsets %s and "
 		   "%s may overlap up to %wu bytes at offset %s",
-		   "%G%qD accessing %wu bytes at offsets %s and "
+		   "%qD accessing %wu bytes at offsets %s and "
 		   "%s may overlap up to %wu bytes at offset %s",
-		   call, func, sizrange[1], offstr[0], offstr[1],
+		   func, sizrange[1], offstr[0], offstr[1],
 		   ovlsiz[1], offstr[2]);
       return true;
     }
@@ -1644,30 +1644,30 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
     {
       if (open_range)
 	warning_n (loc, OPT_Wrestrict, ovlsiz[1],
-		   "%G%qD accessing between %wu and %wu bytes "
+		   "%qD accessing between %wu and %wu bytes "
 		   "may overlap %wu byte",
-		   "%G%qD accessing between %wu and %wu bytes "
+		   "%qD accessing between %wu and %wu bytes "
 		   "may overlap up to %wu bytes",
-		   call, func, sizrange[0], sizrange[1], ovlsiz[1]);
+		   func, sizrange[0], sizrange[1], ovlsiz[1]);
       else
 	warning_n (loc, OPT_Wrestrict, ovlsiz[1],
-		   "%G%qD accessing between %wu and %wu bytes "
+		   "%qD accessing between %wu and %wu bytes "
 		   "at offsets %s and %s may overlap %wu byte "
 		   "at offset %s",
-		   "%G%qD accessing between %wu and %wu bytes "
+		   "%qD accessing between %wu and %wu bytes "
 		   "at offsets %s and %s may overlap up to %wu "
 		   "bytes at offset %s",
-		   call, func, sizrange[0], sizrange[1],
+		   func, sizrange[0], sizrange[1],
 		   offstr[0], offstr[1], ovlsiz[1], offstr[2]);
       return true;
     }
 
   warning_n (loc, OPT_Wrestrict, ovlsiz[1],
-	     "%G%qD accessing %wu or more bytes at offsets %s "
+	     "%qD accessing %wu or more bytes at offsets %s "
 	     "and %s may overlap %wu byte at offset %s",
-	     "%G%qD accessing %wu or more bytes at offsets %s "
+	     "%qD accessing %wu or more bytes at offsets %s "
 	     "and %s may overlap up to %wu bytes at offset %s",
-	     call, func, sizrange[0], offstr[0], offstr[1],
+	     func, sizrange[0], offstr[0], offstr[1],
 	     ovlsiz[1], offstr[2]);
 
   return true;
@@ -1688,7 +1688,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 			  const builtin_memref &ref, offset_int wroff,
 			  bool do_warn)
 {
-  location_t loc = gimple_or_expr_nonartificial_location (call, ref.ptr);
+  location_t loc = gimple_location (call);
   const offset_int maxobjsize = ref.maxobjsize;
 
   /* Check for excessive size first and regardless of warning options
@@ -1706,15 +1706,15 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	{
 	  if (ref.sizrange[0] == ref.sizrange[1])
 	    return warning_at (loc, OPT_Wstringop_overflow_,
-			       "%G%qD specified bound %wu "
+			       "%qD specified bound %wu "
 			       "exceeds maximum object size %wu",
-			       call, func, ref.sizrange[0].to_uhwi (),
+			       func, ref.sizrange[0].to_uhwi (),
 			       maxobjsize.to_uhwi ());
 
 	  return warning_at (loc, OPT_Wstringop_overflow_,
-			     "%G%qD specified bound between %wu and %wu "
+			     "%qD specified bound between %wu and %wu "
 			     "exceeds maximum object size %wu",
-			     call, func, ref.sizrange[0].to_uhwi (),
+			     func, ref.sizrange[0].to_uhwi (),
 			     ref.sizrange[1].to_uhwi (),
 			     maxobjsize.to_uhwi ());
 	}
@@ -1771,9 +1771,9 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	{
 	  auto_diagnostic_group d;
 	  if (warning_at (loc, OPT_Warray_bounds,
-			  "%G%qD pointer overflow between offset %s "
+			  "%qD pointer overflow between offset %s "
 			  "and size %s accessing array %qD with type %qT",
-			  call, func, rangestr[0], rangestr[1], ref.base, type))
+			  func, rangestr[0], rangestr[1], ref.base, type))
 	    {
 	      inform (DECL_SOURCE_LOCATION (ref.base),
 		      "array %qD declared here", ref.base);
@@ -1781,15 +1781,15 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	    }
 	  else
 	    warned = warning_at (loc, OPT_Warray_bounds,
-				 "%G%qD pointer overflow between offset %s "
+				 "%qD pointer overflow between offset %s "
 				 "and size %s",
-				 call, func, rangestr[0], rangestr[1]);
+				 func, rangestr[0], rangestr[1]);
 	}
       else
 	warned = warning_at (loc, OPT_Warray_bounds,
-			     "%G%qD pointer overflow between offset %s "
+			     "%qD pointer overflow between offset %s "
 			     "and size %s",
-			     call, func, rangestr[0], rangestr[1]);
+			     func, rangestr[0], rangestr[1]);
     }
   else if (oobref == ref.base)
     {
@@ -1804,20 +1804,20 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	  if ((ref.basesize < maxobjsize
 	       && warning_at (loc, OPT_Warray_bounds,
 			      form
-			      ? G_("%G%qD forming offset %s is out of "
+			      ? G_("%qD forming offset %s is out of "
 				   "the bounds [0, %wu] of object %qD with "
 				   "type %qT")
-			      : G_("%G%qD offset %s is out of the bounds "
+			      : G_("%qD offset %s is out of the bounds "
 				   "[0, %wu] of object %qD with type %qT"),
-			      call, func, rangestr[0], ref.basesize.to_uhwi (),
+			      func, rangestr[0], ref.basesize.to_uhwi (),
 			      ref.base, TREE_TYPE (ref.base)))
 	      || warning_at (loc, OPT_Warray_bounds,
 			     form
-			     ? G_("%G%qD forming offset %s is out of "
+			     ? G_("%qD forming offset %s is out of "
 				  "the bounds of object %qD with type %qT")
-			     : G_("%G%qD offset %s is out of the bounds "
+			     : G_("%qD offset %s is out of the bounds "
 				  "of object %qD with type %qT"),
-			     call, func, rangestr[0],
+			     func, rangestr[0],
 			     ref.base, TREE_TYPE (ref.base)))
 	    {
 	      inform (DECL_SOURCE_LOCATION (ref.base),
@@ -1828,17 +1828,17 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
       else if (ref.basesize < maxobjsize)
 	warned = warning_at (loc, OPT_Warray_bounds,
 			     form
-			     ? G_("%G%qD forming offset %s is out "
+			     ? G_("%qD forming offset %s is out "
 				  "of the bounds [0, %wu]")
-			     : G_("%G%qD offset %s is out "
+			     : G_("%qD offset %s is out "
 				  "of the bounds [0, %wu]"),
-			     call, func, rangestr[0], ref.basesize.to_uhwi ());
+			     func, rangestr[0], ref.basesize.to_uhwi ());
       else
 	warned = warning_at (loc, OPT_Warray_bounds,
 			     form
-			     ? G_("%G%qD forming offset %s is out of bounds")
-			     : G_("%G%qD offset %s is out of bounds"),
-			     call, func, rangestr[0]);
+			     ? G_("%qD forming offset %s is out of bounds")
+			     : G_("%qD offset %s is out of bounds"),
+			     func, rangestr[0]);
     }
   else if (TREE_CODE (ref.ref) == MEM_REF)
     {
@@ -1849,9 +1849,9 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
       type = TYPE_MAIN_VARIANT (type);
 
       if (warning_at (loc, OPT_Warray_bounds,
-		      "%G%qD offset %s from the object at %qE is out "
+		      "%qD offset %s from the object at %qE is out "
 		      "of the bounds of %qT",
-		      call, func, rangestr[0], ref.base, type))
+		      func, rangestr[0], ref.base, type))
 	{
 	  if (TREE_CODE (ref.ref) == COMPONENT_REF)
 	    refop = TREE_OPERAND (ref.ref, 1);
@@ -1867,10 +1867,10 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
       tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref));
 
       if (warning_at (loc, OPT_Warray_bounds,
-		      "%G%qD offset %s from the object at %qE is out "
+		      "%qD offset %s from the object at %qE is out "
 		      "of the bounds of referenced subobject %qD with "
 		      "type %qT at offset %wi",
-		      call, func, rangestr[0], ref.base,
+		      func, rangestr[0], ref.base,
 		      TREE_OPERAND (ref.ref, 1), type,
 		      ref.refoff.to_shwi ()))
 	{
@@ -2057,7 +2057,7 @@ check_bounds_or_overlap (range_query *query,
 	}
     }
 
-  location_t loc = gimple_or_expr_nonartificial_location (call, dst);
+  location_t loc = gimple_location (call);
   if (operand_equal_p (dst, src, 0))
     {
       /* Issue -Wrestrict unless the pointers are null (those do
@@ -2067,8 +2067,8 @@ check_bounds_or_overlap (range_query *query,
       if (!integer_zerop (dst) && !gimple_no_warning_p (call))
 	{
 	  warning_at (loc, OPT_Wrestrict,
-		      "%G%qD source argument is the same as destination",
-		      call, func);
+		      "%qD source argument is the same as destination",
+		      func);
 	  gimple_set_no_warning (call, true);
 	  return OPT_Wrestrict;
 	}
diff --git a/gcc/testsuite/g++.dg/warn/Wdtor1.s b/gcc/testsuite/g++.dg/warn/Wdtor1.s
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-71.c b/gcc/testsuite/gcc.dg/Warray-bounds-71.c
new file mode 100644
index 00000000000..425bb122909
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-71.c
@@ -0,0 +1,7 @@
+/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic
+   works at any call site in an inlining stack
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+#define IGNORE '1'
+#include "Warray-bounds-71.h"
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-71.h b/gcc/testsuite/gcc.dg/Warray-bounds-71.h
new file mode 100644
index 00000000000..89d1068a266
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-71.h
@@ -0,0 +1,46 @@
+/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic
+   works at any call site in an inlining stack
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+int a[4];
+
+void f1 (int *p, int i)
+{
+#pragma GCC diagnostic push
+#if IGNORE == '1'
+#  pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+  p[i + 1] = 0;
+#pragma GCC diagnostic pop
+}
+
+void f2 (int *p, int i)
+{
+#pragma GCC diagnostic push
+#if IGNORE == '2'
+#  pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+  f1 (p + 1, i + 1);
+#pragma GCC diagnostic pop
+}
+
+void f3 (int *p, int i)
+{
+#pragma GCC diagnostic push
+#if IGNORE == '3'
+#  pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+  f2 (p + 1, i + 1);
+#pragma GCC diagnostic pop
+}
+
+void f4 (void)
+{
+#pragma GCC diagnostic push
+#if IGNORE == '4'
+#  pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+  f3 (a, 1);
+#pragma GCC diagnostic pop
+}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-72.c b/gcc/testsuite/gcc.dg/Warray-bounds-72.c
new file mode 100644
index 00000000000..eb3f664c0c8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-72.c
@@ -0,0 +1,7 @@
+/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic
+   works at any call site in an inlining stack
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+#define IGNORE '2'
+#include "Warray-bounds-71.h"
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-73.c b/gcc/testsuite/gcc.dg/Warray-bounds-73.c
new file mode 100644
index 00000000000..50e20835293
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-73.c
@@ -0,0 +1,7 @@
+/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic
+   works at any call site in an inlining stack
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+#define IGNORE '3'
+#include "Warray-bounds-71.h"
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-74.c b/gcc/testsuite/gcc.dg/Warray-bounds-74.c
new file mode 100644
index 00000000000..c59a876e073
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-74.c
@@ -0,0 +1,7 @@
+/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic
+   works at any call site in an inlining stack
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+#define IGNORE '4'
+#include "Warray-bounds-71.h"
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-75.c b/gcc/testsuite/gcc.dg/Warray-bounds-75.c
new file mode 100644
index 00000000000..306b1768b0e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-75.c
@@ -0,0 +1,12 @@
+/* Sanity test for Warray-bounds-7[1-4].c.  Also verify the expected
+   inlining stack.
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+#include "Warray-bounds-71.h"
+
+// { dg-regexp "In function 'f1'," "In function f1" { target *-*-* } 0 }
+// { dg-regexp "inlined from 'f2' at \[^\\n\\r\]+\[\\n\\r\]" "inlined from f2" { target *-*-* } 0 }
+// { dg-regexp "inlined from 'f3' at \[^\\n\\r\]+\[\\n\\r\]" "inlined from f3" { target *-*-* } 0 }
+// { dg-regexp "inlined from 'f4' at \[^\\n\\r\]+\[\\n\\r\]" "inlined from f4" { target *-*-* } 0 }
+// { dg-message "Warray-bounds-71.h:\\d+:\\d+: warning: array subscript 6 is outside array bounds of 'int\\\[4]'" "warning" { target *-*-* } 0 }
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c
index a7d921248c4..fdef9e6b3ea 100644
--- a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c
@@ -26,7 +26,7 @@ void g2 (struct A *p) { g1 (p); }
 
 #define NOIPA __attribute__ ((noipa))
 
-extern int array[];
+extern int array[];           // { dg-message "declared here" "note on line 29" }
 
 /* Verify the warning is issued even for calls in a system header inlined
    into a function outside the header.  */
@@ -39,7 +39,7 @@ NOIPA void warn_g0 (struct A *p)
   g0 (p);
 }
 
-// { dg-message "inlined from 'warn_g0'" "" { target *-*-* } 0 }
+// { dg-message "inlined from 'warn_g0'" "note on line 42" { target *-*-* } 0 }
 
 
 /* Also verify the warning can be suppressed.  */
@@ -65,8 +65,8 @@ NOIPA void warn_g1 (struct A *p)
   g1 (p);
 }
 
-// { dg-message "inlined from 'g1'" "" { target *-*-* } 0 }
-// { dg-message "inlined from 'warn_g1'" "" { target *-*-* } 0 }
+// { dg-message "inlined from 'g1'" "note on line 68" { target *-*-* } 0 }
+// { dg-message "inlined from 'warn_g1'" "note on line 69" { target *-*-* } 0 }
 
 
 NOIPA void nowarn_g1 (struct A *p)
@@ -90,8 +90,8 @@ NOIPA void warn_g2 (struct A *p)
   g2 (p);
 }
 
-// { dg-message "inlined from 'g2'" "" { target *-*-* } 0 }
-// { dg-message "inlined from 'warn_g2'" "" { target *-*-* } 0 }
+// { dg-message "inlined from 'g2'" "note on line 93" { target *-*-* } 0 }
+// { dg-message "inlined from 'warn_g2'" "note on line 94" { target *-*-* } 0 }
 
 
 NOIPA void nowarn_g2 (struct A *p)
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c
new file mode 100644
index 00000000000..979e1e3d78f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c
@@ -0,0 +1,45 @@
+/* Similar to Wfree-nonheap-object-4.c but without system headers:
+   verify that warnings for the same call site from distinct callers
+   include the correct function names in the inlining stack.
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+struct A
+{
+  void *p;
+};
+
+void f0 (struct A *p)
+{
+  __builtin_free (p->p);      // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+// Expect two instances of the text below:
+// { dg-regexp "In function 'f0'," "f0 prefix" { target *-*-* } 0 }
+// { dg-regexp "In function 'f0'," "f0 prefix" { target *-*-* } 0 }
+
+void f1 (struct A *p) { f0 (p); }
+void f2 (struct A *p) { f1 (p); }
+
+extern int array[];
+// Also expect two instances of the note:
+// { dg-regexp "declared here" "note on line 24" { target *-*-* } .-2 }
+// { dg-regexp "declared here" "note on line 24" { target *-*-* } .-3 }
+
+void foo (struct A *p)
+{
+  p->p = array + 1;
+  f0 (p);
+}
+
+// { dg-message "inlined from 'foo'" "note on line 35" { target *-*-* } 0 }
+
+
+void bar (struct A *p)
+{
+  p->p = array + 2;
+  f1 (p);
+}
+
+// { dg-message "inlined from 'f1'" "note on line 44" { target *-*-* } 0 }
+// { dg-message "inlined from 'bar'" "note on line 45" { target *-*-* } 0 }
diff --git a/gcc/testsuite/gcc.dg/Wobjsize-1.c b/gcc/testsuite/gcc.dg/Wobjsize-1.c
index e80c8add3bb..2bd2f93897b 100644
--- a/gcc/testsuite/gcc.dg/Wobjsize-1.c
+++ b/gcc/testsuite/gcc.dg/Wobjsize-1.c
@@ -4,13 +4,17 @@
 #include "Wobjsize-1.h"
 
 char buf[6];
-/* { dg-warning "writing" "" { target *-*-* } .-1 } */
 
 int main(int argc, char **argv)
 {
-  strcpy (buf,"hello ");
+  strcpy (buf,"hello ");    /* { dg-warning "\\\[-Wstringop-overflow" } */
   return 0;
 }
 
-/* { dg-message "file included" "included" { target *-*-* } 0 } */
-/* { dg-message "inlined from" "inlined" { target *-*-* } 0 } */
+/* { dg-message "file included" "included" { target *-*-* } 0 }
+   { dg-message "inlined from" "inlined" { target *-*-* } 0 }
+
+   The test might emit two warnings, one for the strcpy call and
+   another for the inlined call to __builtin___strcpy_chk() called
+   from strcpy().
+   { dg-prune-output "writing 7 bytes into a region of size 6" } */
diff --git a/gcc/testsuite/gcc.dg/pragma-diag-10.c b/gcc/testsuite/gcc.dg/pragma-diag-10.c
new file mode 100644
index 00000000000..127b299939a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pragma-diag-10.c
@@ -0,0 +1,20 @@
+/* PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective
+   in conjunction with alias attribute
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+void *
+__rawmemchr_ppc (const void *s, int c)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+#pragma GCC diagnostic ignored "-Wstringop-overread"
+  if (c != 0)
+    return __builtin_memchr (s, c, (unsigned long)-1);    // { dg-bogus "specified bound \\d+ exceeds maximum object size" }
+#pragma GCC diagnostic pop
+
+  return (char *)s + __builtin_strlen (s);
+}
+
+extern __typeof (__rawmemchr_ppc) __EI___rawmemchr_ppc
+  __attribute__((alias ("__rawmemchr_ppc")));
diff --git a/gcc/testsuite/gcc.dg/pragma-diag-9.c b/gcc/testsuite/gcc.dg/pragma-diag-9.c
new file mode 100644
index 00000000000..d7eac558128
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pragma-diag-9.c
@@ -0,0 +1,134 @@
+/* Verify that #pragma GCC diagnostic down the inlining stack suppresses
+   a warning that would otherwise be issued for inlined calls higher up
+   the inlining stack.
+   { dg-do compile }
+   { dg-options "-O2 -Wall -Wno-array-bounds" } */
+
+extern void* memset (void*, int, __SIZE_TYPE__);
+
+static void warn0 (int *p)
+{
+  memset (p, __LINE__, 3);    // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+static void warn1 (int *p)
+{
+  warn0 (p + 1);
+}
+
+static void warn2 (int *p)
+{
+  warn1 (p + 1);
+}
+
+int a2[2];                    // { dg-message "at offset 12 into destination object 'a2' of size 8" }
+
+void warn3 (void)
+{
+  warn2 (a2 + 1);
+}
+
+
+static void ignore0 (int *p)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  memset (p, __LINE__, 3);
+#pragma GCC diagnostic pop
+}
+
+static void nowarn1_ignore0 (int *p)
+{
+  ignore0 (p + 1);
+}
+
+static void nowarn2_ignore0 (int *p)
+{
+  nowarn1_ignore0 (p + 1);
+}
+
+int b2[2];
+
+void nowarn3_ignore0 (void)
+{
+  nowarn2_ignore0 (b2 + 1);
+}
+
+
+static void nowarn0_ignore1 (int *p)
+{
+  memset (p, __LINE__, 3);
+}
+
+static void ignore1 (int *p)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  nowarn0_ignore1 (p + 1);
+#pragma GCC diagnostic pop
+}
+
+void nowarn2_ignore1 (int *p)
+{
+  ignore1 (p + 1);
+}
+
+int c2[2];
+
+void nowarn3_ignore1 (void)
+{
+  nowarn2_ignore1 (c2 + 1);
+}
+
+
+static void nowarn0_ignore2 (int *p)
+{
+  memset (p, __LINE__, 3);
+}
+
+static void nowarn1_ignore2 (int *p)
+{
+  nowarn0_ignore2 (p + 1);
+}
+
+static void ignore2 (int *p)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  nowarn1_ignore2 (p + 1);
+#pragma GCC diagnostic pop
+}
+
+int d2[2];
+
+void nowarn3_ignore2 (void)
+{
+  ignore2 (c2 + 1);
+}
+
+
+
+static void nowarn0_ignore3 (int *p)
+{
+  memset (p, __LINE__, 3);
+}
+
+static void nowarn1_ignore3 (int *p)
+{
+  nowarn0_ignore3 (p + 1);
+}
+
+static void nowarn2_ignore3 (int *p)
+{
+  nowarn1_ignore3 (p + 1);
+}
+
+int e2[2];
+
+void ignore3 (void)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  nowarn2_ignore3 (e2 + 1);
+#pragma GCC diagnostic pop
+}
diff --git a/gcc/testsuite/gcc.dg/uninit-suppress_3.c b/gcc/testsuite/gcc.dg/uninit-suppress_3.c
new file mode 100644
index 00000000000..7bbe9edc605
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-suppress_3.c
@@ -0,0 +1,98 @@
+/* PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at declaration
+   site
+   { dg-do compile }
+   { dg-options "-O1 -Wall" } */
+
+struct A
+{
+  int x;
+};
+
+// Verify that suppression works at every inlining level.
+
+static int f0 (int *x)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+
+  return ++*x;
+
+#pragma GCC diagnostic pop
+}
+
+static int f1 (int *p, int n)
+{
+  struct A a;
+  for (int i = 0; i < n; ++i) {
+    if (p[i] > 1) {
+      a = (struct A){p[i]};
+    }
+  }
+	
+  return f0 (&a.x);
+}
+
+int f2 (void)
+{
+  int a[] = { 1, 2, 3, 4 };
+  return f1 (a, 4);
+}
+
+
+static int g0 (int *x)
+{
+  return ++*x;
+}
+
+static int g1 (int *p, int n)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+
+  struct A a;
+  for (int i = 0; i < n; ++i) {
+    if (p[i] > 1) {
+      a = (struct A){p[i]};
+    }
+  }
+	
+  return g0 (&a.x);
+
+#pragma GCC diagnostic pop
+}
+
+int g2 (void)
+{
+  int a[] = { 1, 2, 3, 4, 5 };
+  return g1 (a, 5);
+}
+
+
+static int h0 (int *x)
+{
+  return ++*x;
+}
+
+static int h1 (int *p, int n)
+{
+  struct A a;
+  for (int i = 0; i < n; ++i) {
+    if (p[i] > 1) {
+      a = (struct A){p[i]};
+    }
+  }
+	
+  return h0 (&a.x);
+}
+
+int h2 (void)
+{
+  int a[] = { 1, 2, 3, 4, 5, 6 };
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+
+  return h1 (a, 6);
+
+#pragma GCC diagnostic pop
+}
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index e74bd1f5ec0..c270d039b15 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -4413,12 +4413,8 @@ ipa_tm_scan_irr_block (basic_block bb)
 	     is to wrap it in a __tm_waiver block.  This is not
 	     yet implemented, so we can't check for it.  */
 	  if (is_tm_safe (current_function_decl))
-	    {
-	      tree t = build1 (NOP_EXPR, void_type_node, size_zero_node);
-	      SET_EXPR_LOCATION (t, gimple_location (stmt));
-	      error ("%K%<asm%> not allowed in %<transaction_safe%> function",
-		     t);
-	    }
+	    error_at (gimple_location (stmt),
+		      "%<asm%> not allowed in %<transaction_safe%> function");
 	  return true;
 
 	default:
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 3834212b867..a7003c55aea 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -3563,7 +3563,7 @@ pass_post_ipa_warn::execute (function *fun)
 	      if (argno == 0)
 		{
 		  if (warning_at (loc, OPT_Wnonnull,
-				  "%G%qs pointer is null", stmt, "this")
+				  "%qs pointer is null", "this")
 		      && fndecl)
 		    inform (DECL_SOURCE_LOCATION (fndecl),
 			    "in a call to non-static member function %qD",
@@ -3572,8 +3572,8 @@ pass_post_ipa_warn::execute (function *fun)
 		}
 
 	      if (!warning_at (loc, OPT_Wnonnull,
-			       "%Gargument %u null where non-null "
-			       "expected", stmt, argno))
+			       "argument %u null where non-null "
+			       "expected", argno))
 		continue;
 
 	      tree fndecl = gimple_call_fndecl (stmt);
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 423075b2bd1..d22bc40afe8 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -2019,13 +2019,12 @@ maybe_warn_overflow (gimple *stmt, tree len, pointer_query &ptr_qry,
 
       warned = (writefn
 		? warning_at (loc, OPT_Wstringop_overflow_,
-			      "%G%qD writing one too many bytes into a region "
+			      "%qD writing one too many bytes into a region "
 			      "of a size that depends on %<strlen%>",
-			      stmt, writefn)
+			      writefn)
 		: warning_at (loc, OPT_Wstringop_overflow_,
-			      "%Gwriting one too many bytes into a region "
-			      "of a size that depends on %<strlen%>",
-			      stmt));
+			      "writing one too many bytes into a region "
+			      "of a size that depends on %<strlen%>"));
     }
   else if (lenrng[0] == lenrng[1])
     {
@@ -2033,65 +2032,65 @@ maybe_warn_overflow (gimple *stmt, tree len, pointer_query &ptr_qry,
 	warned = (writefn
 		  ? warning_n (loc, OPT_Wstringop_overflow_,
 			       lenrng[0].to_uhwi (),
-			       "%G%qD writing %wu byte into a region "
+			       "%qD writing %wu byte into a region "
 			       "of size %wu",
-			       "%G%qD writing %wu bytes into a region "
+			       "%qD writing %wu bytes into a region "
 			       "of size %wu",
-			       stmt, writefn, lenrng[0].to_uhwi (),
+			       writefn, lenrng[0].to_uhwi (),
 			       spcrng[0].to_uhwi ())
 		  : warning_n (loc, OPT_Wstringop_overflow_,
 			       lenrng[0].to_uhwi (),
-			       "%Gwriting %wu byte into a region "
+			       "writing %wu byte into a region "
 			       "of size %wu",
-			       "%Gwriting %wu bytes into a region "
+			       "writing %wu bytes into a region "
 			       "of size %wu",
-			       stmt, lenrng[0].to_uhwi (),
+			       lenrng[0].to_uhwi (),
 			       spcrng[0].to_uhwi ()));
       else
 	warned = (writefn
 		  ? warning_n (loc, OPT_Wstringop_overflow_,
 			       lenrng[0].to_uhwi (),
-			       "%G%qD writing %wu byte into a region "
+			       "%qD writing %wu byte into a region "
 			       "of size between %wu and %wu",
-			       "%G%qD writing %wu bytes into a region "
+			       "%qD writing %wu bytes into a region "
 			       "of size between %wu and %wu",
-			       stmt, writefn, lenrng[0].to_uhwi (),
+			       writefn, lenrng[0].to_uhwi (),
 			       spcrng[0].to_uhwi (), spcrng[1].to_uhwi ())
 		  : warning_n (loc, OPT_Wstringop_overflow_,
 			       lenrng[0].to_uhwi (),
-			       "%Gwriting %wu byte into a region "
+			       "writing %wu byte into a region "
 			       "of size between %wu and %wu",
-			       "%Gwriting %wu bytes into a region "
+			       "writing %wu bytes into a region "
 			       "of size between %wu and %wu",
-			       stmt, lenrng[0].to_uhwi (),
+			       lenrng[0].to_uhwi (),
 			       spcrng[0].to_uhwi (), spcrng[1].to_uhwi ()));
     }
   else if (spcrng[0] == spcrng[1])
     warned = (writefn
 	      ? warning_at (loc, OPT_Wstringop_overflow_,
-			    "%G%qD writing between %wu and %wu bytes "
+			    "%qD writing between %wu and %wu bytes "
 			    "into a region of size %wu",
-			    stmt, writefn, lenrng[0].to_uhwi (),
+			    writefn, lenrng[0].to_uhwi (),
 			    lenrng[1].to_uhwi (),
 			    spcrng[0].to_uhwi ())
 	      : warning_at (loc, OPT_Wstringop_overflow_,
-			    "%Gwriting between %wu and %wu bytes "
+			    "writing between %wu and %wu bytes "
 			    "into a region of size %wu",
-			    stmt, lenrng[0].to_uhwi (),
+			    lenrng[0].to_uhwi (),
 			    lenrng[1].to_uhwi (),
 			    spcrng[0].to_uhwi ()));
   else
     warned = (writefn
 	      ? warning_at (loc, OPT_Wstringop_overflow_,
-			    "%G%qD writing between %wu and %wu bytes "
+			    "%qD writing between %wu and %wu bytes "
 			    "into a region of size between %wu and %wu",
-			    stmt, writefn, lenrng[0].to_uhwi (),
+			    writefn, lenrng[0].to_uhwi (),
 			    lenrng[1].to_uhwi (),
 			    spcrng[0].to_uhwi (), spcrng[1].to_uhwi ())
 	      : warning_at (loc, OPT_Wstringop_overflow_,
-			    "%Gwriting between %wu and %wu bytes "
+			    "writing between %wu and %wu bytes "
 			    "into a region of size between %wu and %wu",
-			    stmt, lenrng[0].to_uhwi (),
+			    lenrng[0].to_uhwi (),
 			    lenrng[1].to_uhwi (),
 			    spcrng[0].to_uhwi (), spcrng[1].to_uhwi ()));
 
@@ -2982,13 +2981,13 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
       if (lenrange[0] == cntrange[1] && cntrange[0] == cntrange[1])
 	return warning_n (callloc, OPT_Wstringop_truncation,
 			  cntrange[0].to_uhwi (),
-			  "%G%qD output truncated before terminating "
+			  "%qD output truncated before terminating "
 			  "nul copying %E byte from a string of the "
 			  "same length",
-			  "%G%qD output truncated before terminating nul "
+			  "%qD output truncated before terminating nul "
 			  "copying %E bytes from a string of the same "
 			  "length",
-			  stmt, func, cnt);
+			  func, cnt);
       else if (!cat_dstlen_bounded)
 	{
 	  if (wi::geu_p (lenrange[0], cntrange[1]))
@@ -2998,16 +2997,16 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
 	      if (cntrange[0] == cntrange[1])
 		return warning_n (callloc, OPT_Wstringop_truncation,
 				  cntrange[0].to_uhwi (),
-				  "%G%qD output truncated copying %E byte "
+				  "%qD output truncated copying %E byte "
 				  "from a string of length %wu",
-				  "%G%qD output truncated copying %E bytes "
+				  "%qD output truncated copying %E bytes "
 				  "from a string of length %wu",
-				  stmt, func, cnt, lenrange[0].to_uhwi ());
+				  func, cnt, lenrange[0].to_uhwi ());
 
 	      return warning_at (callloc, OPT_Wstringop_truncation,
-				 "%G%qD output truncated copying between %wu "
+				 "%qD output truncated copying between %wu "
 				 "and %wu bytes from a string of length %wu",
-				 stmt, func, cntrange[0].to_uhwi (),
+				 func, cntrange[0].to_uhwi (),
 				 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
 	    }
 	  else if (wi::geu_p (lenrange[1], cntrange[1]))
@@ -3017,16 +3016,16 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
 	      if (cntrange[0] == cntrange[1])
 		return warning_n (callloc, OPT_Wstringop_truncation,
 				  cntrange[0].to_uhwi (),
-				  "%G%qD output may be truncated copying %E "
+				  "%qD output may be truncated copying %E "
 				  "byte from a string of length %wu",
-				  "%G%qD output may be truncated copying %E "
+				  "%qD output may be truncated copying %E "
 				  "bytes from a string of length %wu",
-				  stmt, func, cnt, lenrange[1].to_uhwi ());
+				  func, cnt, lenrange[1].to_uhwi ());
 
 	      return warning_at (callloc, OPT_Wstringop_truncation,
-				 "%G%qD output may be truncated copying between "
+				 "%qD output may be truncated copying between "
 				 "%wu and %wu bytes from a string of length %wu",
-				 stmt, func, cntrange[0].to_uhwi (),
+				 func, cntrange[0].to_uhwi (),
 				 cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
 	    }
 	}
@@ -3040,9 +3039,9 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
 	     the lower bound of the specified count but shorter than the
 	     upper bound the copy may (but need not) be truncated.  */
 	  return warning_at (callloc, OPT_Wstringop_truncation,
-			     "%G%qD output may be truncated copying between "
+			     "%qD output may be truncated copying between "
 			     "%wu and %wu bytes from a string of length %wu",
-			     stmt, func, cntrange[0].to_uhwi (),
+			     func, cntrange[0].to_uhwi (),
 			     cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
 	}
     }
@@ -3069,8 +3068,8 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
 
       if (cntrange[0] == cntrange[1])
 	return warning_at (callloc, OPT_Wstringop_truncation,
-			   "%G%qD specified bound %E equals destination size",
-			   stmt, func, cnt);
+			   "%qD specified bound %E equals destination size",
+			   func, cnt);
     }
 
   return false;
@@ -3193,9 +3192,9 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
       && sisrc == silen
       && is_strlen_related_p (src, len)
       && warning_at (callloc, OPT_Wstringop_truncation,
-		     "%G%qD output truncated before terminating nul "
+		     "%qD output truncated before terminating nul "
 		     "copying as many bytes from a string as its length",
-		     stmt, func))
+		     func))
     warned = true;
   else if ((append_p || !dstsize || len == dstlenp1)
 	   && silen && is_strlen_related_p (src, silen->ptr))
@@ -3206,9 +3205,9 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
       int opt = (append_p || dstsize
 		 ? OPT_Wstringop_overflow_ : OPT_Wstringop_truncation);
       warned = warning_at (callloc, opt,
-			   "%G%qD specified bound depends on the length "
+			   "%qD specified bound depends on the length "
 			   "of the source argument",
-			   stmt, func);
+			   func);
     }
   if (warned)
     {
@@ -4140,24 +4139,24 @@ maybe_warn_pointless_strcmp (gimple *stmt, HOST_WIDE_INT bound,
   if (siz <= minlen && bound == -1)
     warned = warning_at (stmt_loc, OPT_Wstring_compare,
 			 (at_least
-			  ? G_("%G%qD of a string of length %wu or more and "
+			  ? G_("%qD of a string of length %wu or more and "
 			       "an array of size %wu evaluates to nonzero")
-			  : G_("%G%qD of a string of length %wu and an array "
+			  : G_("%qD of a string of length %wu and an array "
 			       "of size %wu evaluates to nonzero")),
-			 stmt, callee, minlen, siz);
+			 callee, minlen, siz);
   else if (!at_least && siz <= HOST_WIDE_INT_MAX)
     {
       if (len[0] != HOST_WIDE_INT_MAX && len[1] != HOST_WIDE_INT_MAX)
 	warned = warning_at (stmt_loc, OPT_Wstring_compare,
-			     "%G%qD of strings of length %wu and %wu "
+			     "%qD of strings of length %wu and %wu "
 			     "and bound of %wu evaluates to nonzero",
-			     stmt, callee, len[0], len[1], bound);
+			     callee, len[0], len[1], bound);
       else
 	warned = warning_at (stmt_loc, OPT_Wstring_compare,
-			     "%G%qD of a string of length %wu, an array "
+			     "%qD of a string of length %wu, an array "
 			     "of size %wu and bound of %wu evaluates to "
 			     "nonzero",
-			     stmt, callee, minlen, siz, bound);
+			     callee, minlen, siz, bound);
     }
 
   if (!warned)
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index 7c002f8ed87..6c8fe12fd39 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -428,7 +428,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
   if (wlims.always_executed)
     {
       if (warning_at (location, OPT_Wuninitialized,
-		      "%G%qE is used uninitialized", stmt, rhs))
+		      "%qE is used uninitialized", rhs))
 	{
 	  /* ???  This is only effective for decls as in
 	     gcc.dg/uninit-B-O0.c.  Avoid doing this for maybe-uninit
@@ -441,7 +441,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
     }
   else if (wlims.wmaybe_uninit)
     warned = warning_at (location, OPT_Wmaybe_uninitialized,
-			 "%G%qE may be used uninitialized", stmt, rhs);
+			 "%qE may be used uninitialized", rhs);
 
   return warned ? base : NULL_TREE;
 }

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 3/4] remove %K from error() calls in the aarch64/arm back ends (PR 98512)
  2021-06-10 23:24     ` [PATCH 0/4] improve warning suppression for inlined functions (PR 98512) Martin Sebor
  2021-06-10 23:26       ` [PATCH 1/4] introduce diagnostic infrastructure changes " Martin Sebor
  2021-06-10 23:27       ` [PATCH 2/4] remove %G and %K from calls in front end and middle end " Martin Sebor
@ 2021-06-10 23:28       ` Martin Sebor
  2021-06-11  7:53         ` Christophe Lyon
  2021-06-11  9:58         ` Richard Sandiford
  2021-06-10 23:30       ` [PATCH 4/4] remove %G and %K support from pretty printer and -Wformat " Martin Sebor
  3 siblings, 2 replies; 44+ messages in thread
From: Martin Sebor @ 2021-06-10 23:28 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 367 bytes --]

This patch removes the uses of %K from error() calls in the aarch64
and arm back ends.  I tested this change only by building a cross-
compiler but I can't easily run the tests so I'd appreciate some help
validating it.  The fallout from the change should be limited to changes
to error messages so in the worst case it could be addressed after
committing the patch.

[-- Attachment #2: gcc-98512-3.diff --]
[-- Type: text/x-patch, Size: 6257 bytes --]

gcc/ChangeLog:

	* config/aarch64/aarch64-builtins.c (aarch64_simd_expand_builtin):
	Remove %K and use error_at.
	(aarch64_expand_fcmla_builtin): Same.
	(aarch64_expand_builtin_tme): Same.
	(aarch64_expand_builtin_memtag): Same.
	* config/arm/arm-builtins.c (arm_expand_acle_builtin): Same.
	(arm_expand_builtin): Same.
	* config/arm/arm.c (bounds_check): Same.

diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 3cab3ec992c..9ed4b72d005 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -1598,8 +1598,9 @@ constant_arg:
 	      if (!(*insn_data[icode].operand[opc].predicate)
 		  (op[opc], mode))
 	      {
-		error ("%Kargument %d must be a constant immediate",
-		       exp, opc + 1 - have_retval);
+		error_at (EXPR_LOCATION (exp),
+			  "argument %d must be a constant immediate",
+			  opc + 1 - have_retval);
 		return const0_rtx;
 	      }
 	      break;
@@ -1669,10 +1670,13 @@ aarch64_simd_expand_builtin (int fcode, tree exp, rtx target)
 				       / UINTVAL (elementsize),
 				      exp);
           else
-	    error ("%Klane index must be a constant immediate", exp);
+	    error_at (EXPR_LOCATION (exp),
+		      "lane index must be a constant immediate");
 	}
       else
-	error ("%Ktotal size and element size must be a non-zero constant immediate", exp);
+	error_at (EXPR_LOCATION (exp),
+		  "total size and element size must be a non-zero "
+		  "constant immediate");
       /* Don't generate any RTL.  */
       return const0_rtx;
     }
@@ -1828,7 +1832,8 @@ aarch64_expand_fcmla_builtin (tree exp, rtx target, int fcode)
   /* Validate that the lane index is a constant.  */
   if (!CONST_INT_P (lane_idx))
     {
-      error ("%Kargument %d must be a constant immediate", exp, 4);
+      error_at (EXPR_LOCATION (exp),
+		"argument %d must be a constant immediate", 4);
       return const0_rtx;
     }
 
@@ -1917,7 +1922,8 @@ aarch64_expand_builtin_tme (int fcode, tree exp, rtx target)
 	  emit_insn (GEN_FCN (CODE_FOR_tcancel) (op0));
 	else
 	  {
-	    error ("%Kargument must be a 16-bit constant immediate", exp);
+	    error_at (EXPR_LOCATION (exp),
+		      "argument must be a 16-bit constant immediate");
 	    return const0_rtx;
 	  }
       }
@@ -2006,8 +2012,9 @@ aarch64_expand_builtin_memtag (int fcode, tree exp, rtx target)
 		  pat = GEN_FCN (icode) (target, op0, const0_rtx, op1);
 		  break;
 		}
-	      error ("%Kargument %d must be a constant immediate "
-		     "in range [0,15]", exp, 2);
+	      error_at (EXPR_LOCATION (exp),
+			"argument %d must be a constant immediate "
+			"in range [0,15]", 2);
 	      return const0_rtx;
 	    }
 	  else
diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c
index fa0fb0b16ab..3a9ff8f26b8 100644
--- a/gcc/config/arm/arm-builtins.c
+++ b/gcc/config/arm/arm-builtins.c
@@ -3092,26 +3092,30 @@ constant_arg:
 			  unsigned int cp_bit = (CONST_INT_P (op[argc])
 						 ? UINTVAL (op[argc]) : -1);
 			  if (IN_RANGE (cp_bit, 0, ARM_CDE_CONST_COPROC))
-			    error ("%Kcoprocessor %d is not enabled "
-				   "with +cdecp%d", exp, cp_bit, cp_bit);
+			    error_at (EXPR_LOCATION (exp),
+				      "coprocessor %d is not enabled "
+				      "with +cdecp%d", cp_bit, cp_bit);
 			  else
-			    error ("%Kcoproc must be a constant immediate in "
-				   "range [0-%d] enabled with +cdecp<N>", exp,
-				   ARM_CDE_CONST_COPROC);
+			    error_at (EXPR_LOCATION (exp),
+				      "coproc must be a constant immediate in "
+				      "range [0-%d] enabled with +cdecp<N>",
+				      ARM_CDE_CONST_COPROC);
 			}
 		      else
 			/* Here we mention the builtin name to follow the same
 			   format that the C/C++ frontends use for referencing
 			   a given argument index.  */
-			error ("%Kargument %d to %qE must be a constant immediate "
-			       "in range [0-%d]", exp, argc + 1,
+			error_at (EXPR_LOCATION (exp),
+				  "argument %d to %qE must be a constant "
+				  "immediate in range [0-%d]", argc + 1,
 			       arm_builtin_decls[fcode],
 			       cde_builtin_data[fcode -
 			       ARM_BUILTIN_CDE_PATTERN_START].imm_max);
 		    }
 		  else
-		    error ("%Kargument %d must be a constant immediate",
-			   exp, argc + 1);
+		    error_at (EXPR_LOCATION (exp),
+			      "argument %d must be a constant immediate",
+			      argc + 1);
 		  /* We have failed to expand the pattern, and are safely
 		     in to invalid code.  But the mid-end will still try to
 		     build an assignment for this node while it expands,
@@ -3328,11 +3332,13 @@ arm_expand_acle_builtin (int fcode, tree exp, rtx target)
       if (CONST_INT_P (sat_imm))
 	{
 	  if (!IN_RANGE (sat_imm, min_sat, max_sat))
-	    error ("%Ksaturation bit range must be in the range [%wd, %wd]",
-		   exp, UINTVAL (min_sat), UINTVAL (max_sat));
+	    error_at (EXPR_LOCATION (exp),
+		      "saturation bit range must be in the range [%wd, %wd]",
+		      UINTVAL (min_sat), UINTVAL (max_sat));
 	}
       else
-	error ("%Ksaturation bit range must be a constant immediate", exp);
+	error_at (EXPR_LOCATION (exp),
+		  "saturation bit range must be a constant immediate");
       /* Don't generate any RTL.  */
       return const0_rtx;
     }
@@ -3455,7 +3461,8 @@ arm_expand_builtin (tree exp,
       if (CONST_INT_P (lane_idx))
 	neon_lane_bounds (lane_idx, 0, TREE_INT_CST_LOW (nlanes), exp);
       else
-	error ("%Klane index must be a constant immediate", exp);
+	error_at (EXPR_LOCATION (exp),
+		  "lane index must be a constant immediate");
       /* Don't generate any RTL.  */
       return const0_rtx;
     }
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 7b37e1b602c..7cdc824730c 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -13242,13 +13242,8 @@ bounds_check (rtx operand, HOST_WIDE_INT low, HOST_WIDE_INT high,
   lane = INTVAL (operand);
 
   if (lane < low || lane >= high)
-    {
-      if (exp)
-	error ("%K%s %wd out of range %wd - %wd",
-	       exp, desc, lane, low, high - 1);
-      else
-	error ("%s %wd out of range %wd - %wd", desc, lane, low, high - 1);
-    }
+    error_at (EXPR_LOCATION (exp),
+	      "%s %wd out of range %wd - %wd", desc, lane, low, high - 1);
 }
 
 /* Bounds-check lanes.  */

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH 4/4] remove %G and %K support from pretty printer and -Wformat (PR 98512)
  2021-06-10 23:24     ` [PATCH 0/4] improve warning suppression for inlined functions (PR 98512) Martin Sebor
                         ` (2 preceding siblings ...)
  2021-06-10 23:28       ` [PATCH 3/4] remove %K from error() calls in the aarch64/arm back ends " Martin Sebor
@ 2021-06-10 23:30       ` Martin Sebor
  2021-06-30 16:17         ` [PING][PATCH " Martin Sebor
  2021-06-30 23:38         ` [PATCH " David Malcolm
  3 siblings, 2 replies; 44+ messages in thread
From: Martin Sebor @ 2021-06-10 23:30 UTC (permalink / raw)
  To: David Malcolm, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 164 bytes --]

This final diff removes the handlers for %G and %K from the pretty
printer and the support for the directives from c-format.c so that
using them will be diagnosed.

[-- Attachment #2: gcc-98512-4.diff --]
[-- Type: text/x-patch, Size: 12517 bytes --]

gcc/c-family/ChangeLog:

	* c-format.c (gcc_tdiag_char_table): Remove support for %G and %K.
	 (gcc_cdiag_char_table): Same.
	 (gcc_cxxdiag_char_table): Same.

gcc/c/ChangeLog:

	* c-objc-common.c (c_tree_printer): Remove support for %G and %K.

gcc/cp/ChangeLog:

	* error.c (cp_printer):  Remove support for %G and %K.

gcc/ChangeLog:

	* gimple-pretty-print.c (percent_G_format): Remove.
	* tree-diagnostic.c (default_tree_printer): Remove calls.
	* tree-pretty-print.c (percent_K_format): Remove.
	* tree-pretty-print.h (percent_K_format): Remove.

gcc/testsuite/ChangeLog:

	* gcc.dg/format/gcc_diag-10.c: Update expected warnings.

diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index bda3b18fcd0..6fd0bb33d21 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -781,10 +781,6 @@ static const format_char_info gcc_tdiag_char_table[] =
   /* These will require a "tree" at runtime.  */
   { "DFTV", 1, STD_C89, { T89_T,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+", "'",   NULL },
   { "E", 1, STD_C89, { T89_T,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+", "",   NULL },
-  { "K", 1, STD_C89, { T89_T,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "", "\"",   NULL },
-
-  /* G requires a "gimple*" argument at runtime.  */
-  { "G", 1, STD_C89, { T89_G,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "", "\"",   NULL },
 
   { NULL,  0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
 };
@@ -799,10 +795,6 @@ static const format_char_info gcc_cdiag_char_table[] =
   /* These will require a "tree" at runtime.  */
   { "DFTV", 1, STD_C89, { T89_T,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+", "'",   NULL },
   { "E",   1, STD_C89, { T89_T,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+", "",   NULL },
-  { "K",   1, STD_C89, { T89_T,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "", "\"",   NULL },
-
-  /* G requires a "gimple*" argument at runtime.  */
-  { "G",   1, STD_C89, { T89_G,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "", "\"",   NULL },
 
   { "v",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q#",  "",   NULL },
 
@@ -819,10 +811,6 @@ static const format_char_info gcc_cxxdiag_char_table[] =
   /* These will require a "tree" at runtime.  */
   { "ADFHISTVX",1,STD_C89,{ T89_T,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+#",   "'",   NULL },
   { "E", 1,STD_C89,{ T89_T,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+#",   "",   NULL },
-  { "K", 1, STD_C89,{ T89_T,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "",   "\"",   NULL },
-
-  /* G requires a "gimple*" argument at runtime.  */
-  { "G", 1, STD_C89,{ T89_G,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "",   "\"",   NULL },
 
   /* These accept either an 'int' or an 'enum tree_code' (which is handled as an 'int'.)  */
   { "CLOPQ",0,STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
diff --git a/gcc/c/c-objc-common.c b/gcc/c/c-objc-common.c
index b945de15ab8..cdb2242758e 100644
--- a/gcc/c/c-objc-common.c
+++ b/gcc/c/c-objc-common.c
@@ -247,8 +247,6 @@ print_type (c_pretty_printer *cpp, tree t, bool *quoted)
    %D: a general decl,
    %E: an identifier or expression,
    %F: a function declaration,
-   %G: a Gimple statement,
-   %K: a CALL_EXPR,
    %T: a type.
    %V: a list of type qualifiers from a tree.
    %v: an explicit list of type qualifiers
@@ -269,19 +267,6 @@ c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
   if (precision != 0 || wide)
     return false;
 
-  if (*spec == 'G')
-    {
-      percent_G_format (text);
-      return true;
-    }
-
-  if (*spec == 'K')
-    {
-      t = va_arg (*text->args_ptr, tree);
-      percent_K_format (text, EXPR_LOCATION (t), TREE_BLOCK (t));
-      return true;
-    }
-
   if (*spec != 'v')
     {
       t = va_arg (*text->args_ptr, tree);
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 4a89b348829..012a4ecddf4 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -4338,10 +4338,8 @@ defer_phase_2_of_type_diff (deferred_printed_type *deferred,
    %D   declaration.
    %E   expression.
    %F   function declaration.
-   %G   gcall *
    %H   type difference (from).
    %I   type difference (to).
-   %K   tree
    %L	language as used in extern "lang".
    %O	binary operator.
    %P   function parameter whose position is indicated by an integer.
@@ -4391,9 +4389,6 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec,
       break;
     case 'E': result = expr_to_string (next_tree);		break;
     case 'F': result = fndecl_to_string (next_tree, verbose);	break;
-    case 'G':
-      percent_G_format (text);
-      return true;
     case 'H':
       defer_phase_2_of_type_diff (&postprocessor->m_type_a, next_tree,
 				  buffer_ptr, verbose, *quoted);
@@ -4402,10 +4397,6 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec,
       defer_phase_2_of_type_diff (&postprocessor->m_type_b, next_tree,
 				  buffer_ptr, verbose, *quoted);
       return true;
-    case 'K':
-      t = va_arg (*text->args_ptr, tree);
-      percent_K_format (text, EXPR_LOCATION (t), TREE_BLOCK (t));
-      return true;
     case 'L': result = language_to_string (next_lang);		break;
     case 'O': result = op_to_string (false, next_tcode);	break;
     case 'P': result = parm_to_string (next_int);		break;
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index c9c0a66ee30..474f3b6953e 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -3056,23 +3056,6 @@ gimple_dump_bb_for_graph (pretty_printer *pp, basic_block bb)
   pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
 }
 
-
-/* Handle the %G format for TEXT.  Same as %K in handle_K_format in
-   tree-pretty-print.c but with a Gimple statement as an argument.  */
-
-void
-percent_G_format (text_info *text)
-{
-  gimple *stmt = va_arg (*text->args_ptr, gimple*);
-
-  /* Fall back on the rich location if the statement doesn't have one.  */
-  location_t loc = gimple_location (stmt);
-  if (loc == UNKNOWN_LOCATION)
-    loc = text->m_richloc->get_loc ();
-  tree block = gimple_block (stmt);
-  percent_K_format (text, loc, block);
-}
-
 #if __GNUC__ >= 10
 #  pragma GCC diagnostic pop
 #endif
diff --git a/gcc/testsuite/gcc.dg/format/gcc_diag-10.c b/gcc/testsuite/gcc.dg/format/gcc_diag-10.c
index a2f99feefc9..3bce538e9fe 100644
--- a/gcc/testsuite/gcc.dg/format/gcc_diag-10.c
+++ b/gcc/testsuite/gcc.dg/format/gcc_diag-10.c
@@ -64,8 +64,8 @@ void test_cdiag (tree t, gimple *gc)
   cdiag ("%D", t);       /* { dg-warning ".D. conversion used unquoted" } */
   cdiag ("%E", t);
   cdiag ("%F", t);       /* { dg-warning ".F. conversion used unquoted" } */
-  cdiag ("%G", gc);
-  cdiag ("%K", t);
+  cdiag ("%G", gc);      /* { dg-warning "format" } */
+  cdiag ("%K", t);       /* { dg-warning "format" } */
 
   cdiag ("%R");       /* { dg-warning "unmatched color reset directive" } */
   cdiag ("%r", "");   /* { dg-warning "unterminated color directive" } */
@@ -80,8 +80,8 @@ void test_cdiag (tree t, gimple *gc)
   cdiag ("%<%D%>", t);
   cdiag ("%<%E%>", t);
   cdiag ("%<%F%>", t);
-  cdiag ("%<%G%>", gc);  /* { dg-warning ".G. conversion used within a quoted sequence" } */
-  cdiag ("%<%K%>", t);   /* { dg-warning ".K. conversion used within a quoted sequence" } */
+  cdiag ("%<%G%>", gc);  /* { dg-warning "format" } */
+  cdiag ("%<%K%>", t);   /* { dg-warning "format" } */
 
   cdiag ("%<%R%>");      /* { dg-warning "unmatched color reset directive" } */
   cdiag ("%<%r%>", "");  /* { dg-warning "unterminated color directive" } */
@@ -103,8 +103,8 @@ void test_tdiag (tree t, gimple *gc)
 
   tdiag ("%D", t);       /* { dg-warning ".D. conversion used unquoted" } */
   tdiag ("%E", t);
-  tdiag ("%G", gc);
-  tdiag ("%K", t);
+  tdiag ("%G", gc);     /* { dg-warning "format" } */
+  tdiag ("%K", t);      /* { dg-warning "format" } */
 
   tdiag ("%R");          /* { dg-warning "unmatched color reset directive" } */
   tdiag ("%r", "");   /* { dg-warning "unterminated color directive" } */
@@ -118,8 +118,8 @@ void test_tdiag (tree t, gimple *gc)
 
   tdiag ("%<%D%>", t);
   tdiag ("%<%E%>", t);
-  tdiag ("%<%G%>", gc);  /* { dg-warning ".G. conversion used within a quoted sequence" } */
-  tdiag ("%<%K%>", t);   /* { dg-warning ".K. conversion used within a quoted sequence" } */
+  tdiag ("%<%G%>", gc);  /* { dg-warning "format" } */
+  tdiag ("%<%K%>", t);   /* { dg-warning "format" } */
 
   tdiag ("%<%R%>");      /* { dg-warning "unmatched color reset directive" } */
   tdiag ("%<%r%>", "");  /* { dg-warning "unterminated color directive" } */
@@ -138,8 +138,8 @@ void test_cxxdiag (tree t, gimple *gc)
   cxxdiag ("%D", t);     /* { dg-warning ".D. conversion used unquoted" } */
   cxxdiag ("%E", t);
   cxxdiag ("%F", t);     /* { dg-warning ".F. conversion used unquoted" } */
-  cxxdiag ("%G", gc);
-  cxxdiag ("%K", t);
+  cxxdiag ("%G", gc);    /* { dg-warning "format" } */
+  cxxdiag ("%K", t);     /* { dg-warning "format" } */
 
   cxxdiag ("%R");        /* { dg-warning "unmatched color reset directive" } */
   cxxdiag ("%r", "");    /* { dg-warning "unterminated color directive" } */
@@ -185,7 +185,7 @@ void test_dump (tree t, gimple *stmt, cgraph_node *node)
 
   dump ("%E", stmt);
   dump ("%T", t);
-  dump ("%G", stmt);
+  dump ("%G", stmt);    /* { dg-warning "format" } */
   dump ("%C", node);
   dump ("%f", 1.0);
   dump ("%4.2f", 1.0); /* { dg-warning "format" } */
diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
index a8c5484849a..614e654e2b2 100644
--- a/gcc/tree-diagnostic.c
+++ b/gcc/tree-diagnostic.c
@@ -276,15 +276,6 @@ default_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
       t = va_arg (*text->args_ptr, tree);
       break;
 
-    case 'G':
-      percent_G_format (text);
-      return true;
-
-    case 'K':
-      t = va_arg (*text->args_ptr, tree);
-      percent_K_format (text, EXPR_LOCATION (t), TREE_BLOCK (t));
-      return true;
-
     default:
       return false;
     }
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index d8a4f55b2ae..df9828cec7b 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -4430,32 +4430,6 @@ newline_and_indent (pretty_printer *pp, int spc)
   INDENT (spc);
 }
 
-/* Handle the %K format for TEXT.  Separate from default_tree_printer
-   so it can also be used in front ends.
-   The location LOC and BLOCK are expected to be extracted by the caller
-   from the %K argument arg via EXPR_LOCATION(arg) and TREE_BLOCK(arg).  */
-
-void
-percent_K_format (text_info *text, location_t loc, tree block)
-{
-  text->set_location (0, loc, SHOW_RANGE_WITH_CARET);
-  gcc_assert (pp_ti_abstract_origin (text) != NULL);
-  *pp_ti_abstract_origin (text) = NULL;
-
-  while (block
-	 && TREE_CODE (block) == BLOCK
-	 && BLOCK_ABSTRACT_ORIGIN (block))
-    {
-      tree ao = BLOCK_ABSTRACT_ORIGIN (block);
-      if (TREE_CODE (ao) == FUNCTION_DECL)
-	{
-	  *pp_ti_abstract_origin (text) = block;
-	  break;
-	}
-      block = BLOCK_SUPERCONTEXT (block);
-    }
-}
-
 /* Print the identifier ID to PRETTY-PRINTER.  */
 
 void
diff --git a/gcc/tree-pretty-print.h b/gcc/tree-pretty-print.h
index 92eb4123e79..1ada5983d5d 100644
--- a/gcc/tree-pretty-print.h
+++ b/gcc/tree-pretty-print.h
@@ -51,7 +51,6 @@ extern int op_prio (const_tree);
 extern const char *op_symbol_code (enum tree_code);
 extern void pretty_print_string (pretty_printer *, const char *, size_t);
 extern void print_call_name (pretty_printer *, tree, dump_flags_t);
-extern void percent_K_format (text_info *, location_t, tree);
 extern void pp_tree_identifier (pretty_printer *, tree);
 extern void dump_function_header (FILE *, tree, dump_flags_t);
 extern void pp_double_int (pretty_printer *pp, double_int d, bool uns);

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 3/4] remove %K from error() calls in the aarch64/arm back ends (PR 98512)
  2021-06-10 23:28       ` [PATCH 3/4] remove %K from error() calls in the aarch64/arm back ends " Martin Sebor
@ 2021-06-11  7:53         ` Christophe Lyon
  2021-06-11 13:10           ` Christophe Lyon
  2021-06-11  9:58         ` Richard Sandiford
  1 sibling, 1 reply; 44+ messages in thread
From: Christophe Lyon @ 2021-06-11  7:53 UTC (permalink / raw)
  To: Martin Sebor; +Cc: gcc-patches

On Fri, 11 Jun 2021 at 01:29, Martin Sebor via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> This patch removes the uses of %K from error() calls in the aarch64
> and arm back ends.  I tested this change only by building a cross-
> compiler but I can't easily run the tests so I'd appreciate some help
> validating it.  The fallout from the change should be limited to changes
> to error messages so in the worst case it could be addressed after
> committing the patch.

I've submitted a validation with your patch, I'll let you know the
results (in a few hours)

Thanks

Christophe

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 3/4] remove %K from error() calls in the aarch64/arm back ends (PR 98512)
  2021-06-10 23:28       ` [PATCH 3/4] remove %K from error() calls in the aarch64/arm back ends " Martin Sebor
  2021-06-11  7:53         ` Christophe Lyon
@ 2021-06-11  9:58         ` Richard Sandiford
  2021-06-11 14:46           ` Martin Sebor
  1 sibling, 1 reply; 44+ messages in thread
From: Richard Sandiford @ 2021-06-11  9:58 UTC (permalink / raw)
  To: Martin Sebor via Gcc-patches

Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> index 7b37e1b602c..7cdc824730c 100644
> --- a/gcc/config/arm/arm.c
> +++ b/gcc/config/arm/arm.c
> @@ -13242,13 +13242,8 @@ bounds_check (rtx operand, HOST_WIDE_INT low, HOST_WIDE_INT high,
>    lane = INTVAL (operand);
>  
>    if (lane < low || lane >= high)
> -    {
> -      if (exp)
> -	error ("%K%s %wd out of range %wd - %wd",
> -	       exp, desc, lane, low, high - 1);
> -      else
> -	error ("%s %wd out of range %wd - %wd", desc, lane, low, high - 1);
> -    }
> +    error_at (EXPR_LOCATION (exp),
> +	      "%s %wd out of range %wd - %wd", desc, lane, low, high - 1);
>  }
>  
>  /* Bounds-check lanes.  */

This part doesn't look safe: “exp” is null when called from arm_const_bounds.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 3/4] remove %K from error() calls in the aarch64/arm back ends (PR 98512)
  2021-06-11  7:53         ` Christophe Lyon
@ 2021-06-11 13:10           ` Christophe Lyon
  2021-06-11 14:47             ` Martin Sebor
  0 siblings, 1 reply; 44+ messages in thread
From: Christophe Lyon @ 2021-06-11 13:10 UTC (permalink / raw)
  To: Martin Sebor; +Cc: gcc-patches

On Fri, 11 Jun 2021 at 09:53, Christophe Lyon
<christophe.lyon@linaro.org> wrote:
>
> On Fri, 11 Jun 2021 at 01:29, Martin Sebor via Gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
> >
> > This patch removes the uses of %K from error() calls in the aarch64
> > and arm back ends.  I tested this change only by building a cross-
> > compiler but I can't easily run the tests so I'd appreciate some help
> > validating it.  The fallout from the change should be limited to changes
> > to error messages so in the worst case it could be addressed after
> > committing the patch.
>
> I've submitted a validation with your patch, I'll let you know the
> results (in a few hours)
>

I haven't noticed any regression with that patch alone.
I just noticed it is patch 3/4: I didn't apply patches 1 and 2 before
this one, do you want me to relaunch the tests with the 3 patches
combined?

Thanks,

Christophe

> Thanks
>
> Christophe

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 3/4] remove %K from error() calls in the aarch64/arm back ends (PR 98512)
  2021-06-11  9:58         ` Richard Sandiford
@ 2021-06-11 14:46           ` Martin Sebor
  2021-06-30 19:56             ` Martin Sebor
  0 siblings, 1 reply; 44+ messages in thread
From: Martin Sebor @ 2021-06-11 14:46 UTC (permalink / raw)
  To: Martin Sebor via Gcc-patches, richard.sandiford

On 6/11/21 3:58 AM, Richard Sandiford wrote:
> Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
>> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
>> index 7b37e1b602c..7cdc824730c 100644
>> --- a/gcc/config/arm/arm.c
>> +++ b/gcc/config/arm/arm.c
>> @@ -13242,13 +13242,8 @@ bounds_check (rtx operand, HOST_WIDE_INT low, HOST_WIDE_INT high,
>>     lane = INTVAL (operand);
>>   
>>     if (lane < low || lane >= high)
>> -    {
>> -      if (exp)
>> -	error ("%K%s %wd out of range %wd - %wd",
>> -	       exp, desc, lane, low, high - 1);
>> -      else
>> -	error ("%s %wd out of range %wd - %wd", desc, lane, low, high - 1);
>> -    }
>> +    error_at (EXPR_LOCATION (exp),
>> +	      "%s %wd out of range %wd - %wd", desc, lane, low, high - 1);
>>   }
>>   
>>   /* Bounds-check lanes.  */
> 
> This part doesn't look safe: “exp” is null when called from arm_const_bounds.

Doh!  Yes, will fix, thanks.

Martin

> 
> Thanks,
> Richard
> 


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 3/4] remove %K from error() calls in the aarch64/arm back ends (PR 98512)
  2021-06-11 13:10           ` Christophe Lyon
@ 2021-06-11 14:47             ` Martin Sebor
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Sebor @ 2021-06-11 14:47 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: gcc-patches

On 6/11/21 7:10 AM, Christophe Lyon wrote:
> On Fri, 11 Jun 2021 at 09:53, Christophe Lyon
> <christophe.lyon@linaro.org> wrote:
>>
>> On Fri, 11 Jun 2021 at 01:29, Martin Sebor via Gcc-patches
>> <gcc-patches@gcc.gnu.org> wrote:
>>>
>>> This patch removes the uses of %K from error() calls in the aarch64
>>> and arm back ends.  I tested this change only by building a cross-
>>> compiler but I can't easily run the tests so I'd appreciate some help
>>> validating it.  The fallout from the change should be limited to changes
>>> to error messages so in the worst case it could be addressed after
>>> committing the patch.
>>
>> I've submitted a validation with your patch, I'll let you know the
>> results (in a few hours)
>>
> 
> I haven't noticed any regression with that patch alone.
> I just noticed it is patch 3/4: I didn't apply patches 1 and 2 before
> this one, do you want me to relaunch the tests with the 3 patches
> combined?

That would be great, as soon as I fix the thinko Richard Sandiford
pointed out.

Thanks for the offer!

Martin

> 
> Thanks,
> 
> Christophe
> 
>> Thanks
>>
>> Christophe


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 1/4] introduce diagnostic infrastructure changes (PR 98512)
  2021-06-10 23:26       ` [PATCH 1/4] introduce diagnostic infrastructure changes " Martin Sebor
@ 2021-06-11 17:04         ` David Malcolm
  2021-06-15 23:00           ` Martin Sebor
  0 siblings, 1 reply; 44+ messages in thread
From: David Malcolm @ 2021-06-11 17:04 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches

On Thu, 2021-06-10 at 17:26 -0600, Martin Sebor wrote:
> This diff introduces the diagnostic infrastructure changes to support
> controlling warnings at any call site in the inlining stack and
> printing
> the inlining context without the %K and %G directives.

Thanks for working on this, looks very promising.

> Improve warning suppression for inlined functions.
> 
> Resolves:
> PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at declaration site
> PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective in conjunction with alias attribute

Am I right in thinking that you add test coverage for both of these in
patch 2 of the kit?

> 
> gcc/ChangeLog:
> 
> 	* diagnostic.c (update_inlining_context): New.
> 	(update_effective_level_from_pragmas): Handle inlining context.
> 	(diagnostic_report_diagnostic): Same.
> 	* diagnostic.h (struct diagnostic_info): Add ctor.
> 	(struct diagnostic_context): Add members.
> 	* tree-diagnostic.c (get_inlining_locations): New.
> 	(set_inlining_location): New.
> 	(tree_diagnostics_defaults): Set new callback pointers.

[..snip...]

> @@ -1204,7 +1256,7 @@ diagnostic_report_diagnostic (diagnostic_context *context,
>        /* We do this to avoid giving the message for -pedantic-errors.  */
>        orig_diag_kind = diagnostic->kind;
>      }
> - 
> +

Stray whitespace change?  Though it looks like a fix of a stray space,
so not a big deal.

>    if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
>      return false;
>  

[..snip...]

> diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
> index 1b9d6b1f64d..b95ee23dda0 100644
> --- a/gcc/diagnostic.h
> +++ b/gcc/diagnostic.h
> @@ -87,6 +87,10 @@ enum diagnostics_extra_output_kind
>     list in diagnostic.def.  */
>  struct diagnostic_info
>  {
> +  diagnostic_info ()
> +    : message (), richloc (), metadata (), x_data (), kind (), option_index ()
> +  { }
> +

Why does the patch add this ctor?

>    /* Text to be formatted.  */
>    text_info message;
>  
> @@ -343,6 +347,32 @@ struct diagnostic_context
>  
>    /* Callback for final cleanup.  */
>    void (*final_cb) (diagnostic_context *context);
> +
> +  /* The inlining context of the diagnostic (may have just one
> +     element if a diagnostic is not for an inlined expression).  */
> +  struct inlining_ctx
> +  {
> +    void reset ()
> +    {
> +      ilocs.release ();
> +      loc = UNKNOWN_LOCATION;
> +      ao = NULL;
> +      allsyslocs = false;
> +    }
> +
> +    /* Locations along the inlining stack.  */
> +    auto_vec<location_t, 8> ilocs;
> +    /* The locus of the diagnostic. */
> +    location_t loc;
> +    /* The abstract origin of the location.  */
> +    void *ao;
> +    /* Set of every ILOCS element is in a system header.  */
> +    bool allsyslocs;
> +  } ictx;

Why is the inlining ctx part of the diagnostic_context?  That feels
strange to me. This inlining information relates to a particular
diagnostic, so it seems more appropriate to me that it should be part
of the diagnostic_info (which might thus necessitate having a ctor for
diagnostic_info).  Doing that might avoid the need for "reset", if I'm
right in assuming that getting the data is done once per diagnostic
during diagnostic_report_diagnostic.

Alternatively, could this be state that's created on the stack during
diagnostic_report_diagnostic and passed around by pointer as another
parameter?  (putting it in diagnostic_info might be simplest though)

Maybe rename it to "inlining_info"?

How involved would it be to make it be a class with private fields?

Can the field names have "m_" prefixes, please?

> +  /* Callbacks to get and set the inlining context.  */

Probably should spell out in the comment here that doing so requires
knowledge of trees, which is why it's a callback (to avoid diagnostic.c
from having to know about trees).

> +  void (*get_locations_cb)(diagnostic_context *, diagnostic_info *);
> +  void (*set_location_cb)(const diagnostic_context *, diagnostic_info *);
>  };
>  
>  static inline void
> diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
> index 95b8ef30070..a8c5484849a 100644
> --- a/gcc/tree-diagnostic.c
> +++ b/gcc/tree-diagnostic.c
> @@ -305,6 +305,84 @@ default_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
>    return true;
>  }
>  
> +/* Get the inlining stack corresponding to the DIAGNOSTIC location.  */
> +
> +static void
> +get_inlining_locations (diagnostic_context *context,
> +			diagnostic_info *diagnostic)
> +{
> +  context->ictx.reset ();
> +
> +  location_t loc = diagnostic_location (diagnostic);
> +  tree block = LOCATION_BLOCK (loc);
> +
> +  /* Count the number of locations in system headers.  When all are,
> +     warnings are suppressed by -Wno-system-headers.  Otherwise, they
> +     involve some user code, possibly inlined into a function in a system
> +     header, and are not treated as coming from system headers.  */
> +  unsigned nsyslocs = 0;
> +
> +  while (block && TREE_CODE (block) == BLOCK
> +	 && BLOCK_ABSTRACT_ORIGIN (block))
> +    {
> +      tree ao = BLOCK_ABSTRACT_ORIGIN (block);
> +      if (TREE_CODE (ao) == FUNCTION_DECL)
> +	{
> +	  if (!context->ictx.ao)
> +	    context->ictx.ao = block;
> +
> +	  location_t loc = BLOCK_SOURCE_LOCATION (block);
> +	  context->ictx.ilocs.safe_push (loc);
> +	  if (in_system_header_at (loc))
> +	    ++nsyslocs;
> +	}
> +      else if (TREE_CODE (ao) != BLOCK)
> +	break;
> +
> +      block = BLOCK_SUPERCONTEXT (block);
> +    }
> +
> +  if (context->ictx.ilocs.length ())
> +    {
> +      /* When there is an inlining context use the macro expansion
> +	 location for the original location and bump up NSYSLOCS if
> +	 it's in a system header since it's not counted above.  */
> +      context->ictx.loc = expansion_point_location_if_in_system_header (loc);
> +      if (context->ictx.loc != loc)
> +	++nsyslocs;
> +    }
> +  else
> +    {
> +      /* When there's no inlining context use the original location
> +	 and set NSYSLOCS accordingly.  */
> +      context->ictx.loc = loc;
> +      nsyslocs = in_system_header_at (loc) != 0;
> +    }
> +
> +  context->ictx.ilocs.safe_push (context->ictx.loc);
> +
> +  /* Set if all locations are in a system header.  */
> +  context->ictx.allsyslocs = nsyslocs == context->ictx.ilocs.length ();;

Surplus trailing semicolon.

Maybe store nsyslocs as private member data ("m_nsyslocs"), and have an
all_system_locations_p accessor?  (since if I'm reading things right
that's the question that diagnostic_report_diagnostic is asking of the
inlining_info that we need this information for)



> +/* Set the inlining location for to the DIAGNOSTIC based on the saved
> +   inlining context.  */
> +
> +static void
> +set_inlining_location (const diagnostic_context *context,
> +		       diagnostic_info *diagnostic)
> +{
> +  if (!pp_ti_abstract_origin (&diagnostic->message)
> +      || !context->ictx.ao
> +      || context->ictx.loc == UNKNOWN_LOCATION)
> +    /* Do nothing when there's no inlining context.  */
> +    return;
> +
> +  *pp_ti_abstract_origin (&diagnostic->message) = (tree)context->ictx.ao;
> +  diagnostic->message.set_location (0, context->ictx.loc,
> +				    SHOW_RANGE_WITH_CARET);
> +}
> +

If the inlining_info becomes a member of the diagnostic_info, does the
need for this "set" callback go away?


[...snip...]

Hope this is constructive and makes sense; thanks again for the patch
Dave


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 1/4] introduce diagnostic infrastructure changes (PR 98512)
  2021-06-11 17:04         ` David Malcolm
@ 2021-06-15 23:00           ` Martin Sebor
  2021-06-28 18:10             ` [PING][PATCH " Martin Sebor
  2021-06-30 22:55             ` [PATCH " David Malcolm
  0 siblings, 2 replies; 44+ messages in thread
From: Martin Sebor @ 2021-06-15 23:00 UTC (permalink / raw)
  To: David Malcolm, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 9280 bytes --]

On 6/11/21 11:04 AM, David Malcolm wrote:
> On Thu, 2021-06-10 at 17:26 -0600, Martin Sebor wrote:
>> This diff introduces the diagnostic infrastructure changes to support
>> controlling warnings at any call site in the inlining stack and
>> printing
>> the inlining context without the %K and %G directives.
> 
> Thanks for working on this, looks very promising.
> 
>> Improve warning suppression for inlined functions.
>>
>> Resolves:
>> PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at declaration site
>> PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective in conjunction with alias attribute
> 
> Am I right in thinking that you add test coverage for both of these in
> patch 2 of the kit?

Yes, the tests depend on the changes in patch 2 (some existing tests
fail with just patch 1 applied because the initial location passed
to warning_t() is different than with it).

> 
>>
>> gcc/ChangeLog:
>>
>> 	* diagnostic.c (update_inlining_context): New.
>> 	(update_effective_level_from_pragmas): Handle inlining context.
>> 	(diagnostic_report_diagnostic): Same.
>> 	* diagnostic.h (struct diagnostic_info): Add ctor.
>> 	(struct diagnostic_context): Add members.
>> 	* tree-diagnostic.c (get_inlining_locations): New.
>> 	(set_inlining_location): New.
>> 	(tree_diagnostics_defaults): Set new callback pointers.
> 
> [..snip...]
> 
>> @@ -1204,7 +1256,7 @@ diagnostic_report_diagnostic (diagnostic_context *context,
>>         /* We do this to avoid giving the message for -pedantic-errors.  */
>>         orig_diag_kind = diagnostic->kind;
>>       }
>> -
>> +
> 
> Stray whitespace change?  Though it looks like a fix of a stray space,
> so not a big deal.
> 
>>     if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
>>       return false;
>>   
> 
> [..snip...]
> 
>> diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
>> index 1b9d6b1f64d..b95ee23dda0 100644
>> --- a/gcc/diagnostic.h
>> +++ b/gcc/diagnostic.h
>> @@ -87,6 +87,10 @@ enum diagnostics_extra_output_kind
>>      list in diagnostic.def.  */
>>   struct diagnostic_info
>>   {
>> +  diagnostic_info ()
>> +    : message (), richloc (), metadata (), x_data (), kind (), option_index ()
>> +  { }
>> +
> 
> Why does the patch add this ctor?

The new code relies on x_data being initially null, and to make it so
I considered two alternatives explicitly initialize the struct or add
a ctor.  I had started with the former but wound up with the latter
after a few ICEs.


> 
>>     /* Text to be formatted.  */
>>     text_info message;
>>   
>> @@ -343,6 +347,32 @@ struct diagnostic_context
>>   
>>     /* Callback for final cleanup.  */
>>     void (*final_cb) (diagnostic_context *context);
>> +
>> +  /* The inlining context of the diagnostic (may have just one
>> +     element if a diagnostic is not for an inlined expression).  */
>> +  struct inlining_ctx
>> +  {
>> +    void reset ()
>> +    {
>> +      ilocs.release ();
>> +      loc = UNKNOWN_LOCATION;
>> +      ao = NULL;
>> +      allsyslocs = false;
>> +    }
>> +
>> +    /* Locations along the inlining stack.  */
>> +    auto_vec<location_t, 8> ilocs;
>> +    /* The locus of the diagnostic. */
>> +    location_t loc;
>> +    /* The abstract origin of the location.  */
>> +    void *ao;
>> +    /* Set of every ILOCS element is in a system header.  */
>> +    bool allsyslocs;
>> +  } ictx;
> 
> Why is the inlining ctx part of the diagnostic_context?  That feels
> strange to me. This inlining information relates to a particular
> diagnostic, so it seems more appropriate to me that it should be part
> of the diagnostic_info (which might thus necessitate having a ctor for
> diagnostic_info).  Doing that might avoid the need for "reset", if I'm
> right in assuming that getting the data is done once per diagnostic
> during diagnostic_report_diagnostic.

I thought that's what you'd suggested when we spoke but I must have
have misremembered or misunderstood.  I agree it fits better in
the diagnostic_info and I've moved it there.

> 
> Alternatively, could this be state that's created on the stack during
> diagnostic_report_diagnostic and passed around by pointer as another
> parameter?  (putting it in diagnostic_info might be simplest though)

Yes, that sounds good to me too.

> 
> Maybe rename it to "inlining_info"?
> 
> How involved would it be to make it be a class with private fields?

Not too involved.  It would involve adding accessors and modifiers
for all of them.  I would normally be in favor of it but I don't
think it's worth the effort for such a small struct that's a member
of another that doesn't use proper encapsulation.  If/when the other
classes in this area are encapsulated it might be a good time to do
it for this class too.

> 
> Can the field names have "m_" prefixes, please?

Done.

> 
>> +  /* Callbacks to get and set the inlining context.  */
> 
> Probably should spell out in the comment here that doing so requires
> knowledge of trees, which is why it's a callback (to avoid diagnostic.c
> from having to know about trees).

Done.

> 
>> +  void (*get_locations_cb)(diagnostic_context *, diagnostic_info *);
>> +  void (*set_location_cb)(const diagnostic_context *, diagnostic_info *);
>>   };
>>   
>>   static inline void
>> diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
>> index 95b8ef30070..a8c5484849a 100644
>> --- a/gcc/tree-diagnostic.c
>> +++ b/gcc/tree-diagnostic.c
>> @@ -305,6 +305,84 @@ default_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
>>     return true;
>>   }
>>   
>> +/* Get the inlining stack corresponding to the DIAGNOSTIC location.  */
>> +
>> +static void
>> +get_inlining_locations (diagnostic_context *context,
>> +			diagnostic_info *diagnostic)
>> +{
>> +  context->ictx.reset ();
>> +
>> +  location_t loc = diagnostic_location (diagnostic);
>> +  tree block = LOCATION_BLOCK (loc);
>> +
>> +  /* Count the number of locations in system headers.  When all are,
>> +     warnings are suppressed by -Wno-system-headers.  Otherwise, they
>> +     involve some user code, possibly inlined into a function in a system
>> +     header, and are not treated as coming from system headers.  */
>> +  unsigned nsyslocs = 0;
>> +
>> +  while (block && TREE_CODE (block) == BLOCK
>> +	 && BLOCK_ABSTRACT_ORIGIN (block))
>> +    {
>> +      tree ao = BLOCK_ABSTRACT_ORIGIN (block);
>> +      if (TREE_CODE (ao) == FUNCTION_DECL)
>> +	{
>> +	  if (!context->ictx.ao)
>> +	    context->ictx.ao = block;
>> +
>> +	  location_t loc = BLOCK_SOURCE_LOCATION (block);
>> +	  context->ictx.ilocs.safe_push (loc);
>> +	  if (in_system_header_at (loc))
>> +	    ++nsyslocs;
>> +	}
>> +      else if (TREE_CODE (ao) != BLOCK)
>> +	break;
>> +
>> +      block = BLOCK_SUPERCONTEXT (block);
>> +    }
>> +
>> +  if (context->ictx.ilocs.length ())
>> +    {
>> +      /* When there is an inlining context use the macro expansion
>> +	 location for the original location and bump up NSYSLOCS if
>> +	 it's in a system header since it's not counted above.  */
>> +      context->ictx.loc = expansion_point_location_if_in_system_header (loc);
>> +      if (context->ictx.loc != loc)
>> +	++nsyslocs;
>> +    }
>> +  else
>> +    {
>> +      /* When there's no inlining context use the original location
>> +	 and set NSYSLOCS accordingly.  */
>> +      context->ictx.loc = loc;
>> +      nsyslocs = in_system_header_at (loc) != 0;
>> +    }
>> +
>> +  context->ictx.ilocs.safe_push (context->ictx.loc);
>> +
>> +  /* Set if all locations are in a system header.  */
>> +  context->ictx.allsyslocs = nsyslocs == context->ictx.ilocs.length ();;
> 
> Surplus trailing semicolon.
> 
> Maybe store nsyslocs as private member data ("m_nsyslocs"), and have an
> all_system_locations_p accessor?  (since if I'm reading things right
> that's the question that diagnostic_report_diagnostic is asking of the
> inlining_info that we need this information for)

nsyslocs is only needed in this function.  The bit of data we need
is context->ictx.allsyslocs (a bool).  I could make it private and
add an accessor but as I said above I don't think that would gain
us anything unless we also did that for all the other members of
diagnostic_info as well.

>> +/* Set the inlining location for to the DIAGNOSTIC based on the saved
>> +   inlining context.  */
>> +
>> +static void
>> +set_inlining_location (const diagnostic_context *context,
>> +		       diagnostic_info *diagnostic)
>> +{
>> +  if (!pp_ti_abstract_origin (&diagnostic->message)
>> +      || !context->ictx.ao
>> +      || context->ictx.loc == UNKNOWN_LOCATION)
>> +    /* Do nothing when there's no inlining context.  */
>> +    return;
>> +
>> +  *pp_ti_abstract_origin (&diagnostic->message) = (tree)context->ictx.ao;
>> +  diagnostic->message.set_location (0, context->ictx.loc,
>> +				    SHOW_RANGE_WITH_CARET);
>> +}
>> +
> 
> If the inlining_info becomes a member of the diagnostic_info, does the
> need for this "set" callback go away?

Yes, that's a good observation!  In the attached revision I was able
to do away with this callback and simplify the whole implementation
a bit thanks to it.

> 
> 
> [...snip...]
> 
> Hope this is constructive and makes sense; thanks again for the patch
> Dave
> 

Yep, thanks.  Please see the attached revision.

Martin

[-- Attachment #2: gcc-98512-1.diff --]
[-- Type: text/x-patch, Size: 11926 bytes --]

Improve warning suppression for inlined functions [PR 98512].

Resolves:
PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at declaration site
PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective in conjunction with alias attribute

gcc/ChangeLog:

	* diagnostic.c (update_inlining_context): New.
	(update_effective_level_from_pragmas): Handle inlining context.
	(diagnostic_enabled): Same.
	(diagnostic_report_diagnostic): Same.
	* diagnostic.h (struct diagnostic_info): Add ctor.
	(struct diagnostic_context): Add new member.
	* tree-diagnostic.c (set_inlining_locations): New.
	(tree_diagnostics_defaults): Set new callback pointer.

diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index d58586f2526..3a22d4d26a6 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -991,51 +991,93 @@ print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
   pp_set_prefix (pp, saved_prefix);
 }
 
-/* Update the diag_class of DIAGNOSTIC based on its location
-   relative to any
+/* Update the inlininig context in CONTEXT for a DIAGNOSTIC.  */
+
+static void
+update_inlining_context (diagnostic_context *context,
+			 diagnostic_info *diagnostic)
+{
+  auto &ilocs = diagnostic->m_iinfo.m_ilocs;
+
+  if (context->set_locations_cb)
+    {
+      /* Retrieve the locations into which the expression about to be
+	 diagnosed has been inlined, including those of all the callers
+	 all the way down the inlining stack.  */
+      context->set_locations_cb (context, diagnostic);
+      location_t loc = diagnostic->m_iinfo.m_ilocs.last ();
+      if (diagnostic->m_iinfo.m_ao && loc != UNKNOWN_LOCATION)
+	diagnostic->message.set_location (0, loc, SHOW_RANGE_WITH_CARET);
+    }
+  else
+    {
+      /* When there's no callback use just the one location provided
+	 by the caller of the diagnostic function.  */
+      location_t loc = diagnostic_location (diagnostic);
+      ilocs.safe_push (loc);
+      diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
+    }
+}
+
+/* Update the kind of DIAGNOSTIC based on its location(s), including
+   any of those in its inlining context, relative to any
      #pragma GCC diagnostic
    directives recorded within CONTEXT.
 
-   Return the new diag_class of DIAGNOSTIC if it was updated, or
-   DK_UNSPECIFIED otherwise.  */
+   Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
+   otherwise.  */
 
 static diagnostic_t
 update_effective_level_from_pragmas (diagnostic_context *context,
 				     diagnostic_info *diagnostic)
 {
-  diagnostic_t diag_class = DK_UNSPECIFIED;
-
-  if (context->n_classification_history > 0)
+  if (diagnostic->m_iinfo.m_allsyslocs && !context->dc_warn_system_headers)
     {
-      location_t location = diagnostic_location (diagnostic);
+      /* Ignore the diagnostic if all the inlined locations are
+	 in system headers and -Wno-system-headers is in effect.  */
+      diagnostic->kind = DK_IGNORED;
+      return DK_IGNORED;
+    }
 
+  if (context->n_classification_history <= 0)
+    return DK_UNSPECIFIED;
+
+  /* Iterate over the locations, checking the diagnostic disposition
+     for the diagnostic at each.  If it's explicitly set as opposed
+     to unspecified, update the disposition for this instance of
+     the diagnostic and return it.  */
+  for (location_t loc: diagnostic->m_iinfo.m_ilocs)
+    {
       /* FIXME: Stupid search.  Optimize later. */
       for (int i = context->n_classification_history - 1; i >= 0; i --)
 	{
-	  if (linemap_location_before_p
-	      (line_table,
-	       context->classification_history[i].location,
-	       location))
+	  const diagnostic_classification_change_t &hist
+	    = context->classification_history[i];
+
+	  location_t pragloc = hist.location;
+	  if (!linemap_location_before_p (line_table, pragloc, loc))
+	    continue;
+
+	  if (hist.kind == (int) DK_POP)
 	    {
-	      if (context->classification_history[i].kind == (int) DK_POP)
-		{
-		  i = context->classification_history[i].option;
-		  continue;
-		}
-	      int option = context->classification_history[i].option;
-	      /* The option 0 is for all the diagnostics.  */
-	      if (option == 0 || option == diagnostic->option_index)
-		{
-		  diag_class = context->classification_history[i].kind;
-		  if (diag_class != DK_UNSPECIFIED)
-		    diagnostic->kind = diag_class;
-		  break;
-		}
+	      /* Move on to the next region.  */
+	      i = hist.option;
+	      continue;
+	    }
+
+	  int option = hist.option;
+	  /* The option 0 is for all the diagnostics.  */
+	  if (option == 0 || option == diagnostic->option_index)
+	    {
+	      diagnostic_t kind = hist.kind;
+	      if (kind != DK_UNSPECIFIED)
+		diagnostic->kind = kind;
+	      return kind;
 	    }
 	}
     }
 
-  return diag_class;
+  return DK_UNSPECIFIED;
 }
 
 /* Generate a URL string describing CWE.  The caller is responsible for
@@ -1129,6 +1171,9 @@ static bool
 diagnostic_enabled (diagnostic_context *context,
 		    diagnostic_info *diagnostic)
 {
+  /* Update the inlining context for this diagnostic.  */
+  update_inlining_context (context, diagnostic);
+
   /* Diagnostics with no option or -fpermissive are always enabled.  */
   if (!diagnostic->option_index
       || diagnostic->option_index == permissive_error_option (context))
@@ -1194,9 +1239,17 @@ diagnostic_report_diagnostic (diagnostic_context *context,
 
   /* Give preference to being able to inhibit warnings, before they
      get reclassified to something else.  */
-  if ((diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
-      && !diagnostic_report_warnings_p (context, location))
-    return false;
+  bool report_warning_p = true;
+  if (diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
+    {
+      if (context->dc_inhibit_warnings)
+	return false;
+      /* Remember the result of the overall system header warning setting
+	 but proceed to also check the inlining context.  */
+      report_warning_p = diagnostic_report_warnings_p (context, location);
+      if (!report_warning_p && diagnostic->kind == DK_PEDWARN)
+	return false;
+    }
 
   if (diagnostic->kind == DK_PEDWARN)
     {
@@ -1204,7 +1257,7 @@ diagnostic_report_diagnostic (diagnostic_context *context,
       /* We do this to avoid giving the message for -pedantic-errors.  */
       orig_diag_kind = diagnostic->kind;
     }
- 
+
   if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
     return false;
 
@@ -1228,9 +1281,19 @@ diagnostic_report_diagnostic (diagnostic_context *context,
       && diagnostic->kind == DK_WARNING)
     diagnostic->kind = DK_ERROR;
 
+  diagnostic->message.x_data = &diagnostic->x_data;
+
+  /* Check to see if the diagnostic is enabled at the location and
+     not disabled by #pragma GCC diagnostic anywhere along the inlining
+     stack.  .  */
   if (!diagnostic_enabled (context, diagnostic))
     return false;
 
+  if (!report_warning_p && diagnostic->m_iinfo.m_allsyslocs)
+    /* Bail if the warning is not to be reported because all locations
+       in the inlining stack (if there is one) are in system headers.  */
+    return false;
+
   if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
     diagnostic_check_max_errors (context);
 
@@ -1270,8 +1333,6 @@ diagnostic_report_diagnostic (diagnostic_context *context,
     }
   context->diagnostic_group_emission_count++;
 
-  diagnostic->message.x_data = &diagnostic->x_data;
-  diagnostic->x_data = NULL;
   pp_format (context->printer, &diagnostic->message);
   (*diagnostic_starter (context)) (context, diagnostic);
   pp_output_formatted_text (context->printer);
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 1b9d6b1f64d..9d02615fb7a 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -87,6 +87,11 @@ enum diagnostics_extra_output_kind
    list in diagnostic.def.  */
 struct diagnostic_info
 {
+  diagnostic_info ()
+    : message (), richloc (), metadata (), x_data (), kind (), option_index (),
+      m_iinfo ()
+  { }
+
   /* Text to be formatted.  */
   text_info message;
 
@@ -103,6 +108,18 @@ struct diagnostic_info
   diagnostic_t kind;
   /* Which OPT_* directly controls this diagnostic.  */
   int option_index;
+
+  /* Inlining context containing locations for each call site along
+     the inlining stack.  */
+  struct inlining_info
+  {
+    /* Locations along the inlining stack.  */
+    auto_vec<location_t, 8> m_ilocs;
+    /* The abstract origin of the location.  */
+    void *m_ao;
+    /* Set if every M_ILOCS element is in a system header.  */
+    bool m_allsyslocs;
+  } m_iinfo;
 };
 
 /* Each time a diagnostic's classification is changed with a pragma,
@@ -343,6 +360,12 @@ struct diagnostic_context
 
   /* Callback for final cleanup.  */
   void (*final_cb) (diagnostic_context *context);
+
+  /* Callback to set the locations of call sites along the inlining
+     stack corresponding to a diagnostic location.  Needed to traverse
+     the BLOCK_SUPERCONTEXT() chain hanging off the LOCATION_BLOCK()
+     of a diagnostic's location.  */
+  void (*set_locations_cb)(diagnostic_context *, diagnostic_info *);
 };
 
 static inline void
diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
index 95b8ef30070..1b636d72a29 100644
--- a/gcc/tree-diagnostic.c
+++ b/gcc/tree-diagnostic.c
@@ -305,6 +305,73 @@ default_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
   return true;
 }
 
+/* Set the locations of call sites along the inlining stack corresponding
+   to the DIAGNOSTIC location.  */
+
+static void
+set_inlining_locations (diagnostic_context *,
+			diagnostic_info *diagnostic)
+{
+  location_t loc = diagnostic_location (diagnostic);
+  tree block = LOCATION_BLOCK (loc);
+
+  /* Count the number of locations in system headers.  When all are,
+     warnings are suppressed by -Wno-system-headers.  Otherwise, they
+     involve some user code, possibly inlined into a function in a system
+     header, and are not treated as coming from system headers.  */
+  unsigned nsyslocs = 0;
+
+  /* Use a reference to the vector of locations for convenience.  */
+  auto &ilocs = diagnostic->m_iinfo.m_ilocs;
+
+  while (block && TREE_CODE (block) == BLOCK
+	 && BLOCK_ABSTRACT_ORIGIN (block))
+    {
+      tree ao = BLOCK_ABSTRACT_ORIGIN (block);
+      if (TREE_CODE (ao) == FUNCTION_DECL)
+	{
+	  if (!diagnostic->m_iinfo.m_ao)
+	    diagnostic->m_iinfo.m_ao = block;
+
+	  location_t bsloc = BLOCK_SOURCE_LOCATION (block);
+	  ilocs.safe_push (bsloc);
+	  if (in_system_header_at (bsloc))
+	    ++nsyslocs;
+	}
+      else if (TREE_CODE (ao) != BLOCK)
+	break;
+
+      block = BLOCK_SUPERCONTEXT (block);
+    }
+
+  if (ilocs.length ())
+    {
+      /* When there is an inlining context use the macro expansion
+	 location for the original location and bump up NSYSLOCS if
+	 it's in a system header since it's not counted above.  */
+      location_t sysloc = expansion_point_location_if_in_system_header (loc);
+      if (sysloc != loc)
+	{
+	  loc = sysloc;
+	  ++nsyslocs;
+	}
+    }
+  else
+    {
+      /* When there's no inlining context use the original location
+	 and set NSYSLOCS accordingly.  */
+      nsyslocs = in_system_header_at (loc) != 0;
+    }
+
+  ilocs.safe_push (loc);
+
+  /* Set if all locations are in a system header.  */
+  diagnostic->m_iinfo.m_allsyslocs = nsyslocs == ilocs.length ();
+
+  if (tree *ao = pp_ti_abstract_origin (&diagnostic->message))
+    *ao = (tree)diagnostic->m_iinfo.m_ao;
+}
+
 /* Sets CONTEXT to use language independent diagnostics.  */
 void
 tree_diagnostics_defaults (diagnostic_context *context)
@@ -314,4 +381,5 @@ tree_diagnostics_defaults (diagnostic_context *context)
   diagnostic_format_decoder (context) = default_tree_printer;
   context->print_path = default_tree_diagnostic_path_printer;
   context->make_json_for_path = default_tree_make_json_for_path;
+  context->set_locations_cb = set_inlining_locations;
 }

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PING][PATCH 1/4] introduce diagnostic infrastructure changes (PR 98512)
  2021-06-15 23:00           ` Martin Sebor
@ 2021-06-28 18:10             ` Martin Sebor
  2021-06-30 22:55             ` [PATCH " David Malcolm
  1 sibling, 0 replies; 44+ messages in thread
From: Martin Sebor @ 2021-06-28 18:10 UTC (permalink / raw)
  To: David Malcolm, gcc-patches

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/572839.html

On 6/15/21 5:00 PM, Martin Sebor wrote:
> On 6/11/21 11:04 AM, David Malcolm wrote:
>> On Thu, 2021-06-10 at 17:26 -0600, Martin Sebor wrote:
>>> This diff introduces the diagnostic infrastructure changes to support
>>> controlling warnings at any call site in the inlining stack and
>>> printing
>>> the inlining context without the %K and %G directives.
>>
>> Thanks for working on this, looks very promising.
>>
>>> Improve warning suppression for inlined functions.
>>>
>>> Resolves:
>>> PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at 
>>> declaration site
>>> PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective in 
>>> conjunction with alias attribute
>>
>> Am I right in thinking that you add test coverage for both of these in
>> patch 2 of the kit?
> 
> Yes, the tests depend on the changes in patch 2 (some existing tests
> fail with just patch 1 applied because the initial location passed
> to warning_t() is different than with it).
> 
>>
>>>
>>> gcc/ChangeLog:
>>>
>>>     * diagnostic.c (update_inlining_context): New.
>>>     (update_effective_level_from_pragmas): Handle inlining context.
>>>     (diagnostic_report_diagnostic): Same.
>>>     * diagnostic.h (struct diagnostic_info): Add ctor.
>>>     (struct diagnostic_context): Add members.
>>>     * tree-diagnostic.c (get_inlining_locations): New.
>>>     (set_inlining_location): New.
>>>     (tree_diagnostics_defaults): Set new callback pointers.
>>
>> [..snip...]
>>
>>> @@ -1204,7 +1256,7 @@ diagnostic_report_diagnostic 
>>> (diagnostic_context *context,
>>>         /* We do this to avoid giving the message for 
>>> -pedantic-errors.  */
>>>         orig_diag_kind = diagnostic->kind;
>>>       }
>>> -
>>> +
>>
>> Stray whitespace change?  Though it looks like a fix of a stray space,
>> so not a big deal.
>>
>>>     if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
>>>       return false;
>>
>> [..snip...]
>>
>>> diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
>>> index 1b9d6b1f64d..b95ee23dda0 100644
>>> --- a/gcc/diagnostic.h
>>> +++ b/gcc/diagnostic.h
>>> @@ -87,6 +87,10 @@ enum diagnostics_extra_output_kind
>>>      list in diagnostic.def.  */
>>>   struct diagnostic_info
>>>   {
>>> +  diagnostic_info ()
>>> +    : message (), richloc (), metadata (), x_data (), kind (), 
>>> option_index ()
>>> +  { }
>>> +
>>
>> Why does the patch add this ctor?
> 
> The new code relies on x_data being initially null, and to make it so
> I considered two alternatives explicitly initialize the struct or add
> a ctor.  I had started with the former but wound up with the latter
> after a few ICEs.
> 
> 
>>
>>>     /* Text to be formatted.  */
>>>     text_info message;
>>> @@ -343,6 +347,32 @@ struct diagnostic_context
>>>     /* Callback for final cleanup.  */
>>>     void (*final_cb) (diagnostic_context *context);
>>> +
>>> +  /* The inlining context of the diagnostic (may have just one
>>> +     element if a diagnostic is not for an inlined expression).  */
>>> +  struct inlining_ctx
>>> +  {
>>> +    void reset ()
>>> +    {
>>> +      ilocs.release ();
>>> +      loc = UNKNOWN_LOCATION;
>>> +      ao = NULL;
>>> +      allsyslocs = false;
>>> +    }
>>> +
>>> +    /* Locations along the inlining stack.  */
>>> +    auto_vec<location_t, 8> ilocs;
>>> +    /* The locus of the diagnostic. */
>>> +    location_t loc;
>>> +    /* The abstract origin of the location.  */
>>> +    void *ao;
>>> +    /* Set of every ILOCS element is in a system header.  */
>>> +    bool allsyslocs;
>>> +  } ictx;
>>
>> Why is the inlining ctx part of the diagnostic_context?  That feels
>> strange to me. This inlining information relates to a particular
>> diagnostic, so it seems more appropriate to me that it should be part
>> of the diagnostic_info (which might thus necessitate having a ctor for
>> diagnostic_info).  Doing that might avoid the need for "reset", if I'm
>> right in assuming that getting the data is done once per diagnostic
>> during diagnostic_report_diagnostic.
> 
> I thought that's what you'd suggested when we spoke but I must have
> have misremembered or misunderstood.  I agree it fits better in
> the diagnostic_info and I've moved it there.
> 
>>
>> Alternatively, could this be state that's created on the stack during
>> diagnostic_report_diagnostic and passed around by pointer as another
>> parameter?  (putting it in diagnostic_info might be simplest though)
> 
> Yes, that sounds good to me too.
> 
>>
>> Maybe rename it to "inlining_info"?
>>
>> How involved would it be to make it be a class with private fields?
> 
> Not too involved.  It would involve adding accessors and modifiers
> for all of them.  I would normally be in favor of it but I don't
> think it's worth the effort for such a small struct that's a member
> of another that doesn't use proper encapsulation.  If/when the other
> classes in this area are encapsulated it might be a good time to do
> it for this class too.
> 
>>
>> Can the field names have "m_" prefixes, please?
> 
> Done.
> 
>>
>>> +  /* Callbacks to get and set the inlining context.  */
>>
>> Probably should spell out in the comment here that doing so requires
>> knowledge of trees, which is why it's a callback (to avoid diagnostic.c
>> from having to know about trees).
> 
> Done.
> 
>>
>>> +  void (*get_locations_cb)(diagnostic_context *, diagnostic_info *);
>>> +  void (*set_location_cb)(const diagnostic_context *, 
>>> diagnostic_info *);
>>>   };
>>>   static inline void
>>> diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
>>> index 95b8ef30070..a8c5484849a 100644
>>> --- a/gcc/tree-diagnostic.c
>>> +++ b/gcc/tree-diagnostic.c
>>> @@ -305,6 +305,84 @@ default_tree_printer (pretty_printer *pp, 
>>> text_info *text, const char *spec,
>>>     return true;
>>>   }
>>> +/* Get the inlining stack corresponding to the DIAGNOSTIC location.  */
>>> +
>>> +static void
>>> +get_inlining_locations (diagnostic_context *context,
>>> +            diagnostic_info *diagnostic)
>>> +{
>>> +  context->ictx.reset ();
>>> +
>>> +  location_t loc = diagnostic_location (diagnostic);
>>> +  tree block = LOCATION_BLOCK (loc);
>>> +
>>> +  /* Count the number of locations in system headers.  When all are,
>>> +     warnings are suppressed by -Wno-system-headers.  Otherwise, they
>>> +     involve some user code, possibly inlined into a function in a 
>>> system
>>> +     header, and are not treated as coming from system headers.  */
>>> +  unsigned nsyslocs = 0;
>>> +
>>> +  while (block && TREE_CODE (block) == BLOCK
>>> +     && BLOCK_ABSTRACT_ORIGIN (block))
>>> +    {
>>> +      tree ao = BLOCK_ABSTRACT_ORIGIN (block);
>>> +      if (TREE_CODE (ao) == FUNCTION_DECL)
>>> +    {
>>> +      if (!context->ictx.ao)
>>> +        context->ictx.ao = block;
>>> +
>>> +      location_t loc = BLOCK_SOURCE_LOCATION (block);
>>> +      context->ictx.ilocs.safe_push (loc);
>>> +      if (in_system_header_at (loc))
>>> +        ++nsyslocs;
>>> +    }
>>> +      else if (TREE_CODE (ao) != BLOCK)
>>> +    break;
>>> +
>>> +      block = BLOCK_SUPERCONTEXT (block);
>>> +    }
>>> +
>>> +  if (context->ictx.ilocs.length ())
>>> +    {
>>> +      /* When there is an inlining context use the macro expansion
>>> +     location for the original location and bump up NSYSLOCS if
>>> +     it's in a system header since it's not counted above.  */
>>> +      context->ictx.loc = 
>>> expansion_point_location_if_in_system_header (loc);
>>> +      if (context->ictx.loc != loc)
>>> +    ++nsyslocs;
>>> +    }
>>> +  else
>>> +    {
>>> +      /* When there's no inlining context use the original location
>>> +     and set NSYSLOCS accordingly.  */
>>> +      context->ictx.loc = loc;
>>> +      nsyslocs = in_system_header_at (loc) != 0;
>>> +    }
>>> +
>>> +  context->ictx.ilocs.safe_push (context->ictx.loc);
>>> +
>>> +  /* Set if all locations are in a system header.  */
>>> +  context->ictx.allsyslocs = nsyslocs == context->ictx.ilocs.length 
>>> ();;
>>
>> Surplus trailing semicolon.
>>
>> Maybe store nsyslocs as private member data ("m_nsyslocs"), and have an
>> all_system_locations_p accessor?  (since if I'm reading things right
>> that's the question that diagnostic_report_diagnostic is asking of the
>> inlining_info that we need this information for)
> 
> nsyslocs is only needed in this function.  The bit of data we need
> is context->ictx.allsyslocs (a bool).  I could make it private and
> add an accessor but as I said above I don't think that would gain
> us anything unless we also did that for all the other members of
> diagnostic_info as well.
> 
>>> +/* Set the inlining location for to the DIAGNOSTIC based on the saved
>>> +   inlining context.  */
>>> +
>>> +static void
>>> +set_inlining_location (const diagnostic_context *context,
>>> +               diagnostic_info *diagnostic)
>>> +{
>>> +  if (!pp_ti_abstract_origin (&diagnostic->message)
>>> +      || !context->ictx.ao
>>> +      || context->ictx.loc == UNKNOWN_LOCATION)
>>> +    /* Do nothing when there's no inlining context.  */
>>> +    return;
>>> +
>>> +  *pp_ti_abstract_origin (&diagnostic->message) = 
>>> (tree)context->ictx.ao;
>>> +  diagnostic->message.set_location (0, context->ictx.loc,
>>> +                    SHOW_RANGE_WITH_CARET);
>>> +}
>>> +
>>
>> If the inlining_info becomes a member of the diagnostic_info, does the
>> need for this "set" callback go away?
> 
> Yes, that's a good observation!  In the attached revision I was able
> to do away with this callback and simplify the whole implementation
> a bit thanks to it.
> 
>>
>>
>> [...snip...]
>>
>> Hope this is constructive and makes sense; thanks again for the patch
>> Dave
>>
> 
> Yep, thanks.  Please see the attached revision.
> 
> Martin


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PING][PATCH 2/4] remove %G and %K from calls in front end and middle end (PR 98512)
  2021-06-10 23:27       ` [PATCH 2/4] remove %G and %K from calls in front end and middle end " Martin Sebor
@ 2021-06-30 15:39         ` Martin Sebor
  2021-06-30 19:45           ` Martin Sebor
  0 siblings, 1 reply; 44+ messages in thread
From: Martin Sebor @ 2021-06-30 15:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm, Jeff Law, Aldy Hernandez

[-- Attachment #1: Type: text/plain, Size: 600 bytes --]

Ping.  Attached is the same patch rebased on top the latest trunk.

As discussed in the review of Aldy's recent changes to the backwards
threader, he has run into the same bug the patch fixes.  Getting this
patch set reviewed and approved would be helpful in keeping him from
having to work around the bug.

https://gcc.gnu.org/pipermail/gcc/2021-June/236608.html

On 6/10/21 5:27 PM, Martin Sebor wrote:
> This diff removes the uses of %G and %K from all warning_at() calls
> throughout GCC front end and middle end.  The inlining context is
> included in diagnostic output whenever it's present.


[-- Attachment #2: gcc-98512-2.diff --]
[-- Type: text/x-patch, Size: 73166 bytes --]

Improve warning suppression for inlined functions.

Resolves:
PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at declaration site
PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective in conjunction with alias attribute

gcc/ChangeLog:

	* builtins.c (warn_string_no_nul): Remove %G.
	(maybe_warn_for_bound): Same.
	(warn_for_access): Same.
	(check_access): Same.
	(check_strncat_sizes): Same.
	(expand_builtin_strncat): Same.
	(expand_builtin_strncmp): Same.
	(expand_builtin): Same.
	(expand_builtin_object_size): Same.
	(warn_dealloc_offset): Same.
	(maybe_emit_free_warning): Same.
	* calls.c (maybe_warn_alloc_args_overflow): Same.
	(maybe_warn_nonstring_arg): Same.
	(maybe_warn_rdwr_sizes): Same.
	* expr.c (expand_expr_real_1): Remove %K.
	* gimple-fold.c (gimple_fold_builtin_strncpy): Remove %G.
	(gimple_fold_builtin_strncat): Same.
	* gimple-ssa-sprintf.c (format_directive): Same.
	(handle_printf_call): Same.
	* gimple-ssa-warn-alloca.c (pass_walloca::execute): Same.
	* gimple-ssa-warn-restrict.c (maybe_diag_overlap): Same.
	(maybe_diag_access_bounds): Same.  Call gimple_location.
	(check_bounds_or_overlap): Same.
	* trans-mem.c (ipa_tm_scan_irr_block): Remove %K.  Simplify.
	* tree-ssa-ccp.c (pass_post_ipa_warn::execute): Remove %G.
	* tree-ssa-strlen.c (maybe_warn_overflow): Same.
	(maybe_diag_stxncpy_trunc): Same.
	(handle_builtin_stxncpy_strncat): Same.
	(maybe_warn_pointless_strcmp): Same.
	* tree-ssa-uninit.c (maybe_warn_operand): Same.

gcc/testsuite/ChangeLog:

	* gcc.dg/Wfree-nonheap-object-4.c: Tighten up.
	* gcc.dg/Wobjsize-1.c: Prune expected output.
	* gcc.dg/Warray-bounds-71.c: New test.
	* gcc.dg/Warray-bounds-71.h: New test.
	* gcc.dg/Warray-bounds-72.c: New test.
	* gcc.dg/Warray-bounds-73.c: New test.
	* gcc.dg/Warray-bounds-74.c: New test.
	* gcc.dg/Warray-bounds-75.c: New test.
	* gcc.dg/Wfree-nonheap-object-5.c: New test.
	* gcc.dg/pragma-diag-10.c: New test.
	* gcc.dg/pragma-diag-9.c: New test.
	* gcc.dg/uninit-suppress_3.c: New test.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index e5e39386a93..e59fa322729 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -1126,30 +1126,30 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
 	{
 	  if (wi::ltu_p (maxsiz, bndrng[0]))
 	    warned = warning_at (loc, opt,
-				 "%K%qD specified bound %s exceeds "
+				 "%qD specified bound %s exceeds "
 				 "maximum object size %E",
-				 expr, func, bndstr, maxobjsize);
+				 func, bndstr, maxobjsize);
 	  else
 	    {
 	      bool maybe = wi::to_wide (size) == bndrng[0];
 	      warned = warning_at (loc, opt,
 				   exact
-				   ? G_("%K%qD specified bound %s exceeds "
+				   ? G_("%qD specified bound %s exceeds "
 					"the size %E of unterminated array")
 				   : (maybe
-				      ? G_("%K%qD specified bound %s may "
+				      ? G_("%qD specified bound %s may "
 					   "exceed the size of at most %E "
 					   "of unterminated array")
-				      : G_("%K%qD specified bound %s exceeds "
+				      : G_("%qD specified bound %s exceeds "
 					   "the size of at most %E "
 					   "of unterminated array")),
-				   expr, func, bndstr, size);
+				   func, bndstr, size);
 	    }
 	}
       else
 	warned = warning_at (loc, opt,
-			     "%K%qD argument missing terminating nul",
-			     expr, func);
+			     "%qD argument missing terminating nul",
+			     func);
     }
   else
     {
@@ -3969,35 +3969,34 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func,
 	    warned = (func
 		      ? warning_at (loc, opt,
 				    (maybe
-				     ? G_("%K%qD specified bound %E may "
+				     ? G_("%qD specified bound %E may "
 					  "exceed maximum object size %E")
-				     : G_("%K%qD specified bound %E "
+				     : G_("%qD specified bound %E "
 					  "exceeds maximum object size %E")),
-				    exp, func, bndrng[0], maxobjsize)
+				    func, bndrng[0], maxobjsize)
 		      : warning_at (loc, opt,
 				    (maybe
-				     ? G_("%Kspecified bound %E may "
+				     ? G_("specified bound %E may "
 					  "exceed maximum object size %E")
-				     : G_("%Kspecified bound %E "
+				     : G_("specified bound %E "
 					  "exceeds maximum object size %E")),
-				    exp, bndrng[0], maxobjsize));
+				    bndrng[0], maxobjsize));
 	  else
 	    warned = (func
 		      ? warning_at (loc, opt,
 				    (maybe
-				     ? G_("%K%qD specified bound [%E, %E] may "
+				     ? G_("%qD specified bound [%E, %E] may "
 					  "exceed maximum object size %E")
-				     : G_("%K%qD specified bound [%E, %E] "
+				     : G_("%qD specified bound [%E, %E] "
 					  "exceeds maximum object size %E")),
-				    exp, func,
-				    bndrng[0], bndrng[1], maxobjsize)
+				    func, bndrng[0], bndrng[1], maxobjsize)
 		      : warning_at (loc, opt,
 				    (maybe
-				     ? G_("%Kspecified bound [%E, %E] may "
+				     ? G_("specified bound [%E, %E] may "
 					  "exceed maximum object size %E")
-				     : G_("%Kspecified bound [%E, %E] "
+				     : G_("specified bound [%E, %E] "
 					  "exceeds maximum object size %E")),
-				    exp, bndrng[0], bndrng[1], maxobjsize));
+				    bndrng[0], bndrng[1], maxobjsize));
 	}
       else if (!size || tree_int_cst_le (bndrng[0], size))
 	return false;
@@ -4005,34 +4004,34 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func,
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD specified bound %E may exceed "
+				 ? G_("%qD specified bound %E may exceed "
 				      "source size %E")
-				 : G_("%K%qD specified bound %E exceeds "
+				 : G_("%qD specified bound %E exceeds "
 				      "source size %E")),
-				exp, func, bndrng[0], size)
+				func, bndrng[0], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kspecified bound %E may exceed "
+				 ? G_("specified bound %E may exceed "
 				      "source size %E")
-				 : G_("%Kspecified bound %E exceeds "
+				 : G_("specified bound %E exceeds "
 				      "source size %E")),
-				exp, bndrng[0], size));
+				bndrng[0], size));
       else
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD specified bound [%E, %E] may "
+				 ? G_("%qD specified bound [%E, %E] may "
 				      "exceed source size %E")
-				 : G_("%K%qD specified bound [%E, %E] exceeds "
+				 : G_("%qD specified bound [%E, %E] exceeds "
 				      "source size %E")),
-				exp, func, bndrng[0], bndrng[1], size)
+				func, bndrng[0], bndrng[1], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kspecified bound [%E, %E] may exceed "
+				 ? G_("specified bound [%E, %E] may exceed "
 				      "source size %E")
-				 : G_("%Kspecified bound [%E, %E] exceeds "
+				 : G_("specified bound [%E, %E] exceeds "
 				      "source size %E")),
-				exp, bndrng[0], bndrng[1], size));
+				bndrng[0], bndrng[1], size));
       if (warned)
 	{
 	  if (pad && pad->src.ref)
@@ -4057,35 +4056,34 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func,
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD specified size %E may "
+				 ? G_("%qD specified size %E may "
 				      "exceed maximum object size %E")
-				 : G_("%K%qD specified size %E "
+				 : G_("%qD specified size %E "
 				      "exceeds maximum object size %E")),
-				exp, func, bndrng[0], maxobjsize)
+				func, bndrng[0], maxobjsize)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kspecified size %E may exceed "
+				 ? G_("specified size %E may exceed "
 				      "maximum object size %E")
-				 : G_("%Kspecified size %E exceeds "
+				 : G_("specified size %E exceeds "
 				      "maximum object size %E")),
-				exp, bndrng[0], maxobjsize));
+				bndrng[0], maxobjsize));
       else
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD specified size between %E and %E "
+				 ? G_("%qD specified size between %E and %E "
 				      "may exceed maximum object size %E")
-				 : G_("%K%qD specified size between %E and %E "
+				 : G_("%qD specified size between %E and %E "
 				      "exceeds maximum object size %E")),
-				exp, func,
-				bndrng[0], bndrng[1], maxobjsize)
+				func, bndrng[0], bndrng[1], maxobjsize)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kspecified size between %E and %E "
+				 ? G_("specified size between %E and %E "
 				      "may exceed maximum object size %E")
-				 : G_("%Kspecified size between %E and %E "
+				 : G_("specified size between %E and %E "
 				      "exceeds maximum object size %E")),
-				exp, bndrng[0], bndrng[1], maxobjsize));
+				bndrng[0], bndrng[1], maxobjsize));
     }
   else if (!size || tree_int_cst_le (bndrng[0], size))
     return false;
@@ -4093,34 +4091,34 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func,
     warned = (func
 	      ? warning_at (loc, opt,
 			    (maybe
-			     ? G_("%K%qD specified bound %E may exceed "
+			     ? G_("%qD specified bound %E may exceed "
 				  "destination size %E")
-			     : G_("%K%qD specified bound %E exceeds "
+			     : G_("%qD specified bound %E exceeds "
 				  "destination size %E")),
-			    exp, func, bndrng[0], size)
+			    func, bndrng[0], size)
 	      : warning_at (loc, opt,
 			    (maybe
-			     ? G_("%Kspecified bound %E may exceed "
+			     ? G_("specified bound %E may exceed "
 				  "destination size %E")
-			     : G_("%Kspecified bound %E exceeds "
+			     : G_("specified bound %E exceeds "
 				  "destination size %E")),
-			    exp, bndrng[0], size));
+			    bndrng[0], size));
   else
     warned = (func
 	      ? warning_at (loc, opt,
 			    (maybe
-			     ? G_("%K%qD specified bound [%E, %E] may exceed "
+			     ? G_("%qD specified bound [%E, %E] may exceed "
 				  "destination size %E")
-			     : G_("%K%qD specified bound [%E, %E] exceeds "
+			     : G_("%qD specified bound [%E, %E] exceeds "
 				  "destination size %E")),
-			    exp, func, bndrng[0], bndrng[1], size)
+			    func, bndrng[0], bndrng[1], size)
 	      : warning_at (loc, opt,
 			    (maybe
-			     ? G_("%Kspecified bound [%E, %E] exceeds "
+			     ? G_("specified bound [%E, %E] exceeds "
 				  "destination size %E")
-			     : G_("%Kspecified bound [%E, %E] exceeds "
+			     : G_("specified bound [%E, %E] exceeds "
 				  "destination size %E")),
-			    exp, bndrng[0], bndrng[1], size));
+			    bndrng[0], bndrng[1], size));
 
   if (warned)
     {
@@ -4158,65 +4156,63 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
 	warned = (func
 		  ? warning_n (loc, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%K%qD may access %E byte in a region "
+				? G_("%qD may access %E byte in a region "
 				     "of size %E")
-				: G_("%K%qD accessing %E byte in a region "
+				: G_("%qD accessing %E byte in a region "
 				     "of size %E")),
 				(maybe
-				 ? G_ ("%K%qD may access %E bytes in a region "
+				 ? G_ ("%qD may access %E bytes in a region "
 				       "of size %E")
-				 : G_ ("%K%qD accessing %E bytes in a region "
+				 : G_ ("%qD accessing %E bytes in a region "
 				       "of size %E")),
-			       exp, func, range[0], size)
+			       func, range[0], size)
 		  : warning_n (loc, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%Kmay access %E byte in a region "
+				? G_("may access %E byte in a region "
 				     "of size %E")
-				: G_("%Kaccessing %E byte in a region "
+				: G_("accessing %E byte in a region "
 				     "of size %E")),
 			       (maybe
-				? G_("%Kmay access %E bytes in a region "
+				? G_("may access %E bytes in a region "
 				     "of size %E")
-				: G_("%Kaccessing %E bytes in a region "
+				: G_("accessing %E bytes in a region "
 				     "of size %E")),
-			       exp, range[0], size));
+			       range[0], size));
       else if (tree_int_cst_sign_bit (range[1]))
 	{
 	  /* Avoid printing the upper bound if it's invalid.  */
 	  warned = (func
 		    ? warning_at (loc, opt,
 				  (maybe
-				   ? G_("%K%qD may access %E or more bytes "
+				   ? G_("%qD may access %E or more bytes "
 					"in a region of size %E")
-				   : G_("%K%qD accessing %E or more bytes "
+				   : G_("%qD accessing %E or more bytes "
 					"in a region of size %E")),
-				  exp, func, range[0], size)
+				  func, range[0], size)
 		    : warning_at (loc, opt,
 				  (maybe
-				   ? G_("%Kmay access %E or more bytes "
+				   ? G_("may access %E or more bytes "
 					"in a region of size %E")
-				   : G_("%Kaccessing %E or more bytes "
+				   : G_("accessing %E or more bytes "
 					"in a region of size %E")),
-				  exp, range[0], size));
+				  range[0], size));
 	}
       else
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD may access between %E and %E "
+				 ? G_("%qD may access between %E and %E "
 				      "bytes in a region of size %E")
-				 : G_("%K%qD accessing between %E and %E "
+				 : G_("%qD accessing between %E and %E "
 				      "bytes in a region of size %E")),
-				exp, func, range[0], range[1],
-				size)
+				func, range[0], range[1], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kmay access between %E and %E bytes "
+				 ? G_("may access between %E and %E bytes "
 				      "in a region of size %E")
-				 : G_("%Kaccessing between %E and %E bytes "
+				 : G_("accessing between %E and %E bytes "
 				      "in a region of size %E")),
-				exp, range[0], range[1],
-				size));
+				range[0], range[1], size));
       return warned;
     }
 
@@ -4226,69 +4222,67 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
 	warned = (func
 		  ? warning_n (loc, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%K%qD may write %E byte into a region "
+				? G_("%qD may write %E byte into a region "
 				     "of size %E")
-				: G_("%K%qD writing %E byte into a region "
+				: G_("%qD writing %E byte into a region "
 				     "of size %E overflows the destination")),
 			       (maybe
-				? G_("%K%qD may write %E bytes into a region "
+				? G_("%qD may write %E bytes into a region "
 				     "of size %E")
-				: G_("%K%qD writing %E bytes into a region "
+				: G_("%qD writing %E bytes into a region "
 				     "of size %E overflows the destination")),
-			       exp, func, range[0], size)
+			       func, range[0], size)
 		  : warning_n (loc, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%Kmay write %E byte into a region "
+				? G_("may write %E byte into a region "
 				     "of size %E")
-				: G_("%Kwriting %E byte into a region "
+				: G_("writing %E byte into a region "
 				     "of size %E overflows the destination")),
 			       (maybe
-				? G_("%Kmay write %E bytes into a region "
+				? G_("may write %E bytes into a region "
 				     "of size %E")
-				: G_("%Kwriting %E bytes into a region "
+				: G_("writing %E bytes into a region "
 				     "of size %E overflows the destination")),
-			       exp, range[0], size));
+			       range[0], size));
       else if (tree_int_cst_sign_bit (range[1]))
 	{
 	  /* Avoid printing the upper bound if it's invalid.  */
 	  warned = (func
 		    ? warning_at (loc, opt,
 				  (maybe
-				   ? G_("%K%qD may write %E or more bytes "
+				   ? G_("%qD may write %E or more bytes "
 					"into a region of size %E")
-				   : G_("%K%qD writing %E or more bytes "
+				   : G_("%qD writing %E or more bytes "
 					"into a region of size %E overflows "
 					"the destination")),
-				  exp, func, range[0], size)
+				  func, range[0], size)
 		    : warning_at (loc, opt,
 				  (maybe
-				   ? G_("%Kmay write %E or more bytes into "
+				   ? G_("may write %E or more bytes into "
 					"a region of size %E")
-				   : G_("%Kwriting %E or more bytes into "
+				   : G_("writing %E or more bytes into "
 					"a region of size %E overflows "
 					"the destination")),
-				  exp, range[0], size));
+				  range[0], size));
 	}
       else
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD may write between %E and %E bytes "
+				 ? G_("%qD may write between %E and %E bytes "
 				      "into a region of size %E")
-				 : G_("%K%qD writing between %E and %E bytes "
+				 : G_("%qD writing between %E and %E bytes "
 				      "into a region of size %E overflows "
 				      "the destination")),
-				exp, func, range[0], range[1],
-				size)
+				func, range[0], range[1], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kmay write between %E and %E bytes "
+				 ? G_("may write between %E and %E bytes "
 				      "into a region of size %E")
-				 : G_("%Kwriting between %E and %E bytes "
+				 : G_("writing between %E and %E bytes "
 				      "into a region of size %E overflows "
 				      "the destination")),
-				exp, range[0], range[1],
-				size));
+				range[0], range[1], size));
       return warned;
     }
 
@@ -4299,64 +4293,64 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
 		  ? warning_n (loc, OPT_Wstringop_overread,
 			       tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%K%qD may read %E byte from a region "
+				? G_("%qD may read %E byte from a region "
 				     "of size %E")
-				: G_("%K%qD reading %E byte from a region "
+				: G_("%qD reading %E byte from a region "
 				     "of size %E")),
 			       (maybe
-				? G_("%K%qD may read %E bytes from a region "
+				? G_("%qD may read %E bytes from a region "
 				     "of size %E")
-				: G_("%K%qD reading %E bytes from a region "
+				: G_("%qD reading %E bytes from a region "
 				     "of size %E")),
-			       exp, func, range[0], size)
+			       func, range[0], size)
 		  : warning_n (loc, OPT_Wstringop_overread,
 			       tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%Kmay read %E byte from a region "
+				? G_("may read %E byte from a region "
 				     "of size %E")
-				: G_("%Kreading %E byte from a region "
+				: G_("reading %E byte from a region "
 				     "of size %E")),
 			       (maybe
-				? G_("%Kmay read %E bytes from a region "
+				? G_("may read %E bytes from a region "
 				     "of size %E")
-				: G_("%Kreading %E bytes from a region "
+				: G_("reading %E bytes from a region "
 				     "of size %E")),
-			       exp, range[0], size));
+			       range[0], size));
       else if (tree_int_cst_sign_bit (range[1]))
 	{
 	  /* Avoid printing the upper bound if it's invalid.  */
 	  warned = (func
 		    ? warning_at (loc, OPT_Wstringop_overread,
 				  (maybe
-				   ? G_("%K%qD may read %E or more bytes "
+				   ? G_("%qD may read %E or more bytes "
 					"from a region of size %E")
-				   : G_("%K%qD reading %E or more bytes "
+				   : G_("%qD reading %E or more bytes "
 					"from a region of size %E")),
-				  exp, func, range[0], size)
+				  func, range[0], size)
 		    : warning_at (loc, OPT_Wstringop_overread,
 				  (maybe
-				   ? G_("%Kmay read %E or more bytes "
+				   ? G_("may read %E or more bytes "
 					"from a region of size %E")
-				   : G_("%Kreading %E or more bytes "
+				   : G_("reading %E or more bytes "
 					"from a region of size %E")),
-				  exp, range[0], size));
+				  range[0], size));
 	}
       else
 	warned = (func
 		  ? warning_at (loc, OPT_Wstringop_overread,
 				(maybe
-				 ? G_("%K%qD may read between %E and %E bytes "
+				 ? G_("%qD may read between %E and %E bytes "
 				      "from a region of size %E")
-				 : G_("%K%qD reading between %E and %E bytes "
+				 : G_("%qD reading between %E and %E bytes "
 				      "from a region of size %E")),
-				exp, func, range[0], range[1], size)
+				func, range[0], range[1], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kmay read between %E and %E bytes "
+				 ? G_("may read between %E and %E bytes "
 				      "from a region of size %E")
-				 : G_("%Kreading between %E and %E bytes "
+				 : G_("reading between %E and %E bytes "
 				      "from a region of size %E")),
-				exp, range[0], range[1], size));
+				range[0], range[1], size));
 
       if (warned)
 	suppress_warning (exp, OPT_Wstringop_overread);
@@ -4369,37 +4363,37 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
     warned = (func
 	      ? warning_n (loc, OPT_Wstringop_overread,
 			   tree_to_uhwi (range[0]),
-			   "%K%qD expecting %E byte in a region of size %E",
-			   "%K%qD expecting %E bytes in a region of size %E",
-			   exp, func, range[0], size)
+			   "%qD expecting %E byte in a region of size %E",
+			   "%qD expecting %E bytes in a region of size %E",
+			   func, range[0], size)
 	      : warning_n (loc, OPT_Wstringop_overread,
 			   tree_to_uhwi (range[0]),
-			   "%Kexpecting %E byte in a region of size %E",
-			   "%Kexpecting %E bytes in a region of size %E",
-			   exp, range[0], size));
+			   "expecting %E byte in a region of size %E",
+			   "expecting %E bytes in a region of size %E",
+			   range[0], size));
   else if (tree_int_cst_sign_bit (range[1]))
     {
       /* Avoid printing the upper bound if it's invalid.  */
       warned = (func
 		? warning_at (loc, OPT_Wstringop_overread,
-			      "%K%qD expecting %E or more bytes in a region "
+			      "%qD expecting %E or more bytes in a region "
 			      "of size %E",
-			      exp, func, range[0], size)
+			      func, range[0], size)
 		: warning_at (loc, OPT_Wstringop_overread,
-			      "%Kexpecting %E or more bytes in a region "
+			      "expecting %E or more bytes in a region "
 			      "of size %E",
-			      exp, range[0], size));
+			      range[0], size));
     }
   else
     warned = (func
 	      ? warning_at (loc, OPT_Wstringop_overread,
-			    "%K%qD expecting between %E and %E bytes in "
+			    "%qD expecting between %E and %E bytes in "
 			    "a region of size %E",
-			    exp, func, range[0], range[1], size)
+			    func, range[0], range[1], size)
 	      : warning_at (loc, OPT_Wstringop_overread,
-			    "%Kexpecting between %E and %E bytes in "
+			    "expecting between %E and %E bytes in "
 			    "a region of size %E",
-			    exp, range[0], range[1], size));
+			    range[0], range[1], size));
 
   if (warned)
     suppress_warning (exp, OPT_Wstringop_overread);
@@ -4759,7 +4753,7 @@ check_access (tree exp, tree dstwrite,
       && TREE_CODE (range[0]) == INTEGER_CST
       && tree_int_cst_lt (maxobjsize, range[0]))
     {
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       maybe_warn_for_bound (OPT_Wstringop_overflow_, loc, exp, func, range,
 			    NULL_TREE, pad);
       return false;
@@ -4787,7 +4781,7 @@ check_access (tree exp, tree dstwrite,
 		  && warning_suppressed_p (pad->dst.ref, opt)))
 	    return false;
 
-	  location_t loc = tree_inlined_location (exp);
+	  location_t loc = EXPR_LOCATION (exp);
 	  bool warned = false;
 	  if (dstwrite == slen && at_least_one)
 	    {
@@ -4796,15 +4790,15 @@ check_access (tree exp, tree dstwrite,
 		 at least one byte past the end of the destination.  */
 	      warned = (func
 			? warning_at (loc, opt,
-				      "%K%qD writing %E or more bytes into "
+				      "%qD writing %E or more bytes into "
 				      "a region of size %E overflows "
 				      "the destination",
 				      exp, func, range[0], dstsize)
 			: warning_at (loc, opt,
-				      "%Kwriting %E or more bytes into "
+				      "writing %E or more bytes into "
 				      "a region of size %E overflows "
 				      "the destination",
-				      exp, range[0], dstsize));
+				      range[0], dstsize));
 	    }
 	  else
 	    {
@@ -4840,7 +4834,7 @@ check_access (tree exp, tree dstwrite,
 	 PAD is nonnull and BNDRNG is valid.  */
       get_size_range (maxread, range, pad ? pad->src.bndrng : NULL);
 
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       tree size = dstsize;
       if (pad && pad->mode == access_read_only)
 	size = wide_int_to_tree (sizetype, pad->src.sizrng[1]);
@@ -4901,7 +4895,7 @@ check_access (tree exp, tree dstwrite,
 	      && warning_suppressed_p (pad->src.ref, opt)))
 	return false;
 
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       const bool read
 	= mode == access_read_only || mode == access_read_write;
       const bool maybe = pad && pad->dst.parmarray;
@@ -6481,10 +6475,10 @@ check_strncat_sizes (tree exp, tree objsize)
   if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (objsize)
       && tree_int_cst_equal (objsize, maxread))
     {
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       warning_at (loc, OPT_Wstringop_overflow_,
-		  "%K%qD specified bound %E equals destination size",
-		  exp, get_callee_fndecl (exp), maxread);
+		  "%qD specified bound %E equals destination size",
+		  get_callee_fndecl (exp), maxread);
 
       return false;
     }
@@ -6554,10 +6548,10 @@ expand_builtin_strncat (tree exp, rtx)
   if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (destsize)
       && tree_int_cst_equal (destsize, maxread))
     {
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       warning_at (loc, OPT_Wstringop_overflow_,
-		  "%K%qD specified bound %E equals destination size",
-		  exp, get_callee_fndecl (exp), maxread);
+		  "%qD specified bound %E equals destination size",
+		  get_callee_fndecl (exp), maxread);
 
       return NULL_RTX;
     }
@@ -7330,7 +7324,7 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
       || !check_nul_terminated_array (exp, arg2, arg3))
     return NULL_RTX;
 
-  location_t loc = tree_inlined_location (exp);
+  location_t loc = EXPR_LOCATION (exp);
   tree len1 = c_strlen (arg1, 1);
   tree len2 = c_strlen (arg2, 1);
 
@@ -10006,13 +10000,13 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
     case BUILT_IN_VA_ARG_PACK:
       /* All valid uses of __builtin_va_arg_pack () are removed during
 	 inlining.  */
-      error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
+      error ("invalid use of %<__builtin_va_arg_pack ()%>");
       return const0_rtx;
 
     case BUILT_IN_VA_ARG_PACK_LEN:
       /* All valid uses of __builtin_va_arg_pack_len () are removed during
 	 inlining.  */
-      error ("%Kinvalid use of %<__builtin_va_arg_pack_len ()%>", exp);
+      error ("invalid use of %<__builtin_va_arg_pack_len ()%>");
       return const0_rtx;
 
       /* Return the address of the first anonymous stack arg.  */
@@ -12961,8 +12955,8 @@ expand_builtin_object_size (tree exp)
 
   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
     {
-      error ("%Kfirst argument of %qD must be a pointer, second integer constant",
-	     exp, fndecl);
+      error ("first argument of %qD must be a pointer, second integer constant",
+	     fndecl);
       expand_builtin_trap ();
       return const0_rtx;
     }
@@ -12974,8 +12968,8 @@ expand_builtin_object_size (tree exp)
       || tree_int_cst_sgn (ost) < 0
       || compare_tree_int (ost, 3) > 0)
     {
-      error ("%Klast argument of %qD is not integer constant between 0 and 3",
-	     exp, fndecl);
+      error ("last argument of %qD is not integer constant between 0 and 3",
+	      fndecl);
       expand_builtin_trap ();
       return const0_rtx;
     }
@@ -13787,8 +13781,8 @@ warn_dealloc_offset (location_t loc, tree exp, const access_ref &aref)
     }
 
   if (!warning_at (loc, OPT_Wfree_nonheap_object,
-		   "%K%qD called on pointer %qE with nonzero offset%s",
-		   exp, dealloc_decl, aref.ref, offstr))
+		   "%qD called on pointer %qE with nonzero offset%s",
+		   dealloc_decl, aref.ref, offstr))
     return false;
 
   if (DECL_P (aref.ref))
@@ -13843,15 +13837,15 @@ maybe_emit_free_warning (tree exp)
     return;
 
   tree dealloc_decl = get_callee_fndecl (exp);
-  location_t loc = tree_inlined_location (exp);
+  location_t loc = EXPR_LOCATION (exp);
 
   if (DECL_P (ref) || EXPR_P (ref))
     {
       /* Diagnose freeing a declared object.  */
       if (aref.ref_declared ()
 	  && warning_at (loc, OPT_Wfree_nonheap_object,
-			 "%K%qD called on unallocated object %qD",
-			 exp, dealloc_decl, ref))
+			 "%qD called on unallocated object %qD",
+			 dealloc_decl, ref))
 	{
 	  loc = (DECL_P (ref)
 		 ? DECL_SOURCE_LOCATION (ref)
@@ -13870,8 +13864,8 @@ maybe_emit_free_warning (tree exp)
   else if (CONSTANT_CLASS_P (ref))
     {
       if (warning_at (loc, OPT_Wfree_nonheap_object,
-		      "%K%qD called on a pointer to an unallocated "
-		      "object %qE", exp, dealloc_decl, ref))
+		      "%qD called on a pointer to an unallocated "
+		      "object %qE", dealloc_decl, ref))
 	{
 	  if (TREE_CODE (ptr) == SSA_NAME)
 	    {
@@ -13909,18 +13903,18 @@ maybe_emit_free_warning (tree exp)
 		     ? OPT_Wmismatched_new_delete
 		     : OPT_Wmismatched_dealloc);
 		  warned = warning_at (loc, opt,
-				       "%K%qD called on pointer returned "
+				       "%qD called on pointer returned "
 				       "from a mismatched allocation "
-				       "function", exp, dealloc_decl);
+				       "function", dealloc_decl);
 		}
 	    }
 	  else if (gimple_call_builtin_p (def_stmt, BUILT_IN_ALLOCA)
 	    	   || gimple_call_builtin_p (def_stmt,
 	    				     BUILT_IN_ALLOCA_WITH_ALIGN))
 	    warned = warning_at (loc, OPT_Wfree_nonheap_object,
-				 "%K%qD called on pointer to "
+				 "%qD called on pointer to "
 				 "an unallocated object",
-				 exp, dealloc_decl);
+				 dealloc_decl);
 	  else if (warn_dealloc_offset (loc, exp, aref))
 	    return;
 
diff --git a/gcc/calls.c b/gcc/calls.c
index f8a4b79e7f8..d2413a280cf 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1435,8 +1435,8 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 	  if (tree_int_cst_lt (args[i], integer_zero_node))
 	    {
 	      warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-				   "%Kargument %i value %qE is negative",
-				   exp, idx[i] + 1, args[i]);
+				   "argument %i value %qE is negative",
+				   idx[i] + 1, args[i]);
 	    }
 	  else if (integer_zerop (args[i]))
 	    {
@@ -1452,8 +1452,8 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 		  : !lookup_attribute ("returns_nonnull",
 				       TYPE_ATTRIBUTES (fntype)))
 		warned = warning_at (loc, OPT_Walloc_zero,
-				     "%Kargument %i value is zero",
-				     exp, idx[i] + 1);
+				     "argument %i value is zero",
+				     idx[i] + 1);
 	    }
 	  else if (tree_int_cst_lt (maxobjsize, args[i]))
 	    {
@@ -1470,9 +1470,9 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 		continue;
 
 	      warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-				   "%Kargument %i value %qE exceeds "
+				   "argument %i value %qE exceeds "
 				   "maximum object size %E",
-				   exp, idx[i] + 1, args[i], maxobjsize);
+				   idx[i] + 1, args[i], maxobjsize);
 	    }
 	}
       else if (TREE_CODE (args[i]) == SSA_NAME
@@ -1484,16 +1484,16 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 	      && tree_int_cst_le (argrange[i][1], integer_zero_node))
 	    {
 	      warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-				   "%Kargument %i range [%E, %E] is negative",
-				   exp, idx[i] + 1,
+				   "argument %i range [%E, %E] is negative",
+				   idx[i] + 1,
 				   argrange[i][0], argrange[i][1]);
 	    }
 	  else if (tree_int_cst_lt (maxobjsize, argrange[i][0]))
 	    {
 	      warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-				   "%Kargument %i range [%E, %E] exceeds "
+				   "argument %i range [%E, %E] exceeds "
 				   "maximum object size %E",
-				   exp, idx[i] + 1,
+				   idx[i] + 1,
 				   argrange[i][0], argrange[i][1],
 				   maxobjsize);
 	    }
@@ -1521,15 +1521,15 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 
       if (vflow)
 	warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-			     "%Kproduct %<%E * %E%> of arguments %i and %i "
+			     "product %<%E * %E%> of arguments %i and %i "
 			     "exceeds %<SIZE_MAX%>",
-			     exp, argrange[0][0], argrange[1][0],
+			     argrange[0][0], argrange[1][0],
 			     idx[0] + 1, idx[1] + 1);
       else if (wi::ltu_p (wi::to_wide (maxobjsize, szprec), prod))
 	warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-			     "%Kproduct %<%E * %E%> of arguments %i and %i "
+			     "product %<%E * %E%> of arguments %i and %i "
 			     "exceeds maximum object size %E",
-			     exp, argrange[0][0], argrange[1][0],
+			     argrange[0][0], argrange[1][0],
 			     idx[0] + 1, idx[1] + 1,
 			     maxobjsize);
 
@@ -1729,14 +1729,14 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
 	  bool warned = false;
 	  if (tree_int_cst_equal (bndrng[0], bndrng[1]))
 	    warned = warning_at (loc, OPT_Wstringop_overread,
-				 "%K%qD specified bound %E "
+				 "%qD specified bound %E "
 				 "exceeds maximum object size %E",
-				 exp, fndecl, bndrng[0], maxobjsize);
+				 fndecl, bndrng[0], maxobjsize);
 	  else
 	    warned = warning_at (loc, OPT_Wstringop_overread,
-				 "%K%qD specified bound [%E, %E] "
+				 "%qD specified bound [%E, %E] "
 				 "exceeds maximum object size %E",
-				 exp, fndecl, bndrng[0], bndrng[1],
+				 fndecl, bndrng[0], bndrng[1],
 				 maxobjsize);
 	  if (warned)
 	    suppress_warning (exp, OPT_Wstringop_overread);
@@ -2068,16 +2068,16 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 		= access.second.array_as_string (ptrtype);
 
 	      if (warning_at (loc, OPT_Wstringop_overflow_,
-			      "%Kbound argument %i value %s is "
+			      "bound argument %i value %s is "
 			      "negative for a variable length array "
 			      "argument %i of type %s",
-			      exp, sizidx + 1, sizstr,
+			      sizidx + 1, sizstr,
 			      ptridx + 1, argtypestr.c_str ()))
 		arg_warned = OPT_Wstringop_overflow_;
 	    }
 	  else if (warning_at (loc, OPT_Wstringop_overflow_,
-			       "%Kargument %i value %s is negative",
-			       exp, sizidx + 1, sizstr))
+			       "argument %i value %s is negative",
+			       sizidx + 1, sizstr))
 	    arg_warned = OPT_Wstringop_overflow_;
 
 	  if (arg_warned != no_warning)
@@ -2124,20 +2124,19 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 		    = access.second.array_as_string (ptrtype);
 
 		  if (warning_at (loc, OPT_Wnonnull,
-				  "%Kargument %i of variable length "
+				  "argument %i of variable length "
 				  "array %s is null but "
 				  "the corresponding bound argument "
 				  "%i value is %s",
-				  exp, sizidx + 1, argtypestr.c_str (),
+				  sizidx + 1, argtypestr.c_str (),
 				  ptridx + 1, sizstr))
 		    arg_warned = OPT_Wnonnull;
 		}
 	      else if (warning_at (loc, OPT_Wnonnull,
-				   "%Kargument %i is null but "
+				   "argument %i is null but "
 				   "the corresponding size argument "
 				   "%i value is %s",
-				   exp, ptridx + 1, sizidx + 1,
-				   sizstr))
+				   ptridx + 1, sizidx + 1, sizstr))
 		arg_warned = OPT_Wnonnull;
 	    }
 	  else if (access_size && access.second.static_p)
@@ -2145,10 +2144,9 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 	      /* Warn about null pointers for [static N] array arguments
 		 but do not warn for ordinary (i.e., nonstatic) arrays.  */
 	      if (warning_at (loc, OPT_Wnonnull,
-			      "%Kargument %i to %<%T[static %E]%> "
+			      "argument %i to %<%T[static %E]%> "
 			      "is null where non-null expected",
-			      exp, ptridx + 1, argtype,
-			      access_size))
+			      ptridx + 1, argtype, access_size))
 		arg_warned = OPT_Wnonnull;		
 	    }
 
diff --git a/gcc/expr.c b/gcc/expr.c
index 025033c9ecf..b9fe1cf91d7 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -11401,7 +11401,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
       /* All valid uses of __builtin_va_arg_pack () are removed during
 	 inlining.  */
       if (CALL_EXPR_VA_ARG_PACK (exp))
-	error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
+	error ("invalid use of %<__builtin_va_arg_pack ()%>");
       {
 	tree fndecl = get_callee_fndecl (exp), attr;
 
@@ -11413,7 +11413,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 					 DECL_ATTRIBUTES (fndecl))) != NULL)
 	  {
 	    const char *ident = lang_hooks.decl_printable_name (fndecl, 1);
-	    error ("%Kcall to %qs declared with attribute error: %s", exp,
+	    error ("call to %qs declared with attribute error: %s",
 		   identifier_to_locale (ident),
 		   TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
 	  }
@@ -11425,10 +11425,10 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 					 DECL_ATTRIBUTES (fndecl))) != NULL)
 	  {
 	    const char *ident = lang_hooks.decl_printable_name (fndecl, 1);
-	    warning_at (tree_nonartificial_location (exp),
+	    warning_at (EXPR_LOCATION (exp),
 			OPT_Wattribute_warning,
-			"%Kcall to %qs declared with attribute warning: %s",
-			exp, identifier_to_locale (ident),
+			"call to %qs declared with attribute warning: %s",
+			identifier_to_locale (ident),
 			TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
 	  }
 
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 68031538145..1401092aa9b 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -2115,13 +2115,13 @@ gimple_fold_builtin_strncpy (gimple_stmt_iterator *gsi,
 	  tree slen = get_maxval_strlen (src, SRK_STRLEN);
 	  if (slen && !integer_zerop (slen))
 	    warning_at (loc, OPT_Wstringop_truncation,
-			"%G%qD destination unchanged after copying no bytes "
+			"%qD destination unchanged after copying no bytes "
 			"from a string of length %E",
-			stmt, fndecl, slen);
+			fndecl, slen);
 	  else
 	    warning_at (loc, OPT_Wstringop_truncation,
-			"%G%qD destination unchanged after copying no bytes",
-			stmt, fndecl);
+			"%qD destination unchanged after copying no bytes",
+			fndecl);
 	}
 
       replace_call_with_value (gsi, dest);
@@ -2498,11 +2498,11 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
 	  location_t loc = gimple_location (stmt);
 	  nowarn = warning_at (loc, OPT_Wstringop_overflow_,
 			       cmpdst == 0
-			       ? G_("%G%qD specified bound %E equals "
+			       ? G_("%qD specified bound %E equals "
 				    "destination size")
-			       : G_("%G%qD specified bound %E exceeds "
+			       : G_("%qD specified bound %E exceeds "
 				    "destination size %wu"),
-			       stmt, fndecl, len, dstsize);
+			       fndecl, len, dstsize);
 	  if (nowarn)
 	    suppress_warning (stmt, OPT_Wstringop_overflow_);
 	}
@@ -2518,8 +2518,8 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
 	 of the destination is unknown (it's not an uncommon mistake
 	 to specify as the bound to strncpy the length of the source).  */
       if (warning_at (loc, OPT_Wstringop_overflow_,
-		      "%G%qD specified bound %E equals source length",
-		      stmt, fndecl, len))
+		      "%qD specified bound %E equals source length",
+		      fndecl, len))
 	suppress_warning (stmt, OPT_Wstringop_overflow_);
     }
 
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index 41e3be6f9f4..f38fb03f068 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -3115,9 +3115,8 @@ format_directive (const call_info &info,
   if (fmtres.nullp)
     {
       fmtwarn (dirloc, argloc, NULL, info.warnopt (),
-	       "%G%<%.*s%> directive argument is null",
-	       info.callstmt, dirlen,
-	       target_to_host (hostdir, sizeof hostdir, dir.beg));
+	       "%<%.*s%> directive argument is null",
+	       dirlen, target_to_host (hostdir, sizeof hostdir, dir.beg));
 
       /* Don't bother processing the rest of the format string.  */
       res->warned = true;
@@ -4620,8 +4619,7 @@ handle_printf_call (gimple_stmt_iterator *gsi, pointer_query &ptr_qry)
 	     is not constant.  */
 	  location_t loc = gimple_location (info.callstmt);
 	  warning_at (EXPR_LOC_OR_LOC (dstptr, loc),
-		      info.warnopt (), "%Gnull destination pointer",
-		      info.callstmt);
+		      info.warnopt (), "null destination pointer");
 	  return false;
 	}
 
@@ -4650,8 +4648,7 @@ handle_printf_call (gimple_stmt_iterator *gsi, pointer_query &ptr_qry)
     {
       location_t loc = gimple_location (info.callstmt);
       warning_at (EXPR_LOC_OR_LOC (info.format, loc),
-		  info.warnopt (), "%Gnull format string",
-		  info.callstmt);
+		  info.warnopt (), "null format string");
       return false;
     }
 
diff --git a/gcc/gimple-ssa-warn-alloca.c b/gcc/gimple-ssa-warn-alloca.c
index 72480f1d8cb..4fc7125d378 100644
--- a/gcc/gimple-ssa-warn-alloca.c
+++ b/gcc/gimple-ssa-warn-alloca.c
@@ -283,7 +283,7 @@ pass_walloca::execute (function *fun)
 	    }
 	  else if (warn_alloca)
 	    {
-	      warning_at (loc, OPT_Walloca, "%Guse of %<alloca%>", stmt);
+	      warning_at (loc, OPT_Walloca, "use of %<alloca%>");
 	      continue;
 	    }
 	  else if (warn_alloca_limit < 0)
@@ -322,11 +322,10 @@ pass_walloca::execute (function *fun)
 		auto_diagnostic_group d;
 		if (warning_at (loc, wcode,
 				(is_vla
-				 ? G_("%Gargument to variable-length "
+				 ? G_("argument to variable-length "
 				      "array may be too large")
-				 : G_("%Gargument to %<alloca%> may be too "
-				      "large")),
-				stmt)
+				 : G_("argument to %<alloca%> may be too "
+				      "large")))
 		    && t.limit != 0)
 		  {
 		    print_decu (t.limit, buff);
@@ -342,10 +341,9 @@ pass_walloca::execute (function *fun)
 		auto_diagnostic_group d;
 		if (warning_at (loc, wcode,
 				(is_vla
-				 ? G_("%Gargument to variable-length"
+				 ? G_("argument to variable-length"
 				      " array is too large")
-				 : G_("%Gargument to %<alloca%> is too large")),
-				stmt)
+				 : G_("argument to %<alloca%> is too large")))
 		    && t.limit != 0)
 		  {
 		    print_decu (t.limit, buff);
@@ -361,22 +359,20 @@ pass_walloca::execute (function *fun)
 
 	      warning_at (loc, wcode,
 			  (is_vla
-			   ? G_("%Gunbounded use of variable-length array")
-			   : G_("%Gunbounded use of %<alloca%>")),
-			  stmt);
+			   ? G_("unbounded use of variable-length array")
+			   : G_("unbounded use of %<alloca%>")));
 	      break;
 	    case ALLOCA_IN_LOOP:
 	      gcc_assert (!is_vla);
 	      warning_at (loc, wcode,
-			  "%Guse of %<alloca%> within a loop", stmt);
+			  "use of %<alloca%> within a loop");
 	      break;
 	    case ALLOCA_ARG_IS_ZERO:
 	      warning_at (loc, wcode,
 			  (is_vla
-			   ? G_("%Gargument to variable-length array "
+			   ? G_("argument to variable-length array "
 				"is zero")
-			   : G_("%Gargument to %<alloca%> is zero")),
-			  stmt);
+			   : G_("argument to %<alloca%> is zero")));
 	      break;
 	    default:
 	      gcc_unreachable ();
diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c
index 02771e4cd60..efb8db98393 100644
--- a/gcc/gimple-ssa-warn-restrict.c
+++ b/gcc/gimple-ssa-warn-restrict.c
@@ -1494,36 +1494,36 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
 	    warning_at (loc, OPT_Wrestrict,
 			sizrange[0] == 1
 			? (ovlsiz[0] == 1
-			   ? G_("%G%qD accessing %wu byte at offsets %s "
+			   ? G_("%qD accessing %wu byte at offsets %s "
 				"and %s overlaps %wu byte at offset %s")
-			   :  G_("%G%qD accessing %wu byte at offsets %s "
+			   :  G_("%qD accessing %wu byte at offsets %s "
 				 "and %s overlaps %wu bytes at offset "
 				 "%s"))
 			: (ovlsiz[0] == 1
-			   ? G_("%G%qD accessing %wu bytes at offsets %s "
+			   ? G_("%qD accessing %wu bytes at offsets %s "
 				"and %s overlaps %wu byte at offset %s")
-			   : G_("%G%qD accessing %wu bytes at offsets %s "
+			   : G_("%qD accessing %wu bytes at offsets %s "
 				"and %s overlaps %wu bytes at offset "
 				"%s")),
-			call, func, sizrange[0],
+			func, sizrange[0],
 			offstr[0], offstr[1], ovlsiz[0], offstr[2]);
 	  else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
 	    warning_n (loc, OPT_Wrestrict, sizrange[0],
-		       "%G%qD accessing %wu byte at offsets %s "
+		       "%qD accessing %wu byte at offsets %s "
 		       "and %s overlaps between %wu and %wu bytes "
 		       "at offset %s",
-		       "%G%qD accessing %wu bytes at offsets %s "
+		       "%qD accessing %wu bytes at offsets %s "
 		       "and %s overlaps between %wu and %wu bytes "
 		       "at offset %s",
-		       call, func, sizrange[0], offstr[0], offstr[1],
+		       func, sizrange[0], offstr[0], offstr[1],
 		       ovlsiz[0], ovlsiz[1], offstr[2]);
 	  else
 	    warning_n (loc, OPT_Wrestrict, sizrange[0],
-		       "%G%qD accessing %wu byte at offsets %s and "
+		       "%qD accessing %wu byte at offsets %s and "
 		       "%s overlaps %wu or more bytes at offset %s",
-		       "%G%qD accessing %wu bytes at offsets %s and "
+		       "%qD accessing %wu bytes at offsets %s and "
 		       "%s overlaps %wu or more bytes at offset %s",
-		       call, func, sizrange[0],
+		       func, sizrange[0],
 		       offstr[0], offstr[1], ovlsiz[0], offstr[2]);
 	  return true;
 	}
@@ -1532,28 +1532,28 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
 	{
 	  if (ovlsiz[0] == ovlsiz[1])
 	    warning_n (loc, OPT_Wrestrict, ovlsiz[0],
-		       "%G%qD accessing between %wu and %wu bytes "
+		       "%qD accessing between %wu and %wu bytes "
 		       "at offsets %s and %s overlaps %wu byte at "
 		       "offset %s",
-		       "%G%qD accessing between %wu and %wu bytes "
+		       "%qD accessing between %wu and %wu bytes "
 		       "at offsets %s and %s overlaps %wu bytes "
 		       "at offset %s",
-		       call, func, sizrange[0], sizrange[1],
+		       func, sizrange[0], sizrange[1],
 		       offstr[0], offstr[1], ovlsiz[0], offstr[2]);
 	  else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
 	    warning_at (loc, OPT_Wrestrict,
-			"%G%qD accessing between %wu and %wu bytes at "
+			"%qD accessing between %wu and %wu bytes at "
 			"offsets %s and %s overlaps between %wu and %wu "
 			"bytes at offset %s",
-			call, func, sizrange[0], sizrange[1],
+			func, sizrange[0], sizrange[1],
 			offstr[0], offstr[1], ovlsiz[0], ovlsiz[1],
 			offstr[2]);
 	  else
 	    warning_at (loc, OPT_Wrestrict,
-			"%G%qD accessing between %wu and %wu bytes at "
+			"%qD accessing between %wu and %wu bytes at "
 			"offsets %s and %s overlaps %wu or more bytes "
 			"at offset %s",
-			call, func, sizrange[0], sizrange[1],
+			func, sizrange[0], sizrange[1],
 			offstr[0], offstr[1], ovlsiz[0], offstr[2]);
 	  return true;
 	}
@@ -1563,24 +1563,24 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
 
       if (ovlsiz[0] == ovlsiz[1])
 	warning_n (loc, OPT_Wrestrict, ovlsiz[0],
-		   "%G%qD accessing %wu or more bytes at offsets "
+		   "%qD accessing %wu or more bytes at offsets "
 		   "%s and %s overlaps %wu byte at offset %s",
-		   "%G%qD accessing %wu or more bytes at offsets "
+		   "%qD accessing %wu or more bytes at offsets "
 		   "%s and %s overlaps %wu bytes at offset %s",
-		   call, func, sizrange[0], offstr[0], offstr[1],
+		   func, sizrange[0], offstr[0], offstr[1],
 		   ovlsiz[0], offstr[2]);
       else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
 	warning_at (loc, OPT_Wrestrict,
-		    "%G%qD accessing %wu or more bytes at offsets %s "
+		    "%qD accessing %wu or more bytes at offsets %s "
 		    "and %s overlaps between %wu and %wu bytes "
 		    "at offset %s",
-		    call, func, sizrange[0], offstr[0], offstr[1],
+		    func, sizrange[0], offstr[0], offstr[1],
 		    ovlsiz[0], ovlsiz[1], offstr[2]);
       else
 	warning_at (loc, OPT_Wrestrict,
-		    "%G%qD accessing %wu or more bytes at offsets %s "
+		    "%qD accessing %wu or more bytes at offsets %s "
 		    "and %s overlaps %wu or more bytes at offset %s",
-		    call, func, sizrange[0], offstr[0], offstr[1],
+		    func, sizrange[0], offstr[0], offstr[1],
 		    ovlsiz[0], offstr[2]);
       return true;
     }
@@ -1606,36 +1606,36 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
 	{
 	  if (open_range)
 	    warning_n (loc, OPT_Wrestrict, sizrange[1],
-		       "%G%qD accessing %wu byte may overlap "
+		       "%qD accessing %wu byte may overlap "
 		       "%wu byte",
-		       "%G%qD accessing %wu bytes may overlap "
+		       "%qD accessing %wu bytes may overlap "
 		       "%wu byte",
-		       call, func, sizrange[1], ovlsiz[1]);
+		       func, sizrange[1], ovlsiz[1]);
 	  else
 	    warning_n (loc, OPT_Wrestrict, sizrange[1],
-		       "%G%qD accessing %wu byte at offsets %s "
+		       "%qD accessing %wu byte at offsets %s "
 		       "and %s may overlap %wu byte at offset %s",
-		       "%G%qD accessing %wu bytes at offsets %s "
+		       "%qD accessing %wu bytes at offsets %s "
 		       "and %s may overlap %wu byte at offset %s",
-		       call, func, sizrange[1], offstr[0], offstr[1],
+		       func, sizrange[1], offstr[0], offstr[1],
 		       ovlsiz[1], offstr[2]);
 	  return true;
 	}
 
       if (open_range)
 	warning_n (loc, OPT_Wrestrict, sizrange[1],
-		   "%G%qD accessing %wu byte may overlap "
+		   "%qD accessing %wu byte may overlap "
 		   "up to %wu bytes",
-		   "%G%qD accessing %wu bytes may overlap "
+		   "%qD accessing %wu bytes may overlap "
 		   "up to %wu bytes",
-		   call, func, sizrange[1], ovlsiz[1]);
+		   func, sizrange[1], ovlsiz[1]);
       else
 	warning_n (loc, OPT_Wrestrict, sizrange[1],
-		   "%G%qD accessing %wu byte at offsets %s and "
+		   "%qD accessing %wu byte at offsets %s and "
 		   "%s may overlap up to %wu bytes at offset %s",
-		   "%G%qD accessing %wu bytes at offsets %s and "
+		   "%qD accessing %wu bytes at offsets %s and "
 		   "%s may overlap up to %wu bytes at offset %s",
-		   call, func, sizrange[1], offstr[0], offstr[1],
+		   func, sizrange[1], offstr[0], offstr[1],
 		   ovlsiz[1], offstr[2]);
       return true;
     }
@@ -1644,30 +1644,30 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
     {
       if (open_range)
 	warning_n (loc, OPT_Wrestrict, ovlsiz[1],
-		   "%G%qD accessing between %wu and %wu bytes "
+		   "%qD accessing between %wu and %wu bytes "
 		   "may overlap %wu byte",
-		   "%G%qD accessing between %wu and %wu bytes "
+		   "%qD accessing between %wu and %wu bytes "
 		   "may overlap up to %wu bytes",
-		   call, func, sizrange[0], sizrange[1], ovlsiz[1]);
+		   func, sizrange[0], sizrange[1], ovlsiz[1]);
       else
 	warning_n (loc, OPT_Wrestrict, ovlsiz[1],
-		   "%G%qD accessing between %wu and %wu bytes "
+		   "%qD accessing between %wu and %wu bytes "
 		   "at offsets %s and %s may overlap %wu byte "
 		   "at offset %s",
-		   "%G%qD accessing between %wu and %wu bytes "
+		   "%qD accessing between %wu and %wu bytes "
 		   "at offsets %s and %s may overlap up to %wu "
 		   "bytes at offset %s",
-		   call, func, sizrange[0], sizrange[1],
+		   func, sizrange[0], sizrange[1],
 		   offstr[0], offstr[1], ovlsiz[1], offstr[2]);
       return true;
     }
 
   warning_n (loc, OPT_Wrestrict, ovlsiz[1],
-	     "%G%qD accessing %wu or more bytes at offsets %s "
+	     "%qD accessing %wu or more bytes at offsets %s "
 	     "and %s may overlap %wu byte at offset %s",
-	     "%G%qD accessing %wu or more bytes at offsets %s "
+	     "%qD accessing %wu or more bytes at offsets %s "
 	     "and %s may overlap up to %wu bytes at offset %s",
-	     call, func, sizrange[0], offstr[0], offstr[1],
+	     func, sizrange[0], offstr[0], offstr[1],
 	     ovlsiz[1], offstr[2]);
 
   return true;
@@ -1689,7 +1689,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 			  const builtin_memref &ref, offset_int wroff,
 			  bool do_warn)
 {
-  location_t loc = gimple_or_expr_nonartificial_location (call, ref.ptr);
+  location_t loc = gimple_location (call);
   const offset_int maxobjsize = ref.maxobjsize;
 
   /* Check for excessive size first and regardless of warning options
@@ -1709,15 +1709,15 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	{
 	  if (ref.sizrange[0] == ref.sizrange[1])
 	    warned = warning_at (loc, opt,
-				 "%G%qD specified bound %wu "
+				 "%qD specified bound %wu "
 				 "exceeds maximum object size %wu",
-				 call, func, ref.sizrange[0].to_uhwi (),
+				 func, ref.sizrange[0].to_uhwi (),
 				 maxobjsize.to_uhwi ());
 	  else
 	    warned = warning_at (loc, opt,
-				 "%G%qD specified bound between %wu and %wu "
+				 "%qD specified bound between %wu and %wu "
 				 "exceeds maximum object size %wu",
-				 call, func, ref.sizrange[0].to_uhwi (),
+				 func, ref.sizrange[0].to_uhwi (),
 				 ref.sizrange[1].to_uhwi (),
 				 maxobjsize.to_uhwi ());
 	  return warned ? opt : no_warning;
@@ -1776,9 +1776,9 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	{
 	  auto_diagnostic_group d;
 	  if (warning_at (loc, opt,
-			  "%G%qD pointer overflow between offset %s "
+			  "%qD pointer overflow between offset %s "
 			  "and size %s accessing array %qD with type %qT",
-			  call, func, rangestr[0], rangestr[1], ref.base, type))
+			  func, rangestr[0], rangestr[1], ref.base, type))
 	    {
 	      inform (DECL_SOURCE_LOCATION (ref.base),
 		      "array %qD declared here", ref.base);
@@ -1786,15 +1786,15 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	    }
 	  else
 	    warned = warning_at (loc, opt,
-				 "%G%qD pointer overflow between offset %s "
+				 "%qD pointer overflow between offset %s "
 				 "and size %s",
-				 call, func, rangestr[0], rangestr[1]);
+				 func, rangestr[0], rangestr[1]);
 	}
       else
 	warned = warning_at (loc, opt,
-			     "%G%qD pointer overflow between offset %s "
+			     "%qD pointer overflow between offset %s "
 			     "and size %s",
-			     call, func, rangestr[0], rangestr[1]);
+			     func, rangestr[0], rangestr[1]);
     }
   else if (oobref == ref.base)
     {
@@ -1809,20 +1809,20 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	  if ((ref.basesize < maxobjsize
 	       && warning_at (loc, opt,
 			      form
-			      ? G_("%G%qD forming offset %s is out of "
+			      ? G_("%qD forming offset %s is out of "
 				   "the bounds [0, %wu] of object %qD with "
 				   "type %qT")
-			      : G_("%G%qD offset %s is out of the bounds "
+			      : G_("%qD offset %s is out of the bounds "
 				   "[0, %wu] of object %qD with type %qT"),
-			      call, func, rangestr[0], ref.basesize.to_uhwi (),
+			      func, rangestr[0], ref.basesize.to_uhwi (),
 			      ref.base, TREE_TYPE (ref.base)))
 	      || warning_at (loc, opt,
 			     form
-			     ? G_("%G%qD forming offset %s is out of "
+			     ? G_("%qD forming offset %s is out of "
 				  "the bounds of object %qD with type %qT")
-			     : G_("%G%qD offset %s is out of the bounds "
+			     : G_("%qD offset %s is out of the bounds "
 				  "of object %qD with type %qT"),
-			     call, func, rangestr[0],
+			     func, rangestr[0],
 			     ref.base, TREE_TYPE (ref.base)))
 	    {
 	      inform (DECL_SOURCE_LOCATION (ref.base),
@@ -1833,17 +1833,17 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
       else if (ref.basesize < maxobjsize)
 	warned = warning_at (loc, opt,
 			     form
-			     ? G_("%G%qD forming offset %s is out "
+			     ? G_("%qD forming offset %s is out "
 				  "of the bounds [0, %wu]")
-			     : G_("%G%qD offset %s is out "
+			     : G_("%qD offset %s is out "
 				  "of the bounds [0, %wu]"),
-			     call, func, rangestr[0], ref.basesize.to_uhwi ());
+			     func, rangestr[0], ref.basesize.to_uhwi ());
       else
 	warned = warning_at (loc, opt,
 			     form
-			     ? G_("%G%qD forming offset %s is out of bounds")
-			     : G_("%G%qD offset %s is out of bounds"),
-			     call, func, rangestr[0]);
+			     ? G_("%qD forming offset %s is out of bounds")
+			     : G_("%qD offset %s is out of bounds"),
+			     func, rangestr[0]);
     }
   else if (TREE_CODE (ref.ref) == MEM_REF)
     {
@@ -1854,9 +1854,9 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
       type = TYPE_MAIN_VARIANT (type);
 
       if (warning_at (loc, opt,
-		      "%G%qD offset %s from the object at %qE is out "
+		      "%qD offset %s from the object at %qE is out "
 		      "of the bounds of %qT",
-		      call, func, rangestr[0], ref.base, type))
+		      func, rangestr[0], ref.base, type))
 	{
 	  if (TREE_CODE (ref.ref) == COMPONENT_REF)
 	    refop = TREE_OPERAND (ref.ref, 1);
@@ -1872,10 +1872,10 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
       tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref));
 
       if (warning_at (loc, opt,
-		      "%G%qD offset %s from the object at %qE is out "
+		      "%qD offset %s from the object at %qE is out "
 		      "of the bounds of referenced subobject %qD with "
 		      "type %qT at offset %wi",
-		      call, func, rangestr[0], ref.base,
+		      func, rangestr[0], ref.base,
 		      TREE_OPERAND (ref.ref, 1), type,
 		      ref.refoff.to_shwi ()))
 	{
@@ -2065,7 +2065,7 @@ check_bounds_or_overlap (range_query *query,
 	}
     }
 
-  location_t loc = gimple_or_expr_nonartificial_location (call, dst);
+  location_t loc = gimple_location (call);
   if (operand_equal_p (dst, src, 0))
     {
       /* Issue -Wrestrict unless the pointers are null (those do
@@ -2075,8 +2075,8 @@ check_bounds_or_overlap (range_query *query,
       if (!integer_zerop (dst) && !warning_suppressed_p (call, OPT_Wrestrict))
 	{
 	  warning_at (loc, OPT_Wrestrict,
-		      "%G%qD source argument is the same as destination",
-		      call, func);
+		      "%qD source argument is the same as destination",
+		      func);
 	  suppress_warning (call, OPT_Wrestrict);
 	  return OPT_Wrestrict;
 	}
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c
index a7d921248c4..fdef9e6b3ea 100644
--- a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c
@@ -26,7 +26,7 @@ void g2 (struct A *p) { g1 (p); }
 
 #define NOIPA __attribute__ ((noipa))
 
-extern int array[];
+extern int array[];           // { dg-message "declared here" "note on line 29" }
 
 /* Verify the warning is issued even for calls in a system header inlined
    into a function outside the header.  */
@@ -39,7 +39,7 @@ NOIPA void warn_g0 (struct A *p)
   g0 (p);
 }
 
-// { dg-message "inlined from 'warn_g0'" "" { target *-*-* } 0 }
+// { dg-message "inlined from 'warn_g0'" "note on line 42" { target *-*-* } 0 }
 
 
 /* Also verify the warning can be suppressed.  */
@@ -65,8 +65,8 @@ NOIPA void warn_g1 (struct A *p)
   g1 (p);
 }
 
-// { dg-message "inlined from 'g1'" "" { target *-*-* } 0 }
-// { dg-message "inlined from 'warn_g1'" "" { target *-*-* } 0 }
+// { dg-message "inlined from 'g1'" "note on line 68" { target *-*-* } 0 }
+// { dg-message "inlined from 'warn_g1'" "note on line 69" { target *-*-* } 0 }
 
 
 NOIPA void nowarn_g1 (struct A *p)
@@ -90,8 +90,8 @@ NOIPA void warn_g2 (struct A *p)
   g2 (p);
 }
 
-// { dg-message "inlined from 'g2'" "" { target *-*-* } 0 }
-// { dg-message "inlined from 'warn_g2'" "" { target *-*-* } 0 }
+// { dg-message "inlined from 'g2'" "note on line 93" { target *-*-* } 0 }
+// { dg-message "inlined from 'warn_g2'" "note on line 94" { target *-*-* } 0 }
 
 
 NOIPA void nowarn_g2 (struct A *p)
diff --git a/gcc/testsuite/gcc.dg/Wobjsize-1.c b/gcc/testsuite/gcc.dg/Wobjsize-1.c
index e80c8add3bb..2bd2f93897b 100644
--- a/gcc/testsuite/gcc.dg/Wobjsize-1.c
+++ b/gcc/testsuite/gcc.dg/Wobjsize-1.c
@@ -4,13 +4,17 @@
 #include "Wobjsize-1.h"
 
 char buf[6];
-/* { dg-warning "writing" "" { target *-*-* } .-1 } */
 
 int main(int argc, char **argv)
 {
-  strcpy (buf,"hello ");
+  strcpy (buf,"hello ");    /* { dg-warning "\\\[-Wstringop-overflow" } */
   return 0;
 }
 
-/* { dg-message "file included" "included" { target *-*-* } 0 } */
-/* { dg-message "inlined from" "inlined" { target *-*-* } 0 } */
+/* { dg-message "file included" "included" { target *-*-* } 0 }
+   { dg-message "inlined from" "inlined" { target *-*-* } 0 }
+
+   The test might emit two warnings, one for the strcpy call and
+   another for the inlined call to __builtin___strcpy_chk() called
+   from strcpy().
+   { dg-prune-output "writing 7 bytes into a region of size 6" } */
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index e74bd1f5ec0..c270d039b15 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -4413,12 +4413,8 @@ ipa_tm_scan_irr_block (basic_block bb)
 	     is to wrap it in a __tm_waiver block.  This is not
 	     yet implemented, so we can't check for it.  */
 	  if (is_tm_safe (current_function_decl))
-	    {
-	      tree t = build1 (NOP_EXPR, void_type_node, size_zero_node);
-	      SET_EXPR_LOCATION (t, gimple_location (stmt));
-	      error ("%K%<asm%> not allowed in %<transaction_safe%> function",
-		     t);
-	    }
+	    error_at (gimple_location (stmt),
+		      "%<asm%> not allowed in %<transaction_safe%> function");
 	  return true;
 
 	default:
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 42585412325..9ce6214d7e2 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -3563,7 +3563,7 @@ pass_post_ipa_warn::execute (function *fun)
 	      if (argno == 0)
 		{
 		  if (warning_at (loc, OPT_Wnonnull,
-				  "%G%qs pointer is null", stmt, "this")
+				  "%qs pointer is null", "this")
 		      && fndecl)
 		    inform (DECL_SOURCE_LOCATION (fndecl),
 			    "in a call to non-static member function %qD",
@@ -3572,8 +3572,8 @@ pass_post_ipa_warn::execute (function *fun)
 		}
 
 	      if (!warning_at (loc, OPT_Wnonnull,
-			       "%Gargument %u null where non-null "
-			       "expected", stmt, argno))
+			       "argument %u null where non-null "
+			       "expected", argno))
 		continue;
 
 	      tree fndecl = gimple_call_fndecl (stmt);
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 13ea107da17..94257df1067 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -2022,13 +2022,12 @@ maybe_warn_overflow (gimple *stmt, tree len, pointer_query &ptr_qry,
 
       warned = (writefn
 		? warning_at (loc, OPT_Wstringop_overflow_,
-			      "%G%qD writing one too many bytes into a region "
+			      "%qD writing one too many bytes into a region "
 			      "of a size that depends on %<strlen%>",
-			      stmt, writefn)
+			      writefn)
 		: warning_at (loc, OPT_Wstringop_overflow_,
-			      "%Gwriting one too many bytes into a region "
-			      "of a size that depends on %<strlen%>",
-			      stmt));
+			      "writing one too many bytes into a region "
+			      "of a size that depends on %<strlen%>"));
     }
   else if (lenrng[0] == lenrng[1])
     {
@@ -2036,65 +2035,65 @@ maybe_warn_overflow (gimple *stmt, tree len, pointer_query &ptr_qry,
 	warned = (writefn
 		  ? warning_n (loc, OPT_Wstringop_overflow_,
 			       lenrng[0].to_uhwi (),
-			       "%G%qD writing %wu byte into a region "
+			       "%qD writing %wu byte into a region "
 			       "of size %wu",
-			       "%G%qD writing %wu bytes into a region "
+			       "%qD writing %wu bytes into a region "
 			       "of size %wu",
-			       stmt, writefn, lenrng[0].to_uhwi (),
+			       writefn, lenrng[0].to_uhwi (),
 			       spcrng[0].to_uhwi ())
 		  : warning_n (loc, OPT_Wstringop_overflow_,
 			       lenrng[0].to_uhwi (),
-			       "%Gwriting %wu byte into a region "
+			       "writing %wu byte into a region "
 			       "of size %wu",
-			       "%Gwriting %wu bytes into a region "
+			       "writing %wu bytes into a region "
 			       "of size %wu",
-			       stmt, lenrng[0].to_uhwi (),
+			       lenrng[0].to_uhwi (),
 			       spcrng[0].to_uhwi ()));
       else
 	warned = (writefn
 		  ? warning_n (loc, OPT_Wstringop_overflow_,
 			       lenrng[0].to_uhwi (),
-			       "%G%qD writing %wu byte into a region "
+			       "%qD writing %wu byte into a region "
 			       "of size between %wu and %wu",
-			       "%G%qD writing %wu bytes into a region "
+			       "%qD writing %wu bytes into a region "
 			       "of size between %wu and %wu",
-			       stmt, writefn, lenrng[0].to_uhwi (),
+			       writefn, lenrng[0].to_uhwi (),
 			       spcrng[0].to_uhwi (), spcrng[1].to_uhwi ())
 		  : warning_n (loc, OPT_Wstringop_overflow_,
 			       lenrng[0].to_uhwi (),
-			       "%Gwriting %wu byte into a region "
+			       "writing %wu byte into a region "
 			       "of size between %wu and %wu",
-			       "%Gwriting %wu bytes into a region "
+			       "writing %wu bytes into a region "
 			       "of size between %wu and %wu",
-			       stmt, lenrng[0].to_uhwi (),
+			       lenrng[0].to_uhwi (),
 			       spcrng[0].to_uhwi (), spcrng[1].to_uhwi ()));
     }
   else if (spcrng[0] == spcrng[1])
     warned = (writefn
 	      ? warning_at (loc, OPT_Wstringop_overflow_,
-			    "%G%qD writing between %wu and %wu bytes "
+			    "%qD writing between %wu and %wu bytes "
 			    "into a region of size %wu",
-			    stmt, writefn, lenrng[0].to_uhwi (),
+			    writefn, lenrng[0].to_uhwi (),
 			    lenrng[1].to_uhwi (),
 			    spcrng[0].to_uhwi ())
 	      : warning_at (loc, OPT_Wstringop_overflow_,
-			    "%Gwriting between %wu and %wu bytes "
+			    "writing between %wu and %wu bytes "
 			    "into a region of size %wu",
-			    stmt, lenrng[0].to_uhwi (),
+			    lenrng[0].to_uhwi (),
 			    lenrng[1].to_uhwi (),
 			    spcrng[0].to_uhwi ()));
   else
     warned = (writefn
 	      ? warning_at (loc, OPT_Wstringop_overflow_,
-			    "%G%qD writing between %wu and %wu bytes "
+			    "%qD writing between %wu and %wu bytes "
 			    "into a region of size between %wu and %wu",
-			    stmt, writefn, lenrng[0].to_uhwi (),
+			    writefn, lenrng[0].to_uhwi (),
 			    lenrng[1].to_uhwi (),
 			    spcrng[0].to_uhwi (), spcrng[1].to_uhwi ())
 	      : warning_at (loc, OPT_Wstringop_overflow_,
-			    "%Gwriting between %wu and %wu bytes "
+			    "writing between %wu and %wu bytes "
 			    "into a region of size between %wu and %wu",
-			    stmt, lenrng[0].to_uhwi (),
+			    lenrng[0].to_uhwi (),
 			    lenrng[1].to_uhwi (),
 			    spcrng[0].to_uhwi (), spcrng[1].to_uhwi ()));
 
@@ -2985,13 +2984,13 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
       if (lenrange[0] == cntrange[1] && cntrange[0] == cntrange[1])
 	return warning_n (callloc, OPT_Wstringop_truncation,
 			  cntrange[0].to_uhwi (),
-			  "%G%qD output truncated before terminating "
+			  "%qD output truncated before terminating "
 			  "nul copying %E byte from a string of the "
 			  "same length",
-			  "%G%qD output truncated before terminating nul "
+			  "%qD output truncated before terminating nul "
 			  "copying %E bytes from a string of the same "
 			  "length",
-			  stmt, func, cnt);
+			  func, cnt);
       else if (!cat_dstlen_bounded)
 	{
 	  if (wi::geu_p (lenrange[0], cntrange[1]))
@@ -3001,16 +3000,16 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
 	      if (cntrange[0] == cntrange[1])
 		return warning_n (callloc, OPT_Wstringop_truncation,
 				  cntrange[0].to_uhwi (),
-				  "%G%qD output truncated copying %E byte "
+				  "%qD output truncated copying %E byte "
 				  "from a string of length %wu",
-				  "%G%qD output truncated copying %E bytes "
+				  "%qD output truncated copying %E bytes "
 				  "from a string of length %wu",
-				  stmt, func, cnt, lenrange[0].to_uhwi ());
+				  func, cnt, lenrange[0].to_uhwi ());
 
 	      return warning_at (callloc, OPT_Wstringop_truncation,
-				 "%G%qD output truncated copying between %wu "
+				 "%qD output truncated copying between %wu "
 				 "and %wu bytes from a string of length %wu",
-				 stmt, func, cntrange[0].to_uhwi (),
+				 func, cntrange[0].to_uhwi (),
 				 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
 	    }
 	  else if (wi::geu_p (lenrange[1], cntrange[1]))
@@ -3020,16 +3019,16 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
 	      if (cntrange[0] == cntrange[1])
 		return warning_n (callloc, OPT_Wstringop_truncation,
 				  cntrange[0].to_uhwi (),
-				  "%G%qD output may be truncated copying %E "
+				  "%qD output may be truncated copying %E "
 				  "byte from a string of length %wu",
-				  "%G%qD output may be truncated copying %E "
+				  "%qD output may be truncated copying %E "
 				  "bytes from a string of length %wu",
-				  stmt, func, cnt, lenrange[1].to_uhwi ());
+				  func, cnt, lenrange[1].to_uhwi ());
 
 	      return warning_at (callloc, OPT_Wstringop_truncation,
-				 "%G%qD output may be truncated copying between "
+				 "%qD output may be truncated copying between "
 				 "%wu and %wu bytes from a string of length %wu",
-				 stmt, func, cntrange[0].to_uhwi (),
+				 func, cntrange[0].to_uhwi (),
 				 cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
 	    }
 	}
@@ -3043,9 +3042,9 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
 	     the lower bound of the specified count but shorter than the
 	     upper bound the copy may (but need not) be truncated.  */
 	  return warning_at (callloc, OPT_Wstringop_truncation,
-			     "%G%qD output may be truncated copying between "
+			     "%qD output may be truncated copying between "
 			     "%wu and %wu bytes from a string of length %wu",
-			     stmt, func, cntrange[0].to_uhwi (),
+			     func, cntrange[0].to_uhwi (),
 			     cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
 	}
     }
@@ -3072,8 +3071,8 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
 
       if (cntrange[0] == cntrange[1])
 	return warning_at (callloc, OPT_Wstringop_truncation,
-			   "%G%qD specified bound %E equals destination size",
-			   stmt, func, cnt);
+			   "%qD specified bound %E equals destination size",
+			   func, cnt);
     }
 
   return false;
@@ -3197,9 +3196,9 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
       && sisrc == silen
       && is_strlen_related_p (src, len)
       && warning_at (callloc, OPT_Wstringop_truncation,
-		     "%G%qD output truncated before terminating nul "
+		     "%qD output truncated before terminating nul "
 		     "copying as many bytes from a string as its length",
-		     stmt, func))
+		     func))
     warned = true;
   else if ((append_p || !dstsize || len == dstlenp1)
 	   && silen && is_strlen_related_p (src, silen->ptr))
@@ -3210,9 +3209,9 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
       opt_code opt = (append_p || dstsize
 		      ? OPT_Wstringop_overflow_ : OPT_Wstringop_truncation);
       warned = warning_at (callloc, opt,
-			   "%G%qD specified bound depends on the length "
+			   "%qD specified bound depends on the length "
 			   "of the source argument",
-			   stmt, func);
+			   func);
     }
   if (warned)
     {
@@ -4141,24 +4140,24 @@ maybe_warn_pointless_strcmp (gimple *stmt, HOST_WIDE_INT bound,
   if (siz <= minlen && bound == -1)
     warned = warning_at (stmt_loc, OPT_Wstring_compare,
 			 (at_least
-			  ? G_("%G%qD of a string of length %wu or more and "
+			  ? G_("%qD of a string of length %wu or more and "
 			       "an array of size %wu evaluates to nonzero")
-			  : G_("%G%qD of a string of length %wu and an array "
+			  : G_("%qD of a string of length %wu and an array "
 			       "of size %wu evaluates to nonzero")),
-			 stmt, callee, minlen, siz);
+			 callee, minlen, siz);
   else if (!at_least && siz <= HOST_WIDE_INT_MAX)
     {
       if (len[0] != HOST_WIDE_INT_MAX && len[1] != HOST_WIDE_INT_MAX)
 	warned = warning_at (stmt_loc, OPT_Wstring_compare,
-			     "%G%qD of strings of length %wu and %wu "
+			     "%qD of strings of length %wu and %wu "
 			     "and bound of %wu evaluates to nonzero",
-			     stmt, callee, len[0], len[1], bound);
+			     callee, len[0], len[1], bound);
       else
 	warned = warning_at (stmt_loc, OPT_Wstring_compare,
-			     "%G%qD of a string of length %wu, an array "
+			     "%qD of a string of length %wu, an array "
 			     "of size %wu and bound of %wu evaluates to "
 			     "nonzero",
-			     stmt, callee, minlen, siz, bound);
+			     callee, minlen, siz, bound);
     }
 
   if (!warned)
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index 99442d7f975..24ac031a693 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -444,7 +444,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
   if (wlims.always_executed)
     {
       if (warning_at (location, OPT_Wuninitialized,
-		      "%G%qE is used uninitialized", stmt, rhs))
+		      "%qE is used uninitialized", rhs))
 	{
 	  /* ???  This is only effective for decls as in
 	     gcc.dg/uninit-B-O0.c.  Avoid doing this for maybe-uninit
@@ -457,7 +457,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
     }
   else if (wlims.wmaybe_uninit)
     warned = warning_at (location, OPT_Wmaybe_uninitialized,
-			 "%G%qE may be used uninitialized", stmt, rhs);
+			 "%qE may be used uninitialized", rhs);
 
   return warned ? base : NULL_TREE;
 }

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PING][PATCH 4/4] remove %G and %K support from pretty printer and -Wformat (PR 98512)
  2021-06-10 23:30       ` [PATCH 4/4] remove %G and %K support from pretty printer and -Wformat " Martin Sebor
@ 2021-06-30 16:17         ` Martin Sebor
  2021-06-30 23:38         ` [PATCH " David Malcolm
  1 sibling, 0 replies; 44+ messages in thread
From: Martin Sebor @ 2021-06-30 16:17 UTC (permalink / raw)
  To: gcc-patches

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/572519.html

On 6/10/21 5:30 PM, Martin Sebor wrote:
> This final diff removes the handlers for %G and %K from the pretty
> printer and the support for the directives from c-format.c so that
> using them will be diagnosed.


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PING][PATCH 2/4] remove %G and %K from calls in front end and middle end (PR 98512)
  2021-06-30 15:39         ` [PING][PATCH " Martin Sebor
@ 2021-06-30 19:45           ` Martin Sebor
  2021-06-30 23:35             ` David Malcolm
  0 siblings, 1 reply; 44+ messages in thread
From: Martin Sebor @ 2021-06-30 19:45 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm, Jeff Law, Aldy Hernandez

[-- Attachment #1: Type: text/plain, Size: 743 bytes --]

On 6/30/21 9:39 AM, Martin Sebor wrote:
> Ping.  Attached is the same patch rebased on top the latest trunk.

Please see the attached patch instead.  The previous one had typo
in it.

> 
> As discussed in the review of Aldy's recent changes to the backwards
> threader, he has run into the same bug the patch fixes.  Getting this
> patch set reviewed and approved would be helpful in keeping him from
> having to work around the bug.
> 
> https://gcc.gnu.org/pipermail/gcc/2021-June/236608.html
> 
> On 6/10/21 5:27 PM, Martin Sebor wrote:
>> This diff removes the uses of %G and %K from all warning_at() calls
>> throughout GCC front end and middle end.  The inlining context is
>> included in diagnostic output whenever it's present.
> 


[-- Attachment #2: gcc-98512-2.diff --]
[-- Type: text/x-patch, Size: 83771 bytes --]

Improve warning suppression for inlined functions.

Resolves:
PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at declaration site
PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective in conjunction with alias attribute

gcc/ChangeLog:

	* builtins.c (warn_string_no_nul): Remove %G.
	(maybe_warn_for_bound): Same.
	(warn_for_access): Same.
	(check_access): Same.
	(check_strncat_sizes): Same.
	(expand_builtin_strncat): Same.
	(expand_builtin_strncmp): Same.
	(expand_builtin): Same.
	(expand_builtin_object_size): Same.
	(warn_dealloc_offset): Same.
	(maybe_emit_free_warning): Same.
	* calls.c (maybe_warn_alloc_args_overflow): Same.
	(maybe_warn_nonstring_arg): Same.
	(maybe_warn_rdwr_sizes): Same.
	* expr.c (expand_expr_real_1): Remove %K.
	* gimple-fold.c (gimple_fold_builtin_strncpy): Remove %G.
	(gimple_fold_builtin_strncat): Same.
	* gimple-ssa-sprintf.c (format_directive): Same.
	(handle_printf_call): Same.
	* gimple-ssa-warn-alloca.c (pass_walloca::execute): Same.
	* gimple-ssa-warn-restrict.c (maybe_diag_overlap): Same.
	(maybe_diag_access_bounds): Same.  Call gimple_location.
	(check_bounds_or_overlap): Same.
	* trans-mem.c (ipa_tm_scan_irr_block): Remove %K.  Simplify.
	* tree-ssa-ccp.c (pass_post_ipa_warn::execute): Remove %G.
	* tree-ssa-strlen.c (maybe_warn_overflow): Same.
	(maybe_diag_stxncpy_trunc): Same.
	(handle_builtin_stxncpy_strncat): Same.
	(maybe_warn_pointless_strcmp): Same.
	* tree-ssa-uninit.c (maybe_warn_operand): Same.

gcc/testsuite/ChangeLog:

	* gcc.dg/Wfree-nonheap-object-4.c: Tighten up.
	* gcc.dg/Wobjsize-1.c: Prune expected output.
	* gcc.dg/Warray-bounds-71.c: New test.
	* gcc.dg/Warray-bounds-71.h: New test.
	* gcc.dg/Warray-bounds-72.c: New test.
	* gcc.dg/Warray-bounds-73.c: New test.
	* gcc.dg/Warray-bounds-74.c: New test.
	* gcc.dg/Warray-bounds-75.c: New test.
	* gcc.dg/Wfree-nonheap-object-5.c: New test.
	* gcc.dg/pragma-diag-10.c: New test.
	* gcc.dg/pragma-diag-9.c: New test.
	* gcc.dg/uninit-suppress_3.c: New test.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index e5e39386a93..e52fe4291c8 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -1126,30 +1126,30 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
 	{
 	  if (wi::ltu_p (maxsiz, bndrng[0]))
 	    warned = warning_at (loc, opt,
-				 "%K%qD specified bound %s exceeds "
+				 "%qD specified bound %s exceeds "
 				 "maximum object size %E",
-				 expr, func, bndstr, maxobjsize);
+				 func, bndstr, maxobjsize);
 	  else
 	    {
 	      bool maybe = wi::to_wide (size) == bndrng[0];
 	      warned = warning_at (loc, opt,
 				   exact
-				   ? G_("%K%qD specified bound %s exceeds "
+				   ? G_("%qD specified bound %s exceeds "
 					"the size %E of unterminated array")
 				   : (maybe
-				      ? G_("%K%qD specified bound %s may "
+				      ? G_("%qD specified bound %s may "
 					   "exceed the size of at most %E "
 					   "of unterminated array")
-				      : G_("%K%qD specified bound %s exceeds "
+				      : G_("%qD specified bound %s exceeds "
 					   "the size of at most %E "
 					   "of unterminated array")),
-				   expr, func, bndstr, size);
+				   func, bndstr, size);
 	    }
 	}
       else
 	warned = warning_at (loc, opt,
-			     "%K%qD argument missing terminating nul",
-			     expr, func);
+			     "%qD argument missing terminating nul",
+			     func);
     }
   else
     {
@@ -3969,35 +3969,34 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func,
 	    warned = (func
 		      ? warning_at (loc, opt,
 				    (maybe
-				     ? G_("%K%qD specified bound %E may "
+				     ? G_("%qD specified bound %E may "
 					  "exceed maximum object size %E")
-				     : G_("%K%qD specified bound %E "
+				     : G_("%qD specified bound %E "
 					  "exceeds maximum object size %E")),
-				    exp, func, bndrng[0], maxobjsize)
+				    func, bndrng[0], maxobjsize)
 		      : warning_at (loc, opt,
 				    (maybe
-				     ? G_("%Kspecified bound %E may "
+				     ? G_("specified bound %E may "
 					  "exceed maximum object size %E")
-				     : G_("%Kspecified bound %E "
+				     : G_("specified bound %E "
 					  "exceeds maximum object size %E")),
-				    exp, bndrng[0], maxobjsize));
+				    bndrng[0], maxobjsize));
 	  else
 	    warned = (func
 		      ? warning_at (loc, opt,
 				    (maybe
-				     ? G_("%K%qD specified bound [%E, %E] may "
+				     ? G_("%qD specified bound [%E, %E] may "
 					  "exceed maximum object size %E")
-				     : G_("%K%qD specified bound [%E, %E] "
+				     : G_("%qD specified bound [%E, %E] "
 					  "exceeds maximum object size %E")),
-				    exp, func,
-				    bndrng[0], bndrng[1], maxobjsize)
+				    func, bndrng[0], bndrng[1], maxobjsize)
 		      : warning_at (loc, opt,
 				    (maybe
-				     ? G_("%Kspecified bound [%E, %E] may "
+				     ? G_("specified bound [%E, %E] may "
 					  "exceed maximum object size %E")
-				     : G_("%Kspecified bound [%E, %E] "
+				     : G_("specified bound [%E, %E] "
 					  "exceeds maximum object size %E")),
-				    exp, bndrng[0], bndrng[1], maxobjsize));
+				    bndrng[0], bndrng[1], maxobjsize));
 	}
       else if (!size || tree_int_cst_le (bndrng[0], size))
 	return false;
@@ -4005,34 +4004,34 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func,
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD specified bound %E may exceed "
+				 ? G_("%qD specified bound %E may exceed "
 				      "source size %E")
-				 : G_("%K%qD specified bound %E exceeds "
+				 : G_("%qD specified bound %E exceeds "
 				      "source size %E")),
-				exp, func, bndrng[0], size)
+				func, bndrng[0], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kspecified bound %E may exceed "
+				 ? G_("specified bound %E may exceed "
 				      "source size %E")
-				 : G_("%Kspecified bound %E exceeds "
+				 : G_("specified bound %E exceeds "
 				      "source size %E")),
-				exp, bndrng[0], size));
+				bndrng[0], size));
       else
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD specified bound [%E, %E] may "
+				 ? G_("%qD specified bound [%E, %E] may "
 				      "exceed source size %E")
-				 : G_("%K%qD specified bound [%E, %E] exceeds "
+				 : G_("%qD specified bound [%E, %E] exceeds "
 				      "source size %E")),
-				exp, func, bndrng[0], bndrng[1], size)
+				func, bndrng[0], bndrng[1], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kspecified bound [%E, %E] may exceed "
+				 ? G_("specified bound [%E, %E] may exceed "
 				      "source size %E")
-				 : G_("%Kspecified bound [%E, %E] exceeds "
+				 : G_("specified bound [%E, %E] exceeds "
 				      "source size %E")),
-				exp, bndrng[0], bndrng[1], size));
+				bndrng[0], bndrng[1], size));
       if (warned)
 	{
 	  if (pad && pad->src.ref)
@@ -4057,35 +4056,34 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func,
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD specified size %E may "
+				 ? G_("%qD specified size %E may "
 				      "exceed maximum object size %E")
-				 : G_("%K%qD specified size %E "
+				 : G_("%qD specified size %E "
 				      "exceeds maximum object size %E")),
-				exp, func, bndrng[0], maxobjsize)
+				func, bndrng[0], maxobjsize)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kspecified size %E may exceed "
+				 ? G_("specified size %E may exceed "
 				      "maximum object size %E")
-				 : G_("%Kspecified size %E exceeds "
+				 : G_("specified size %E exceeds "
 				      "maximum object size %E")),
-				exp, bndrng[0], maxobjsize));
+				bndrng[0], maxobjsize));
       else
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD specified size between %E and %E "
+				 ? G_("%qD specified size between %E and %E "
 				      "may exceed maximum object size %E")
-				 : G_("%K%qD specified size between %E and %E "
+				 : G_("%qD specified size between %E and %E "
 				      "exceeds maximum object size %E")),
-				exp, func,
-				bndrng[0], bndrng[1], maxobjsize)
+				func, bndrng[0], bndrng[1], maxobjsize)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kspecified size between %E and %E "
+				 ? G_("specified size between %E and %E "
 				      "may exceed maximum object size %E")
-				 : G_("%Kspecified size between %E and %E "
+				 : G_("specified size between %E and %E "
 				      "exceeds maximum object size %E")),
-				exp, bndrng[0], bndrng[1], maxobjsize));
+				bndrng[0], bndrng[1], maxobjsize));
     }
   else if (!size || tree_int_cst_le (bndrng[0], size))
     return false;
@@ -4093,34 +4091,34 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func,
     warned = (func
 	      ? warning_at (loc, opt,
 			    (maybe
-			     ? G_("%K%qD specified bound %E may exceed "
+			     ? G_("%qD specified bound %E may exceed "
 				  "destination size %E")
-			     : G_("%K%qD specified bound %E exceeds "
+			     : G_("%qD specified bound %E exceeds "
 				  "destination size %E")),
-			    exp, func, bndrng[0], size)
+			    func, bndrng[0], size)
 	      : warning_at (loc, opt,
 			    (maybe
-			     ? G_("%Kspecified bound %E may exceed "
+			     ? G_("specified bound %E may exceed "
 				  "destination size %E")
-			     : G_("%Kspecified bound %E exceeds "
+			     : G_("specified bound %E exceeds "
 				  "destination size %E")),
-			    exp, bndrng[0], size));
+			    bndrng[0], size));
   else
     warned = (func
 	      ? warning_at (loc, opt,
 			    (maybe
-			     ? G_("%K%qD specified bound [%E, %E] may exceed "
+			     ? G_("%qD specified bound [%E, %E] may exceed "
 				  "destination size %E")
-			     : G_("%K%qD specified bound [%E, %E] exceeds "
+			     : G_("%qD specified bound [%E, %E] exceeds "
 				  "destination size %E")),
-			    exp, func, bndrng[0], bndrng[1], size)
+			    func, bndrng[0], bndrng[1], size)
 	      : warning_at (loc, opt,
 			    (maybe
-			     ? G_("%Kspecified bound [%E, %E] exceeds "
+			     ? G_("specified bound [%E, %E] exceeds "
 				  "destination size %E")
-			     : G_("%Kspecified bound [%E, %E] exceeds "
+			     : G_("specified bound [%E, %E] exceeds "
 				  "destination size %E")),
-			    exp, bndrng[0], bndrng[1], size));
+			    bndrng[0], bndrng[1], size));
 
   if (warned)
     {
@@ -4158,65 +4156,63 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
 	warned = (func
 		  ? warning_n (loc, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%K%qD may access %E byte in a region "
+				? G_("%qD may access %E byte in a region "
 				     "of size %E")
-				: G_("%K%qD accessing %E byte in a region "
+				: G_("%qD accessing %E byte in a region "
 				     "of size %E")),
 				(maybe
-				 ? G_ ("%K%qD may access %E bytes in a region "
+				 ? G_ ("%qD may access %E bytes in a region "
 				       "of size %E")
-				 : G_ ("%K%qD accessing %E bytes in a region "
+				 : G_ ("%qD accessing %E bytes in a region "
 				       "of size %E")),
-			       exp, func, range[0], size)
+			       func, range[0], size)
 		  : warning_n (loc, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%Kmay access %E byte in a region "
+				? G_("may access %E byte in a region "
 				     "of size %E")
-				: G_("%Kaccessing %E byte in a region "
+				: G_("accessing %E byte in a region "
 				     "of size %E")),
 			       (maybe
-				? G_("%Kmay access %E bytes in a region "
+				? G_("may access %E bytes in a region "
 				     "of size %E")
-				: G_("%Kaccessing %E bytes in a region "
+				: G_("accessing %E bytes in a region "
 				     "of size %E")),
-			       exp, range[0], size));
+			       range[0], size));
       else if (tree_int_cst_sign_bit (range[1]))
 	{
 	  /* Avoid printing the upper bound if it's invalid.  */
 	  warned = (func
 		    ? warning_at (loc, opt,
 				  (maybe
-				   ? G_("%K%qD may access %E or more bytes "
+				   ? G_("%qD may access %E or more bytes "
 					"in a region of size %E")
-				   : G_("%K%qD accessing %E or more bytes "
+				   : G_("%qD accessing %E or more bytes "
 					"in a region of size %E")),
-				  exp, func, range[0], size)
+				  func, range[0], size)
 		    : warning_at (loc, opt,
 				  (maybe
-				   ? G_("%Kmay access %E or more bytes "
+				   ? G_("may access %E or more bytes "
 					"in a region of size %E")
-				   : G_("%Kaccessing %E or more bytes "
+				   : G_("accessing %E or more bytes "
 					"in a region of size %E")),
-				  exp, range[0], size));
+				  range[0], size));
 	}
       else
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD may access between %E and %E "
+				 ? G_("%qD may access between %E and %E "
 				      "bytes in a region of size %E")
-				 : G_("%K%qD accessing between %E and %E "
+				 : G_("%qD accessing between %E and %E "
 				      "bytes in a region of size %E")),
-				exp, func, range[0], range[1],
-				size)
+				func, range[0], range[1], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kmay access between %E and %E bytes "
+				 ? G_("may access between %E and %E bytes "
 				      "in a region of size %E")
-				 : G_("%Kaccessing between %E and %E bytes "
+				 : G_("accessing between %E and %E bytes "
 				      "in a region of size %E")),
-				exp, range[0], range[1],
-				size));
+				range[0], range[1], size));
       return warned;
     }
 
@@ -4226,69 +4222,67 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
 	warned = (func
 		  ? warning_n (loc, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%K%qD may write %E byte into a region "
+				? G_("%qD may write %E byte into a region "
 				     "of size %E")
-				: G_("%K%qD writing %E byte into a region "
+				: G_("%qD writing %E byte into a region "
 				     "of size %E overflows the destination")),
 			       (maybe
-				? G_("%K%qD may write %E bytes into a region "
+				? G_("%qD may write %E bytes into a region "
 				     "of size %E")
-				: G_("%K%qD writing %E bytes into a region "
+				: G_("%qD writing %E bytes into a region "
 				     "of size %E overflows the destination")),
-			       exp, func, range[0], size)
+			       func, range[0], size)
 		  : warning_n (loc, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%Kmay write %E byte into a region "
+				? G_("may write %E byte into a region "
 				     "of size %E")
-				: G_("%Kwriting %E byte into a region "
+				: G_("writing %E byte into a region "
 				     "of size %E overflows the destination")),
 			       (maybe
-				? G_("%Kmay write %E bytes into a region "
+				? G_("may write %E bytes into a region "
 				     "of size %E")
-				: G_("%Kwriting %E bytes into a region "
+				: G_("writing %E bytes into a region "
 				     "of size %E overflows the destination")),
-			       exp, range[0], size));
+			       range[0], size));
       else if (tree_int_cst_sign_bit (range[1]))
 	{
 	  /* Avoid printing the upper bound if it's invalid.  */
 	  warned = (func
 		    ? warning_at (loc, opt,
 				  (maybe
-				   ? G_("%K%qD may write %E or more bytes "
+				   ? G_("%qD may write %E or more bytes "
 					"into a region of size %E")
-				   : G_("%K%qD writing %E or more bytes "
+				   : G_("%qD writing %E or more bytes "
 					"into a region of size %E overflows "
 					"the destination")),
-				  exp, func, range[0], size)
+				  func, range[0], size)
 		    : warning_at (loc, opt,
 				  (maybe
-				   ? G_("%Kmay write %E or more bytes into "
+				   ? G_("may write %E or more bytes into "
 					"a region of size %E")
-				   : G_("%Kwriting %E or more bytes into "
+				   : G_("writing %E or more bytes into "
 					"a region of size %E overflows "
 					"the destination")),
-				  exp, range[0], size));
+				  range[0], size));
 	}
       else
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD may write between %E and %E bytes "
+				 ? G_("%qD may write between %E and %E bytes "
 				      "into a region of size %E")
-				 : G_("%K%qD writing between %E and %E bytes "
+				 : G_("%qD writing between %E and %E bytes "
 				      "into a region of size %E overflows "
 				      "the destination")),
-				exp, func, range[0], range[1],
-				size)
+				func, range[0], range[1], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kmay write between %E and %E bytes "
+				 ? G_("may write between %E and %E bytes "
 				      "into a region of size %E")
-				 : G_("%Kwriting between %E and %E bytes "
+				 : G_("writing between %E and %E bytes "
 				      "into a region of size %E overflows "
 				      "the destination")),
-				exp, range[0], range[1],
-				size));
+				range[0], range[1], size));
       return warned;
     }
 
@@ -4299,64 +4293,64 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
 		  ? warning_n (loc, OPT_Wstringop_overread,
 			       tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%K%qD may read %E byte from a region "
+				? G_("%qD may read %E byte from a region "
 				     "of size %E")
-				: G_("%K%qD reading %E byte from a region "
+				: G_("%qD reading %E byte from a region "
 				     "of size %E")),
 			       (maybe
-				? G_("%K%qD may read %E bytes from a region "
+				? G_("%qD may read %E bytes from a region "
 				     "of size %E")
-				: G_("%K%qD reading %E bytes from a region "
+				: G_("%qD reading %E bytes from a region "
 				     "of size %E")),
-			       exp, func, range[0], size)
+			       func, range[0], size)
 		  : warning_n (loc, OPT_Wstringop_overread,
 			       tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%Kmay read %E byte from a region "
+				? G_("may read %E byte from a region "
 				     "of size %E")
-				: G_("%Kreading %E byte from a region "
+				: G_("reading %E byte from a region "
 				     "of size %E")),
 			       (maybe
-				? G_("%Kmay read %E bytes from a region "
+				? G_("may read %E bytes from a region "
 				     "of size %E")
-				: G_("%Kreading %E bytes from a region "
+				: G_("reading %E bytes from a region "
 				     "of size %E")),
-			       exp, range[0], size));
+			       range[0], size));
       else if (tree_int_cst_sign_bit (range[1]))
 	{
 	  /* Avoid printing the upper bound if it's invalid.  */
 	  warned = (func
 		    ? warning_at (loc, OPT_Wstringop_overread,
 				  (maybe
-				   ? G_("%K%qD may read %E or more bytes "
+				   ? G_("%qD may read %E or more bytes "
 					"from a region of size %E")
-				   : G_("%K%qD reading %E or more bytes "
+				   : G_("%qD reading %E or more bytes "
 					"from a region of size %E")),
-				  exp, func, range[0], size)
+				  func, range[0], size)
 		    : warning_at (loc, OPT_Wstringop_overread,
 				  (maybe
-				   ? G_("%Kmay read %E or more bytes "
+				   ? G_("may read %E or more bytes "
 					"from a region of size %E")
-				   : G_("%Kreading %E or more bytes "
+				   : G_("reading %E or more bytes "
 					"from a region of size %E")),
-				  exp, range[0], size));
+				  range[0], size));
 	}
       else
 	warned = (func
 		  ? warning_at (loc, OPT_Wstringop_overread,
 				(maybe
-				 ? G_("%K%qD may read between %E and %E bytes "
+				 ? G_("%qD may read between %E and %E bytes "
 				      "from a region of size %E")
-				 : G_("%K%qD reading between %E and %E bytes "
+				 : G_("%qD reading between %E and %E bytes "
 				      "from a region of size %E")),
-				exp, func, range[0], range[1], size)
+				func, range[0], range[1], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kmay read between %E and %E bytes "
+				 ? G_("may read between %E and %E bytes "
 				      "from a region of size %E")
-				 : G_("%Kreading between %E and %E bytes "
+				 : G_("reading between %E and %E bytes "
 				      "from a region of size %E")),
-				exp, range[0], range[1], size));
+				range[0], range[1], size));
 
       if (warned)
 	suppress_warning (exp, OPT_Wstringop_overread);
@@ -4369,37 +4363,37 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
     warned = (func
 	      ? warning_n (loc, OPT_Wstringop_overread,
 			   tree_to_uhwi (range[0]),
-			   "%K%qD expecting %E byte in a region of size %E",
-			   "%K%qD expecting %E bytes in a region of size %E",
-			   exp, func, range[0], size)
+			   "%qD expecting %E byte in a region of size %E",
+			   "%qD expecting %E bytes in a region of size %E",
+			   func, range[0], size)
 	      : warning_n (loc, OPT_Wstringop_overread,
 			   tree_to_uhwi (range[0]),
-			   "%Kexpecting %E byte in a region of size %E",
-			   "%Kexpecting %E bytes in a region of size %E",
-			   exp, range[0], size));
+			   "expecting %E byte in a region of size %E",
+			   "expecting %E bytes in a region of size %E",
+			   range[0], size));
   else if (tree_int_cst_sign_bit (range[1]))
     {
       /* Avoid printing the upper bound if it's invalid.  */
       warned = (func
 		? warning_at (loc, OPT_Wstringop_overread,
-			      "%K%qD expecting %E or more bytes in a region "
+			      "%qD expecting %E or more bytes in a region "
 			      "of size %E",
-			      exp, func, range[0], size)
+			      func, range[0], size)
 		: warning_at (loc, OPT_Wstringop_overread,
-			      "%Kexpecting %E or more bytes in a region "
+			      "expecting %E or more bytes in a region "
 			      "of size %E",
-			      exp, range[0], size));
+			      range[0], size));
     }
   else
     warned = (func
 	      ? warning_at (loc, OPT_Wstringop_overread,
-			    "%K%qD expecting between %E and %E bytes in "
+			    "%qD expecting between %E and %E bytes in "
 			    "a region of size %E",
-			    exp, func, range[0], range[1], size)
+			    func, range[0], range[1], size)
 	      : warning_at (loc, OPT_Wstringop_overread,
-			    "%Kexpecting between %E and %E bytes in "
+			    "expecting between %E and %E bytes in "
 			    "a region of size %E",
-			    exp, range[0], range[1], size));
+			    range[0], range[1], size));
 
   if (warned)
     suppress_warning (exp, OPT_Wstringop_overread);
@@ -4759,7 +4753,7 @@ check_access (tree exp, tree dstwrite,
       && TREE_CODE (range[0]) == INTEGER_CST
       && tree_int_cst_lt (maxobjsize, range[0]))
     {
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       maybe_warn_for_bound (OPT_Wstringop_overflow_, loc, exp, func, range,
 			    NULL_TREE, pad);
       return false;
@@ -4787,7 +4781,7 @@ check_access (tree exp, tree dstwrite,
 		  && warning_suppressed_p (pad->dst.ref, opt)))
 	    return false;
 
-	  location_t loc = tree_inlined_location (exp);
+	  location_t loc = EXPR_LOCATION (exp);
 	  bool warned = false;
 	  if (dstwrite == slen && at_least_one)
 	    {
@@ -4796,15 +4790,15 @@ check_access (tree exp, tree dstwrite,
 		 at least one byte past the end of the destination.  */
 	      warned = (func
 			? warning_at (loc, opt,
-				      "%K%qD writing %E or more bytes into "
+				      "%qD writing %E or more bytes into "
 				      "a region of size %E overflows "
 				      "the destination",
-				      exp, func, range[0], dstsize)
+				      func, range[0], dstsize)
 			: warning_at (loc, opt,
-				      "%Kwriting %E or more bytes into "
+				      "writing %E or more bytes into "
 				      "a region of size %E overflows "
 				      "the destination",
-				      exp, range[0], dstsize));
+				      range[0], dstsize));
 	    }
 	  else
 	    {
@@ -4840,7 +4834,7 @@ check_access (tree exp, tree dstwrite,
 	 PAD is nonnull and BNDRNG is valid.  */
       get_size_range (maxread, range, pad ? pad->src.bndrng : NULL);
 
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       tree size = dstsize;
       if (pad && pad->mode == access_read_only)
 	size = wide_int_to_tree (sizetype, pad->src.sizrng[1]);
@@ -4901,7 +4895,7 @@ check_access (tree exp, tree dstwrite,
 	      && warning_suppressed_p (pad->src.ref, opt)))
 	return false;
 
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       const bool read
 	= mode == access_read_only || mode == access_read_write;
       const bool maybe = pad && pad->dst.parmarray;
@@ -6481,10 +6475,10 @@ check_strncat_sizes (tree exp, tree objsize)
   if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (objsize)
       && tree_int_cst_equal (objsize, maxread))
     {
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       warning_at (loc, OPT_Wstringop_overflow_,
-		  "%K%qD specified bound %E equals destination size",
-		  exp, get_callee_fndecl (exp), maxread);
+		  "%qD specified bound %E equals destination size",
+		  get_callee_fndecl (exp), maxread);
 
       return false;
     }
@@ -6554,10 +6548,10 @@ expand_builtin_strncat (tree exp, rtx)
   if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (destsize)
       && tree_int_cst_equal (destsize, maxread))
     {
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       warning_at (loc, OPT_Wstringop_overflow_,
-		  "%K%qD specified bound %E equals destination size",
-		  exp, get_callee_fndecl (exp), maxread);
+		  "%qD specified bound %E equals destination size",
+		  get_callee_fndecl (exp), maxread);
 
       return NULL_RTX;
     }
@@ -7330,7 +7324,7 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
       || !check_nul_terminated_array (exp, arg2, arg3))
     return NULL_RTX;
 
-  location_t loc = tree_inlined_location (exp);
+  location_t loc = EXPR_LOCATION (exp);
   tree len1 = c_strlen (arg1, 1);
   tree len2 = c_strlen (arg2, 1);
 
@@ -10006,13 +10000,13 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
     case BUILT_IN_VA_ARG_PACK:
       /* All valid uses of __builtin_va_arg_pack () are removed during
 	 inlining.  */
-      error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
+      error ("invalid use of %<__builtin_va_arg_pack ()%>");
       return const0_rtx;
 
     case BUILT_IN_VA_ARG_PACK_LEN:
       /* All valid uses of __builtin_va_arg_pack_len () are removed during
 	 inlining.  */
-      error ("%Kinvalid use of %<__builtin_va_arg_pack_len ()%>", exp);
+      error ("invalid use of %<__builtin_va_arg_pack_len ()%>");
       return const0_rtx;
 
       /* Return the address of the first anonymous stack arg.  */
@@ -12961,8 +12955,8 @@ expand_builtin_object_size (tree exp)
 
   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
     {
-      error ("%Kfirst argument of %qD must be a pointer, second integer constant",
-	     exp, fndecl);
+      error ("first argument of %qD must be a pointer, second integer constant",
+	     fndecl);
       expand_builtin_trap ();
       return const0_rtx;
     }
@@ -12974,8 +12968,8 @@ expand_builtin_object_size (tree exp)
       || tree_int_cst_sgn (ost) < 0
       || compare_tree_int (ost, 3) > 0)
     {
-      error ("%Klast argument of %qD is not integer constant between 0 and 3",
-	     exp, fndecl);
+      error ("last argument of %qD is not integer constant between 0 and 3",
+	      fndecl);
       expand_builtin_trap ();
       return const0_rtx;
     }
@@ -13787,8 +13781,8 @@ warn_dealloc_offset (location_t loc, tree exp, const access_ref &aref)
     }
 
   if (!warning_at (loc, OPT_Wfree_nonheap_object,
-		   "%K%qD called on pointer %qE with nonzero offset%s",
-		   exp, dealloc_decl, aref.ref, offstr))
+		   "%qD called on pointer %qE with nonzero offset%s",
+		   dealloc_decl, aref.ref, offstr))
     return false;
 
   if (DECL_P (aref.ref))
@@ -13843,15 +13837,15 @@ maybe_emit_free_warning (tree exp)
     return;
 
   tree dealloc_decl = get_callee_fndecl (exp);
-  location_t loc = tree_inlined_location (exp);
+  location_t loc = EXPR_LOCATION (exp);
 
   if (DECL_P (ref) || EXPR_P (ref))
     {
       /* Diagnose freeing a declared object.  */
       if (aref.ref_declared ()
 	  && warning_at (loc, OPT_Wfree_nonheap_object,
-			 "%K%qD called on unallocated object %qD",
-			 exp, dealloc_decl, ref))
+			 "%qD called on unallocated object %qD",
+			 dealloc_decl, ref))
 	{
 	  loc = (DECL_P (ref)
 		 ? DECL_SOURCE_LOCATION (ref)
@@ -13870,8 +13864,8 @@ maybe_emit_free_warning (tree exp)
   else if (CONSTANT_CLASS_P (ref))
     {
       if (warning_at (loc, OPT_Wfree_nonheap_object,
-		      "%K%qD called on a pointer to an unallocated "
-		      "object %qE", exp, dealloc_decl, ref))
+		      "%qD called on a pointer to an unallocated "
+		      "object %qE", dealloc_decl, ref))
 	{
 	  if (TREE_CODE (ptr) == SSA_NAME)
 	    {
@@ -13909,18 +13903,18 @@ maybe_emit_free_warning (tree exp)
 		     ? OPT_Wmismatched_new_delete
 		     : OPT_Wmismatched_dealloc);
 		  warned = warning_at (loc, opt,
-				       "%K%qD called on pointer returned "
+				       "%qD called on pointer returned "
 				       "from a mismatched allocation "
-				       "function", exp, dealloc_decl);
+				       "function", dealloc_decl);
 		}
 	    }
 	  else if (gimple_call_builtin_p (def_stmt, BUILT_IN_ALLOCA)
 	    	   || gimple_call_builtin_p (def_stmt,
 	    				     BUILT_IN_ALLOCA_WITH_ALIGN))
 	    warned = warning_at (loc, OPT_Wfree_nonheap_object,
-				 "%K%qD called on pointer to "
+				 "%qD called on pointer to "
 				 "an unallocated object",
-				 exp, dealloc_decl);
+				 dealloc_decl);
 	  else if (warn_dealloc_offset (loc, exp, aref))
 	    return;
 
diff --git a/gcc/calls.c b/gcc/calls.c
index f8a4b79e7f8..d2413a280cf 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1435,8 +1435,8 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 	  if (tree_int_cst_lt (args[i], integer_zero_node))
 	    {
 	      warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-				   "%Kargument %i value %qE is negative",
-				   exp, idx[i] + 1, args[i]);
+				   "argument %i value %qE is negative",
+				   idx[i] + 1, args[i]);
 	    }
 	  else if (integer_zerop (args[i]))
 	    {
@@ -1452,8 +1452,8 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 		  : !lookup_attribute ("returns_nonnull",
 				       TYPE_ATTRIBUTES (fntype)))
 		warned = warning_at (loc, OPT_Walloc_zero,
-				     "%Kargument %i value is zero",
-				     exp, idx[i] + 1);
+				     "argument %i value is zero",
+				     idx[i] + 1);
 	    }
 	  else if (tree_int_cst_lt (maxobjsize, args[i]))
 	    {
@@ -1470,9 +1470,9 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 		continue;
 
 	      warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-				   "%Kargument %i value %qE exceeds "
+				   "argument %i value %qE exceeds "
 				   "maximum object size %E",
-				   exp, idx[i] + 1, args[i], maxobjsize);
+				   idx[i] + 1, args[i], maxobjsize);
 	    }
 	}
       else if (TREE_CODE (args[i]) == SSA_NAME
@@ -1484,16 +1484,16 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 	      && tree_int_cst_le (argrange[i][1], integer_zero_node))
 	    {
 	      warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-				   "%Kargument %i range [%E, %E] is negative",
-				   exp, idx[i] + 1,
+				   "argument %i range [%E, %E] is negative",
+				   idx[i] + 1,
 				   argrange[i][0], argrange[i][1]);
 	    }
 	  else if (tree_int_cst_lt (maxobjsize, argrange[i][0]))
 	    {
 	      warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-				   "%Kargument %i range [%E, %E] exceeds "
+				   "argument %i range [%E, %E] exceeds "
 				   "maximum object size %E",
-				   exp, idx[i] + 1,
+				   idx[i] + 1,
 				   argrange[i][0], argrange[i][1],
 				   maxobjsize);
 	    }
@@ -1521,15 +1521,15 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 
       if (vflow)
 	warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-			     "%Kproduct %<%E * %E%> of arguments %i and %i "
+			     "product %<%E * %E%> of arguments %i and %i "
 			     "exceeds %<SIZE_MAX%>",
-			     exp, argrange[0][0], argrange[1][0],
+			     argrange[0][0], argrange[1][0],
 			     idx[0] + 1, idx[1] + 1);
       else if (wi::ltu_p (wi::to_wide (maxobjsize, szprec), prod))
 	warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-			     "%Kproduct %<%E * %E%> of arguments %i and %i "
+			     "product %<%E * %E%> of arguments %i and %i "
 			     "exceeds maximum object size %E",
-			     exp, argrange[0][0], argrange[1][0],
+			     argrange[0][0], argrange[1][0],
 			     idx[0] + 1, idx[1] + 1,
 			     maxobjsize);
 
@@ -1729,14 +1729,14 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
 	  bool warned = false;
 	  if (tree_int_cst_equal (bndrng[0], bndrng[1]))
 	    warned = warning_at (loc, OPT_Wstringop_overread,
-				 "%K%qD specified bound %E "
+				 "%qD specified bound %E "
 				 "exceeds maximum object size %E",
-				 exp, fndecl, bndrng[0], maxobjsize);
+				 fndecl, bndrng[0], maxobjsize);
 	  else
 	    warned = warning_at (loc, OPT_Wstringop_overread,
-				 "%K%qD specified bound [%E, %E] "
+				 "%qD specified bound [%E, %E] "
 				 "exceeds maximum object size %E",
-				 exp, fndecl, bndrng[0], bndrng[1],
+				 fndecl, bndrng[0], bndrng[1],
 				 maxobjsize);
 	  if (warned)
 	    suppress_warning (exp, OPT_Wstringop_overread);
@@ -2068,16 +2068,16 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 		= access.second.array_as_string (ptrtype);
 
 	      if (warning_at (loc, OPT_Wstringop_overflow_,
-			      "%Kbound argument %i value %s is "
+			      "bound argument %i value %s is "
 			      "negative for a variable length array "
 			      "argument %i of type %s",
-			      exp, sizidx + 1, sizstr,
+			      sizidx + 1, sizstr,
 			      ptridx + 1, argtypestr.c_str ()))
 		arg_warned = OPT_Wstringop_overflow_;
 	    }
 	  else if (warning_at (loc, OPT_Wstringop_overflow_,
-			       "%Kargument %i value %s is negative",
-			       exp, sizidx + 1, sizstr))
+			       "argument %i value %s is negative",
+			       sizidx + 1, sizstr))
 	    arg_warned = OPT_Wstringop_overflow_;
 
 	  if (arg_warned != no_warning)
@@ -2124,20 +2124,19 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 		    = access.second.array_as_string (ptrtype);
 
 		  if (warning_at (loc, OPT_Wnonnull,
-				  "%Kargument %i of variable length "
+				  "argument %i of variable length "
 				  "array %s is null but "
 				  "the corresponding bound argument "
 				  "%i value is %s",
-				  exp, sizidx + 1, argtypestr.c_str (),
+				  sizidx + 1, argtypestr.c_str (),
 				  ptridx + 1, sizstr))
 		    arg_warned = OPT_Wnonnull;
 		}
 	      else if (warning_at (loc, OPT_Wnonnull,
-				   "%Kargument %i is null but "
+				   "argument %i is null but "
 				   "the corresponding size argument "
 				   "%i value is %s",
-				   exp, ptridx + 1, sizidx + 1,
-				   sizstr))
+				   ptridx + 1, sizidx + 1, sizstr))
 		arg_warned = OPT_Wnonnull;
 	    }
 	  else if (access_size && access.second.static_p)
@@ -2145,10 +2144,9 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 	      /* Warn about null pointers for [static N] array arguments
 		 but do not warn for ordinary (i.e., nonstatic) arrays.  */
 	      if (warning_at (loc, OPT_Wnonnull,
-			      "%Kargument %i to %<%T[static %E]%> "
+			      "argument %i to %<%T[static %E]%> "
 			      "is null where non-null expected",
-			      exp, ptridx + 1, argtype,
-			      access_size))
+			      ptridx + 1, argtype, access_size))
 		arg_warned = OPT_Wnonnull;		
 	    }
 
diff --git a/gcc/expr.c b/gcc/expr.c
index 025033c9ecf..b9fe1cf91d7 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -11401,7 +11401,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
       /* All valid uses of __builtin_va_arg_pack () are removed during
 	 inlining.  */
       if (CALL_EXPR_VA_ARG_PACK (exp))
-	error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
+	error ("invalid use of %<__builtin_va_arg_pack ()%>");
       {
 	tree fndecl = get_callee_fndecl (exp), attr;
 
@@ -11413,7 +11413,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 					 DECL_ATTRIBUTES (fndecl))) != NULL)
 	  {
 	    const char *ident = lang_hooks.decl_printable_name (fndecl, 1);
-	    error ("%Kcall to %qs declared with attribute error: %s", exp,
+	    error ("call to %qs declared with attribute error: %s",
 		   identifier_to_locale (ident),
 		   TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
 	  }
@@ -11425,10 +11425,10 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 					 DECL_ATTRIBUTES (fndecl))) != NULL)
 	  {
 	    const char *ident = lang_hooks.decl_printable_name (fndecl, 1);
-	    warning_at (tree_nonartificial_location (exp),
+	    warning_at (EXPR_LOCATION (exp),
 			OPT_Wattribute_warning,
-			"%Kcall to %qs declared with attribute warning: %s",
-			exp, identifier_to_locale (ident),
+			"call to %qs declared with attribute warning: %s",
+			identifier_to_locale (ident),
 			TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
 	  }
 
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 68031538145..1401092aa9b 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -2115,13 +2115,13 @@ gimple_fold_builtin_strncpy (gimple_stmt_iterator *gsi,
 	  tree slen = get_maxval_strlen (src, SRK_STRLEN);
 	  if (slen && !integer_zerop (slen))
 	    warning_at (loc, OPT_Wstringop_truncation,
-			"%G%qD destination unchanged after copying no bytes "
+			"%qD destination unchanged after copying no bytes "
 			"from a string of length %E",
-			stmt, fndecl, slen);
+			fndecl, slen);
 	  else
 	    warning_at (loc, OPT_Wstringop_truncation,
-			"%G%qD destination unchanged after copying no bytes",
-			stmt, fndecl);
+			"%qD destination unchanged after copying no bytes",
+			fndecl);
 	}
 
       replace_call_with_value (gsi, dest);
@@ -2498,11 +2498,11 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
 	  location_t loc = gimple_location (stmt);
 	  nowarn = warning_at (loc, OPT_Wstringop_overflow_,
 			       cmpdst == 0
-			       ? G_("%G%qD specified bound %E equals "
+			       ? G_("%qD specified bound %E equals "
 				    "destination size")
-			       : G_("%G%qD specified bound %E exceeds "
+			       : G_("%qD specified bound %E exceeds "
 				    "destination size %wu"),
-			       stmt, fndecl, len, dstsize);
+			       fndecl, len, dstsize);
 	  if (nowarn)
 	    suppress_warning (stmt, OPT_Wstringop_overflow_);
 	}
@@ -2518,8 +2518,8 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
 	 of the destination is unknown (it's not an uncommon mistake
 	 to specify as the bound to strncpy the length of the source).  */
       if (warning_at (loc, OPT_Wstringop_overflow_,
-		      "%G%qD specified bound %E equals source length",
-		      stmt, fndecl, len))
+		      "%qD specified bound %E equals source length",
+		      fndecl, len))
 	suppress_warning (stmt, OPT_Wstringop_overflow_);
     }
 
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index 41e3be6f9f4..f38fb03f068 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -3115,9 +3115,8 @@ format_directive (const call_info &info,
   if (fmtres.nullp)
     {
       fmtwarn (dirloc, argloc, NULL, info.warnopt (),
-	       "%G%<%.*s%> directive argument is null",
-	       info.callstmt, dirlen,
-	       target_to_host (hostdir, sizeof hostdir, dir.beg));
+	       "%<%.*s%> directive argument is null",
+	       dirlen, target_to_host (hostdir, sizeof hostdir, dir.beg));
 
       /* Don't bother processing the rest of the format string.  */
       res->warned = true;
@@ -4620,8 +4619,7 @@ handle_printf_call (gimple_stmt_iterator *gsi, pointer_query &ptr_qry)
 	     is not constant.  */
 	  location_t loc = gimple_location (info.callstmt);
 	  warning_at (EXPR_LOC_OR_LOC (dstptr, loc),
-		      info.warnopt (), "%Gnull destination pointer",
-		      info.callstmt);
+		      info.warnopt (), "null destination pointer");
 	  return false;
 	}
 
@@ -4650,8 +4648,7 @@ handle_printf_call (gimple_stmt_iterator *gsi, pointer_query &ptr_qry)
     {
       location_t loc = gimple_location (info.callstmt);
       warning_at (EXPR_LOC_OR_LOC (info.format, loc),
-		  info.warnopt (), "%Gnull format string",
-		  info.callstmt);
+		  info.warnopt (), "null format string");
       return false;
     }
 
diff --git a/gcc/gimple-ssa-warn-alloca.c b/gcc/gimple-ssa-warn-alloca.c
index 72480f1d8cb..4fc7125d378 100644
--- a/gcc/gimple-ssa-warn-alloca.c
+++ b/gcc/gimple-ssa-warn-alloca.c
@@ -283,7 +283,7 @@ pass_walloca::execute (function *fun)
 	    }
 	  else if (warn_alloca)
 	    {
-	      warning_at (loc, OPT_Walloca, "%Guse of %<alloca%>", stmt);
+	      warning_at (loc, OPT_Walloca, "use of %<alloca%>");
 	      continue;
 	    }
 	  else if (warn_alloca_limit < 0)
@@ -322,11 +322,10 @@ pass_walloca::execute (function *fun)
 		auto_diagnostic_group d;
 		if (warning_at (loc, wcode,
 				(is_vla
-				 ? G_("%Gargument to variable-length "
+				 ? G_("argument to variable-length "
 				      "array may be too large")
-				 : G_("%Gargument to %<alloca%> may be too "
-				      "large")),
-				stmt)
+				 : G_("argument to %<alloca%> may be too "
+				      "large")))
 		    && t.limit != 0)
 		  {
 		    print_decu (t.limit, buff);
@@ -342,10 +341,9 @@ pass_walloca::execute (function *fun)
 		auto_diagnostic_group d;
 		if (warning_at (loc, wcode,
 				(is_vla
-				 ? G_("%Gargument to variable-length"
+				 ? G_("argument to variable-length"
 				      " array is too large")
-				 : G_("%Gargument to %<alloca%> is too large")),
-				stmt)
+				 : G_("argument to %<alloca%> is too large")))
 		    && t.limit != 0)
 		  {
 		    print_decu (t.limit, buff);
@@ -361,22 +359,20 @@ pass_walloca::execute (function *fun)
 
 	      warning_at (loc, wcode,
 			  (is_vla
-			   ? G_("%Gunbounded use of variable-length array")
-			   : G_("%Gunbounded use of %<alloca%>")),
-			  stmt);
+			   ? G_("unbounded use of variable-length array")
+			   : G_("unbounded use of %<alloca%>")));
 	      break;
 	    case ALLOCA_IN_LOOP:
 	      gcc_assert (!is_vla);
 	      warning_at (loc, wcode,
-			  "%Guse of %<alloca%> within a loop", stmt);
+			  "use of %<alloca%> within a loop");
 	      break;
 	    case ALLOCA_ARG_IS_ZERO:
 	      warning_at (loc, wcode,
 			  (is_vla
-			   ? G_("%Gargument to variable-length array "
+			   ? G_("argument to variable-length array "
 				"is zero")
-			   : G_("%Gargument to %<alloca%> is zero")),
-			  stmt);
+			   : G_("argument to %<alloca%> is zero")));
 	      break;
 	    default:
 	      gcc_unreachable ();
diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c
index 02771e4cd60..efb8db98393 100644
--- a/gcc/gimple-ssa-warn-restrict.c
+++ b/gcc/gimple-ssa-warn-restrict.c
@@ -1494,36 +1494,36 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
 	    warning_at (loc, OPT_Wrestrict,
 			sizrange[0] == 1
 			? (ovlsiz[0] == 1
-			   ? G_("%G%qD accessing %wu byte at offsets %s "
+			   ? G_("%qD accessing %wu byte at offsets %s "
 				"and %s overlaps %wu byte at offset %s")
-			   :  G_("%G%qD accessing %wu byte at offsets %s "
+			   :  G_("%qD accessing %wu byte at offsets %s "
 				 "and %s overlaps %wu bytes at offset "
 				 "%s"))
 			: (ovlsiz[0] == 1
-			   ? G_("%G%qD accessing %wu bytes at offsets %s "
+			   ? G_("%qD accessing %wu bytes at offsets %s "
 				"and %s overlaps %wu byte at offset %s")
-			   : G_("%G%qD accessing %wu bytes at offsets %s "
+			   : G_("%qD accessing %wu bytes at offsets %s "
 				"and %s overlaps %wu bytes at offset "
 				"%s")),
-			call, func, sizrange[0],
+			func, sizrange[0],
 			offstr[0], offstr[1], ovlsiz[0], offstr[2]);
 	  else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
 	    warning_n (loc, OPT_Wrestrict, sizrange[0],
-		       "%G%qD accessing %wu byte at offsets %s "
+		       "%qD accessing %wu byte at offsets %s "
 		       "and %s overlaps between %wu and %wu bytes "
 		       "at offset %s",
-		       "%G%qD accessing %wu bytes at offsets %s "
+		       "%qD accessing %wu bytes at offsets %s "
 		       "and %s overlaps between %wu and %wu bytes "
 		       "at offset %s",
-		       call, func, sizrange[0], offstr[0], offstr[1],
+		       func, sizrange[0], offstr[0], offstr[1],
 		       ovlsiz[0], ovlsiz[1], offstr[2]);
 	  else
 	    warning_n (loc, OPT_Wrestrict, sizrange[0],
-		       "%G%qD accessing %wu byte at offsets %s and "
+		       "%qD accessing %wu byte at offsets %s and "
 		       "%s overlaps %wu or more bytes at offset %s",
-		       "%G%qD accessing %wu bytes at offsets %s and "
+		       "%qD accessing %wu bytes at offsets %s and "
 		       "%s overlaps %wu or more bytes at offset %s",
-		       call, func, sizrange[0],
+		       func, sizrange[0],
 		       offstr[0], offstr[1], ovlsiz[0], offstr[2]);
 	  return true;
 	}
@@ -1532,28 +1532,28 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
 	{
 	  if (ovlsiz[0] == ovlsiz[1])
 	    warning_n (loc, OPT_Wrestrict, ovlsiz[0],
-		       "%G%qD accessing between %wu and %wu bytes "
+		       "%qD accessing between %wu and %wu bytes "
 		       "at offsets %s and %s overlaps %wu byte at "
 		       "offset %s",
-		       "%G%qD accessing between %wu and %wu bytes "
+		       "%qD accessing between %wu and %wu bytes "
 		       "at offsets %s and %s overlaps %wu bytes "
 		       "at offset %s",
-		       call, func, sizrange[0], sizrange[1],
+		       func, sizrange[0], sizrange[1],
 		       offstr[0], offstr[1], ovlsiz[0], offstr[2]);
 	  else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
 	    warning_at (loc, OPT_Wrestrict,
-			"%G%qD accessing between %wu and %wu bytes at "
+			"%qD accessing between %wu and %wu bytes at "
 			"offsets %s and %s overlaps between %wu and %wu "
 			"bytes at offset %s",
-			call, func, sizrange[0], sizrange[1],
+			func, sizrange[0], sizrange[1],
 			offstr[0], offstr[1], ovlsiz[0], ovlsiz[1],
 			offstr[2]);
 	  else
 	    warning_at (loc, OPT_Wrestrict,
-			"%G%qD accessing between %wu and %wu bytes at "
+			"%qD accessing between %wu and %wu bytes at "
 			"offsets %s and %s overlaps %wu or more bytes "
 			"at offset %s",
-			call, func, sizrange[0], sizrange[1],
+			func, sizrange[0], sizrange[1],
 			offstr[0], offstr[1], ovlsiz[0], offstr[2]);
 	  return true;
 	}
@@ -1563,24 +1563,24 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
 
       if (ovlsiz[0] == ovlsiz[1])
 	warning_n (loc, OPT_Wrestrict, ovlsiz[0],
-		   "%G%qD accessing %wu or more bytes at offsets "
+		   "%qD accessing %wu or more bytes at offsets "
 		   "%s and %s overlaps %wu byte at offset %s",
-		   "%G%qD accessing %wu or more bytes at offsets "
+		   "%qD accessing %wu or more bytes at offsets "
 		   "%s and %s overlaps %wu bytes at offset %s",
-		   call, func, sizrange[0], offstr[0], offstr[1],
+		   func, sizrange[0], offstr[0], offstr[1],
 		   ovlsiz[0], offstr[2]);
       else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
 	warning_at (loc, OPT_Wrestrict,
-		    "%G%qD accessing %wu or more bytes at offsets %s "
+		    "%qD accessing %wu or more bytes at offsets %s "
 		    "and %s overlaps between %wu and %wu bytes "
 		    "at offset %s",
-		    call, func, sizrange[0], offstr[0], offstr[1],
+		    func, sizrange[0], offstr[0], offstr[1],
 		    ovlsiz[0], ovlsiz[1], offstr[2]);
       else
 	warning_at (loc, OPT_Wrestrict,
-		    "%G%qD accessing %wu or more bytes at offsets %s "
+		    "%qD accessing %wu or more bytes at offsets %s "
 		    "and %s overlaps %wu or more bytes at offset %s",
-		    call, func, sizrange[0], offstr[0], offstr[1],
+		    func, sizrange[0], offstr[0], offstr[1],
 		    ovlsiz[0], offstr[2]);
       return true;
     }
@@ -1606,36 +1606,36 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
 	{
 	  if (open_range)
 	    warning_n (loc, OPT_Wrestrict, sizrange[1],
-		       "%G%qD accessing %wu byte may overlap "
+		       "%qD accessing %wu byte may overlap "
 		       "%wu byte",
-		       "%G%qD accessing %wu bytes may overlap "
+		       "%qD accessing %wu bytes may overlap "
 		       "%wu byte",
-		       call, func, sizrange[1], ovlsiz[1]);
+		       func, sizrange[1], ovlsiz[1]);
 	  else
 	    warning_n (loc, OPT_Wrestrict, sizrange[1],
-		       "%G%qD accessing %wu byte at offsets %s "
+		       "%qD accessing %wu byte at offsets %s "
 		       "and %s may overlap %wu byte at offset %s",
-		       "%G%qD accessing %wu bytes at offsets %s "
+		       "%qD accessing %wu bytes at offsets %s "
 		       "and %s may overlap %wu byte at offset %s",
-		       call, func, sizrange[1], offstr[0], offstr[1],
+		       func, sizrange[1], offstr[0], offstr[1],
 		       ovlsiz[1], offstr[2]);
 	  return true;
 	}
 
       if (open_range)
 	warning_n (loc, OPT_Wrestrict, sizrange[1],
-		   "%G%qD accessing %wu byte may overlap "
+		   "%qD accessing %wu byte may overlap "
 		   "up to %wu bytes",
-		   "%G%qD accessing %wu bytes may overlap "
+		   "%qD accessing %wu bytes may overlap "
 		   "up to %wu bytes",
-		   call, func, sizrange[1], ovlsiz[1]);
+		   func, sizrange[1], ovlsiz[1]);
       else
 	warning_n (loc, OPT_Wrestrict, sizrange[1],
-		   "%G%qD accessing %wu byte at offsets %s and "
+		   "%qD accessing %wu byte at offsets %s and "
 		   "%s may overlap up to %wu bytes at offset %s",
-		   "%G%qD accessing %wu bytes at offsets %s and "
+		   "%qD accessing %wu bytes at offsets %s and "
 		   "%s may overlap up to %wu bytes at offset %s",
-		   call, func, sizrange[1], offstr[0], offstr[1],
+		   func, sizrange[1], offstr[0], offstr[1],
 		   ovlsiz[1], offstr[2]);
       return true;
     }
@@ -1644,30 +1644,30 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
     {
       if (open_range)
 	warning_n (loc, OPT_Wrestrict, ovlsiz[1],
-		   "%G%qD accessing between %wu and %wu bytes "
+		   "%qD accessing between %wu and %wu bytes "
 		   "may overlap %wu byte",
-		   "%G%qD accessing between %wu and %wu bytes "
+		   "%qD accessing between %wu and %wu bytes "
 		   "may overlap up to %wu bytes",
-		   call, func, sizrange[0], sizrange[1], ovlsiz[1]);
+		   func, sizrange[0], sizrange[1], ovlsiz[1]);
       else
 	warning_n (loc, OPT_Wrestrict, ovlsiz[1],
-		   "%G%qD accessing between %wu and %wu bytes "
+		   "%qD accessing between %wu and %wu bytes "
 		   "at offsets %s and %s may overlap %wu byte "
 		   "at offset %s",
-		   "%G%qD accessing between %wu and %wu bytes "
+		   "%qD accessing between %wu and %wu bytes "
 		   "at offsets %s and %s may overlap up to %wu "
 		   "bytes at offset %s",
-		   call, func, sizrange[0], sizrange[1],
+		   func, sizrange[0], sizrange[1],
 		   offstr[0], offstr[1], ovlsiz[1], offstr[2]);
       return true;
     }
 
   warning_n (loc, OPT_Wrestrict, ovlsiz[1],
-	     "%G%qD accessing %wu or more bytes at offsets %s "
+	     "%qD accessing %wu or more bytes at offsets %s "
 	     "and %s may overlap %wu byte at offset %s",
-	     "%G%qD accessing %wu or more bytes at offsets %s "
+	     "%qD accessing %wu or more bytes at offsets %s "
 	     "and %s may overlap up to %wu bytes at offset %s",
-	     call, func, sizrange[0], offstr[0], offstr[1],
+	     func, sizrange[0], offstr[0], offstr[1],
 	     ovlsiz[1], offstr[2]);
 
   return true;
@@ -1689,7 +1689,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 			  const builtin_memref &ref, offset_int wroff,
 			  bool do_warn)
 {
-  location_t loc = gimple_or_expr_nonartificial_location (call, ref.ptr);
+  location_t loc = gimple_location (call);
   const offset_int maxobjsize = ref.maxobjsize;
 
   /* Check for excessive size first and regardless of warning options
@@ -1709,15 +1709,15 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	{
 	  if (ref.sizrange[0] == ref.sizrange[1])
 	    warned = warning_at (loc, opt,
-				 "%G%qD specified bound %wu "
+				 "%qD specified bound %wu "
 				 "exceeds maximum object size %wu",
-				 call, func, ref.sizrange[0].to_uhwi (),
+				 func, ref.sizrange[0].to_uhwi (),
 				 maxobjsize.to_uhwi ());
 	  else
 	    warned = warning_at (loc, opt,
-				 "%G%qD specified bound between %wu and %wu "
+				 "%qD specified bound between %wu and %wu "
 				 "exceeds maximum object size %wu",
-				 call, func, ref.sizrange[0].to_uhwi (),
+				 func, ref.sizrange[0].to_uhwi (),
 				 ref.sizrange[1].to_uhwi (),
 				 maxobjsize.to_uhwi ());
 	  return warned ? opt : no_warning;
@@ -1776,9 +1776,9 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	{
 	  auto_diagnostic_group d;
 	  if (warning_at (loc, opt,
-			  "%G%qD pointer overflow between offset %s "
+			  "%qD pointer overflow between offset %s "
 			  "and size %s accessing array %qD with type %qT",
-			  call, func, rangestr[0], rangestr[1], ref.base, type))
+			  func, rangestr[0], rangestr[1], ref.base, type))
 	    {
 	      inform (DECL_SOURCE_LOCATION (ref.base),
 		      "array %qD declared here", ref.base);
@@ -1786,15 +1786,15 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	    }
 	  else
 	    warned = warning_at (loc, opt,
-				 "%G%qD pointer overflow between offset %s "
+				 "%qD pointer overflow between offset %s "
 				 "and size %s",
-				 call, func, rangestr[0], rangestr[1]);
+				 func, rangestr[0], rangestr[1]);
 	}
       else
 	warned = warning_at (loc, opt,
-			     "%G%qD pointer overflow between offset %s "
+			     "%qD pointer overflow between offset %s "
 			     "and size %s",
-			     call, func, rangestr[0], rangestr[1]);
+			     func, rangestr[0], rangestr[1]);
     }
   else if (oobref == ref.base)
     {
@@ -1809,20 +1809,20 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	  if ((ref.basesize < maxobjsize
 	       && warning_at (loc, opt,
 			      form
-			      ? G_("%G%qD forming offset %s is out of "
+			      ? G_("%qD forming offset %s is out of "
 				   "the bounds [0, %wu] of object %qD with "
 				   "type %qT")
-			      : G_("%G%qD offset %s is out of the bounds "
+			      : G_("%qD offset %s is out of the bounds "
 				   "[0, %wu] of object %qD with type %qT"),
-			      call, func, rangestr[0], ref.basesize.to_uhwi (),
+			      func, rangestr[0], ref.basesize.to_uhwi (),
 			      ref.base, TREE_TYPE (ref.base)))
 	      || warning_at (loc, opt,
 			     form
-			     ? G_("%G%qD forming offset %s is out of "
+			     ? G_("%qD forming offset %s is out of "
 				  "the bounds of object %qD with type %qT")
-			     : G_("%G%qD offset %s is out of the bounds "
+			     : G_("%qD offset %s is out of the bounds "
 				  "of object %qD with type %qT"),
-			     call, func, rangestr[0],
+			     func, rangestr[0],
 			     ref.base, TREE_TYPE (ref.base)))
 	    {
 	      inform (DECL_SOURCE_LOCATION (ref.base),
@@ -1833,17 +1833,17 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
       else if (ref.basesize < maxobjsize)
 	warned = warning_at (loc, opt,
 			     form
-			     ? G_("%G%qD forming offset %s is out "
+			     ? G_("%qD forming offset %s is out "
 				  "of the bounds [0, %wu]")
-			     : G_("%G%qD offset %s is out "
+			     : G_("%qD offset %s is out "
 				  "of the bounds [0, %wu]"),
-			     call, func, rangestr[0], ref.basesize.to_uhwi ());
+			     func, rangestr[0], ref.basesize.to_uhwi ());
       else
 	warned = warning_at (loc, opt,
 			     form
-			     ? G_("%G%qD forming offset %s is out of bounds")
-			     : G_("%G%qD offset %s is out of bounds"),
-			     call, func, rangestr[0]);
+			     ? G_("%qD forming offset %s is out of bounds")
+			     : G_("%qD offset %s is out of bounds"),
+			     func, rangestr[0]);
     }
   else if (TREE_CODE (ref.ref) == MEM_REF)
     {
@@ -1854,9 +1854,9 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
       type = TYPE_MAIN_VARIANT (type);
 
       if (warning_at (loc, opt,
-		      "%G%qD offset %s from the object at %qE is out "
+		      "%qD offset %s from the object at %qE is out "
 		      "of the bounds of %qT",
-		      call, func, rangestr[0], ref.base, type))
+		      func, rangestr[0], ref.base, type))
 	{
 	  if (TREE_CODE (ref.ref) == COMPONENT_REF)
 	    refop = TREE_OPERAND (ref.ref, 1);
@@ -1872,10 +1872,10 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
       tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref));
 
       if (warning_at (loc, opt,
-		      "%G%qD offset %s from the object at %qE is out "
+		      "%qD offset %s from the object at %qE is out "
 		      "of the bounds of referenced subobject %qD with "
 		      "type %qT at offset %wi",
-		      call, func, rangestr[0], ref.base,
+		      func, rangestr[0], ref.base,
 		      TREE_OPERAND (ref.ref, 1), type,
 		      ref.refoff.to_shwi ()))
 	{
@@ -2065,7 +2065,7 @@ check_bounds_or_overlap (range_query *query,
 	}
     }
 
-  location_t loc = gimple_or_expr_nonartificial_location (call, dst);
+  location_t loc = gimple_location (call);
   if (operand_equal_p (dst, src, 0))
     {
       /* Issue -Wrestrict unless the pointers are null (those do
@@ -2075,8 +2075,8 @@ check_bounds_or_overlap (range_query *query,
       if (!integer_zerop (dst) && !warning_suppressed_p (call, OPT_Wrestrict))
 	{
 	  warning_at (loc, OPT_Wrestrict,
-		      "%G%qD source argument is the same as destination",
-		      call, func);
+		      "%qD source argument is the same as destination",
+		      func);
 	  suppress_warning (call, OPT_Wrestrict);
 	  return OPT_Wrestrict;
 	}
diff --git a/gcc/testsuite/g++.dg/warn/Wdtor1.s b/gcc/testsuite/g++.dg/warn/Wdtor1.s
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-71.c b/gcc/testsuite/gcc.dg/Warray-bounds-71.c
new file mode 100644
index 00000000000..425bb122909
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-71.c
@@ -0,0 +1,7 @@
+/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic
+   works at any call site in an inlining stack
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+#define IGNORE '1'
+#include "Warray-bounds-71.h"
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-71.h b/gcc/testsuite/gcc.dg/Warray-bounds-71.h
new file mode 100644
index 00000000000..89d1068a266
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-71.h
@@ -0,0 +1,46 @@
+/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic
+   works at any call site in an inlining stack
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+int a[4];
+
+void f1 (int *p, int i)
+{
+#pragma GCC diagnostic push
+#if IGNORE == '1'
+#  pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+  p[i + 1] = 0;
+#pragma GCC diagnostic pop
+}
+
+void f2 (int *p, int i)
+{
+#pragma GCC diagnostic push
+#if IGNORE == '2'
+#  pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+  f1 (p + 1, i + 1);
+#pragma GCC diagnostic pop
+}
+
+void f3 (int *p, int i)
+{
+#pragma GCC diagnostic push
+#if IGNORE == '3'
+#  pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+  f2 (p + 1, i + 1);
+#pragma GCC diagnostic pop
+}
+
+void f4 (void)
+{
+#pragma GCC diagnostic push
+#if IGNORE == '4'
+#  pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+  f3 (a, 1);
+#pragma GCC diagnostic pop
+}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-72.c b/gcc/testsuite/gcc.dg/Warray-bounds-72.c
new file mode 100644
index 00000000000..eb3f664c0c8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-72.c
@@ -0,0 +1,7 @@
+/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic
+   works at any call site in an inlining stack
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+#define IGNORE '2'
+#include "Warray-bounds-71.h"
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-73.c b/gcc/testsuite/gcc.dg/Warray-bounds-73.c
new file mode 100644
index 00000000000..50e20835293
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-73.c
@@ -0,0 +1,7 @@
+/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic
+   works at any call site in an inlining stack
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+#define IGNORE '3'
+#include "Warray-bounds-71.h"
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-74.c b/gcc/testsuite/gcc.dg/Warray-bounds-74.c
new file mode 100644
index 00000000000..c59a876e073
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-74.c
@@ -0,0 +1,7 @@
+/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic
+   works at any call site in an inlining stack
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+#define IGNORE '4'
+#include "Warray-bounds-71.h"
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-75.c b/gcc/testsuite/gcc.dg/Warray-bounds-75.c
new file mode 100644
index 00000000000..306b1768b0e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-75.c
@@ -0,0 +1,12 @@
+/* Sanity test for Warray-bounds-7[1-4].c.  Also verify the expected
+   inlining stack.
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+#include "Warray-bounds-71.h"
+
+// { dg-regexp "In function 'f1'," "In function f1" { target *-*-* } 0 }
+// { dg-regexp "inlined from 'f2' at \[^\\n\\r\]+\[\\n\\r\]" "inlined from f2" { target *-*-* } 0 }
+// { dg-regexp "inlined from 'f3' at \[^\\n\\r\]+\[\\n\\r\]" "inlined from f3" { target *-*-* } 0 }
+// { dg-regexp "inlined from 'f4' at \[^\\n\\r\]+\[\\n\\r\]" "inlined from f4" { target *-*-* } 0 }
+// { dg-message "Warray-bounds-71.h:\\d+:\\d+: warning: array subscript 6 is outside array bounds of 'int\\\[4]'" "warning" { target *-*-* } 0 }
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c
index a7d921248c4..fdef9e6b3ea 100644
--- a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c
@@ -26,7 +26,7 @@ void g2 (struct A *p) { g1 (p); }
 
 #define NOIPA __attribute__ ((noipa))
 
-extern int array[];
+extern int array[];           // { dg-message "declared here" "note on line 29" }
 
 /* Verify the warning is issued even for calls in a system header inlined
    into a function outside the header.  */
@@ -39,7 +39,7 @@ NOIPA void warn_g0 (struct A *p)
   g0 (p);
 }
 
-// { dg-message "inlined from 'warn_g0'" "" { target *-*-* } 0 }
+// { dg-message "inlined from 'warn_g0'" "note on line 42" { target *-*-* } 0 }
 
 
 /* Also verify the warning can be suppressed.  */
@@ -65,8 +65,8 @@ NOIPA void warn_g1 (struct A *p)
   g1 (p);
 }
 
-// { dg-message "inlined from 'g1'" "" { target *-*-* } 0 }
-// { dg-message "inlined from 'warn_g1'" "" { target *-*-* } 0 }
+// { dg-message "inlined from 'g1'" "note on line 68" { target *-*-* } 0 }
+// { dg-message "inlined from 'warn_g1'" "note on line 69" { target *-*-* } 0 }
 
 
 NOIPA void nowarn_g1 (struct A *p)
@@ -90,8 +90,8 @@ NOIPA void warn_g2 (struct A *p)
   g2 (p);
 }
 
-// { dg-message "inlined from 'g2'" "" { target *-*-* } 0 }
-// { dg-message "inlined from 'warn_g2'" "" { target *-*-* } 0 }
+// { dg-message "inlined from 'g2'" "note on line 93" { target *-*-* } 0 }
+// { dg-message "inlined from 'warn_g2'" "note on line 94" { target *-*-* } 0 }
 
 
 NOIPA void nowarn_g2 (struct A *p)
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c
new file mode 100644
index 00000000000..979e1e3d78f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c
@@ -0,0 +1,45 @@
+/* Similar to Wfree-nonheap-object-4.c but without system headers:
+   verify that warnings for the same call site from distinct callers
+   include the correct function names in the inlining stack.
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+struct A
+{
+  void *p;
+};
+
+void f0 (struct A *p)
+{
+  __builtin_free (p->p);      // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+// Expect two instances of the text below:
+// { dg-regexp "In function 'f0'," "f0 prefix" { target *-*-* } 0 }
+// { dg-regexp "In function 'f0'," "f0 prefix" { target *-*-* } 0 }
+
+void f1 (struct A *p) { f0 (p); }
+void f2 (struct A *p) { f1 (p); }
+
+extern int array[];
+// Also expect two instances of the note:
+// { dg-regexp "declared here" "note on line 24" { target *-*-* } .-2 }
+// { dg-regexp "declared here" "note on line 24" { target *-*-* } .-3 }
+
+void foo (struct A *p)
+{
+  p->p = array + 1;
+  f0 (p);
+}
+
+// { dg-message "inlined from 'foo'" "note on line 35" { target *-*-* } 0 }
+
+
+void bar (struct A *p)
+{
+  p->p = array + 2;
+  f1 (p);
+}
+
+// { dg-message "inlined from 'f1'" "note on line 44" { target *-*-* } 0 }
+// { dg-message "inlined from 'bar'" "note on line 45" { target *-*-* } 0 }
diff --git a/gcc/testsuite/gcc.dg/Wobjsize-1.c b/gcc/testsuite/gcc.dg/Wobjsize-1.c
index e80c8add3bb..2bd2f93897b 100644
--- a/gcc/testsuite/gcc.dg/Wobjsize-1.c
+++ b/gcc/testsuite/gcc.dg/Wobjsize-1.c
@@ -4,13 +4,17 @@
 #include "Wobjsize-1.h"
 
 char buf[6];
-/* { dg-warning "writing" "" { target *-*-* } .-1 } */
 
 int main(int argc, char **argv)
 {
-  strcpy (buf,"hello ");
+  strcpy (buf,"hello ");    /* { dg-warning "\\\[-Wstringop-overflow" } */
   return 0;
 }
 
-/* { dg-message "file included" "included" { target *-*-* } 0 } */
-/* { dg-message "inlined from" "inlined" { target *-*-* } 0 } */
+/* { dg-message "file included" "included" { target *-*-* } 0 }
+   { dg-message "inlined from" "inlined" { target *-*-* } 0 }
+
+   The test might emit two warnings, one for the strcpy call and
+   another for the inlined call to __builtin___strcpy_chk() called
+   from strcpy().
+   { dg-prune-output "writing 7 bytes into a region of size 6" } */
diff --git a/gcc/testsuite/gcc.dg/pragma-diag-10.c b/gcc/testsuite/gcc.dg/pragma-diag-10.c
new file mode 100644
index 00000000000..127b299939a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pragma-diag-10.c
@@ -0,0 +1,20 @@
+/* PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective
+   in conjunction with alias attribute
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+void *
+__rawmemchr_ppc (const void *s, int c)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+#pragma GCC diagnostic ignored "-Wstringop-overread"
+  if (c != 0)
+    return __builtin_memchr (s, c, (unsigned long)-1);    // { dg-bogus "specified bound \\d+ exceeds maximum object size" }
+#pragma GCC diagnostic pop
+
+  return (char *)s + __builtin_strlen (s);
+}
+
+extern __typeof (__rawmemchr_ppc) __EI___rawmemchr_ppc
+  __attribute__((alias ("__rawmemchr_ppc")));
diff --git a/gcc/testsuite/gcc.dg/pragma-diag-9.c b/gcc/testsuite/gcc.dg/pragma-diag-9.c
new file mode 100644
index 00000000000..d7eac558128
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pragma-diag-9.c
@@ -0,0 +1,134 @@
+/* Verify that #pragma GCC diagnostic down the inlining stack suppresses
+   a warning that would otherwise be issued for inlined calls higher up
+   the inlining stack.
+   { dg-do compile }
+   { dg-options "-O2 -Wall -Wno-array-bounds" } */
+
+extern void* memset (void*, int, __SIZE_TYPE__);
+
+static void warn0 (int *p)
+{
+  memset (p, __LINE__, 3);    // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+static void warn1 (int *p)
+{
+  warn0 (p + 1);
+}
+
+static void warn2 (int *p)
+{
+  warn1 (p + 1);
+}
+
+int a2[2];                    // { dg-message "at offset 12 into destination object 'a2' of size 8" }
+
+void warn3 (void)
+{
+  warn2 (a2 + 1);
+}
+
+
+static void ignore0 (int *p)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  memset (p, __LINE__, 3);
+#pragma GCC diagnostic pop
+}
+
+static void nowarn1_ignore0 (int *p)
+{
+  ignore0 (p + 1);
+}
+
+static void nowarn2_ignore0 (int *p)
+{
+  nowarn1_ignore0 (p + 1);
+}
+
+int b2[2];
+
+void nowarn3_ignore0 (void)
+{
+  nowarn2_ignore0 (b2 + 1);
+}
+
+
+static void nowarn0_ignore1 (int *p)
+{
+  memset (p, __LINE__, 3);
+}
+
+static void ignore1 (int *p)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  nowarn0_ignore1 (p + 1);
+#pragma GCC diagnostic pop
+}
+
+void nowarn2_ignore1 (int *p)
+{
+  ignore1 (p + 1);
+}
+
+int c2[2];
+
+void nowarn3_ignore1 (void)
+{
+  nowarn2_ignore1 (c2 + 1);
+}
+
+
+static void nowarn0_ignore2 (int *p)
+{
+  memset (p, __LINE__, 3);
+}
+
+static void nowarn1_ignore2 (int *p)
+{
+  nowarn0_ignore2 (p + 1);
+}
+
+static void ignore2 (int *p)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  nowarn1_ignore2 (p + 1);
+#pragma GCC diagnostic pop
+}
+
+int d2[2];
+
+void nowarn3_ignore2 (void)
+{
+  ignore2 (c2 + 1);
+}
+
+
+
+static void nowarn0_ignore3 (int *p)
+{
+  memset (p, __LINE__, 3);
+}
+
+static void nowarn1_ignore3 (int *p)
+{
+  nowarn0_ignore3 (p + 1);
+}
+
+static void nowarn2_ignore3 (int *p)
+{
+  nowarn1_ignore3 (p + 1);
+}
+
+int e2[2];
+
+void ignore3 (void)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  nowarn2_ignore3 (e2 + 1);
+#pragma GCC diagnostic pop
+}
diff --git a/gcc/testsuite/gcc.dg/uninit-suppress_3.c b/gcc/testsuite/gcc.dg/uninit-suppress_3.c
new file mode 100644
index 00000000000..7bbe9edc605
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-suppress_3.c
@@ -0,0 +1,98 @@
+/* PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at declaration
+   site
+   { dg-do compile }
+   { dg-options "-O1 -Wall" } */
+
+struct A
+{
+  int x;
+};
+
+// Verify that suppression works at every inlining level.
+
+static int f0 (int *x)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+
+  return ++*x;
+
+#pragma GCC diagnostic pop
+}
+
+static int f1 (int *p, int n)
+{
+  struct A a;
+  for (int i = 0; i < n; ++i) {
+    if (p[i] > 1) {
+      a = (struct A){p[i]};
+    }
+  }
+	
+  return f0 (&a.x);
+}
+
+int f2 (void)
+{
+  int a[] = { 1, 2, 3, 4 };
+  return f1 (a, 4);
+}
+
+
+static int g0 (int *x)
+{
+  return ++*x;
+}
+
+static int g1 (int *p, int n)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+
+  struct A a;
+  for (int i = 0; i < n; ++i) {
+    if (p[i] > 1) {
+      a = (struct A){p[i]};
+    }
+  }
+	
+  return g0 (&a.x);
+
+#pragma GCC diagnostic pop
+}
+
+int g2 (void)
+{
+  int a[] = { 1, 2, 3, 4, 5 };
+  return g1 (a, 5);
+}
+
+
+static int h0 (int *x)
+{
+  return ++*x;
+}
+
+static int h1 (int *p, int n)
+{
+  struct A a;
+  for (int i = 0; i < n; ++i) {
+    if (p[i] > 1) {
+      a = (struct A){p[i]};
+    }
+  }
+	
+  return h0 (&a.x);
+}
+
+int h2 (void)
+{
+  int a[] = { 1, 2, 3, 4, 5, 6 };
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+
+  return h1 (a, 6);
+
+#pragma GCC diagnostic pop
+}
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index e74bd1f5ec0..c270d039b15 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -4413,12 +4413,8 @@ ipa_tm_scan_irr_block (basic_block bb)
 	     is to wrap it in a __tm_waiver block.  This is not
 	     yet implemented, so we can't check for it.  */
 	  if (is_tm_safe (current_function_decl))
-	    {
-	      tree t = build1 (NOP_EXPR, void_type_node, size_zero_node);
-	      SET_EXPR_LOCATION (t, gimple_location (stmt));
-	      error ("%K%<asm%> not allowed in %<transaction_safe%> function",
-		     t);
-	    }
+	    error_at (gimple_location (stmt),
+		      "%<asm%> not allowed in %<transaction_safe%> function");
 	  return true;
 
 	default:
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 42585412325..9ce6214d7e2 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -3563,7 +3563,7 @@ pass_post_ipa_warn::execute (function *fun)
 	      if (argno == 0)
 		{
 		  if (warning_at (loc, OPT_Wnonnull,
-				  "%G%qs pointer is null", stmt, "this")
+				  "%qs pointer is null", "this")
 		      && fndecl)
 		    inform (DECL_SOURCE_LOCATION (fndecl),
 			    "in a call to non-static member function %qD",
@@ -3572,8 +3572,8 @@ pass_post_ipa_warn::execute (function *fun)
 		}
 
 	      if (!warning_at (loc, OPT_Wnonnull,
-			       "%Gargument %u null where non-null "
-			       "expected", stmt, argno))
+			       "argument %u null where non-null "
+			       "expected", argno))
 		continue;
 
 	      tree fndecl = gimple_call_fndecl (stmt);
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 13ea107da17..94257df1067 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -2022,13 +2022,12 @@ maybe_warn_overflow (gimple *stmt, tree len, pointer_query &ptr_qry,
 
       warned = (writefn
 		? warning_at (loc, OPT_Wstringop_overflow_,
-			      "%G%qD writing one too many bytes into a region "
+			      "%qD writing one too many bytes into a region "
 			      "of a size that depends on %<strlen%>",
-			      stmt, writefn)
+			      writefn)
 		: warning_at (loc, OPT_Wstringop_overflow_,
-			      "%Gwriting one too many bytes into a region "
-			      "of a size that depends on %<strlen%>",
-			      stmt));
+			      "writing one too many bytes into a region "
+			      "of a size that depends on %<strlen%>"));
     }
   else if (lenrng[0] == lenrng[1])
     {
@@ -2036,65 +2035,65 @@ maybe_warn_overflow (gimple *stmt, tree len, pointer_query &ptr_qry,
 	warned = (writefn
 		  ? warning_n (loc, OPT_Wstringop_overflow_,
 			       lenrng[0].to_uhwi (),
-			       "%G%qD writing %wu byte into a region "
+			       "%qD writing %wu byte into a region "
 			       "of size %wu",
-			       "%G%qD writing %wu bytes into a region "
+			       "%qD writing %wu bytes into a region "
 			       "of size %wu",
-			       stmt, writefn, lenrng[0].to_uhwi (),
+			       writefn, lenrng[0].to_uhwi (),
 			       spcrng[0].to_uhwi ())
 		  : warning_n (loc, OPT_Wstringop_overflow_,
 			       lenrng[0].to_uhwi (),
-			       "%Gwriting %wu byte into a region "
+			       "writing %wu byte into a region "
 			       "of size %wu",
-			       "%Gwriting %wu bytes into a region "
+			       "writing %wu bytes into a region "
 			       "of size %wu",
-			       stmt, lenrng[0].to_uhwi (),
+			       lenrng[0].to_uhwi (),
 			       spcrng[0].to_uhwi ()));
       else
 	warned = (writefn
 		  ? warning_n (loc, OPT_Wstringop_overflow_,
 			       lenrng[0].to_uhwi (),
-			       "%G%qD writing %wu byte into a region "
+			       "%qD writing %wu byte into a region "
 			       "of size between %wu and %wu",
-			       "%G%qD writing %wu bytes into a region "
+			       "%qD writing %wu bytes into a region "
 			       "of size between %wu and %wu",
-			       stmt, writefn, lenrng[0].to_uhwi (),
+			       writefn, lenrng[0].to_uhwi (),
 			       spcrng[0].to_uhwi (), spcrng[1].to_uhwi ())
 		  : warning_n (loc, OPT_Wstringop_overflow_,
 			       lenrng[0].to_uhwi (),
-			       "%Gwriting %wu byte into a region "
+			       "writing %wu byte into a region "
 			       "of size between %wu and %wu",
-			       "%Gwriting %wu bytes into a region "
+			       "writing %wu bytes into a region "
 			       "of size between %wu and %wu",
-			       stmt, lenrng[0].to_uhwi (),
+			       lenrng[0].to_uhwi (),
 			       spcrng[0].to_uhwi (), spcrng[1].to_uhwi ()));
     }
   else if (spcrng[0] == spcrng[1])
     warned = (writefn
 	      ? warning_at (loc, OPT_Wstringop_overflow_,
-			    "%G%qD writing between %wu and %wu bytes "
+			    "%qD writing between %wu and %wu bytes "
 			    "into a region of size %wu",
-			    stmt, writefn, lenrng[0].to_uhwi (),
+			    writefn, lenrng[0].to_uhwi (),
 			    lenrng[1].to_uhwi (),
 			    spcrng[0].to_uhwi ())
 	      : warning_at (loc, OPT_Wstringop_overflow_,
-			    "%Gwriting between %wu and %wu bytes "
+			    "writing between %wu and %wu bytes "
 			    "into a region of size %wu",
-			    stmt, lenrng[0].to_uhwi (),
+			    lenrng[0].to_uhwi (),
 			    lenrng[1].to_uhwi (),
 			    spcrng[0].to_uhwi ()));
   else
     warned = (writefn
 	      ? warning_at (loc, OPT_Wstringop_overflow_,
-			    "%G%qD writing between %wu and %wu bytes "
+			    "%qD writing between %wu and %wu bytes "
 			    "into a region of size between %wu and %wu",
-			    stmt, writefn, lenrng[0].to_uhwi (),
+			    writefn, lenrng[0].to_uhwi (),
 			    lenrng[1].to_uhwi (),
 			    spcrng[0].to_uhwi (), spcrng[1].to_uhwi ())
 	      : warning_at (loc, OPT_Wstringop_overflow_,
-			    "%Gwriting between %wu and %wu bytes "
+			    "writing between %wu and %wu bytes "
 			    "into a region of size between %wu and %wu",
-			    stmt, lenrng[0].to_uhwi (),
+			    lenrng[0].to_uhwi (),
 			    lenrng[1].to_uhwi (),
 			    spcrng[0].to_uhwi (), spcrng[1].to_uhwi ()));
 
@@ -2985,13 +2984,13 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
       if (lenrange[0] == cntrange[1] && cntrange[0] == cntrange[1])
 	return warning_n (callloc, OPT_Wstringop_truncation,
 			  cntrange[0].to_uhwi (),
-			  "%G%qD output truncated before terminating "
+			  "%qD output truncated before terminating "
 			  "nul copying %E byte from a string of the "
 			  "same length",
-			  "%G%qD output truncated before terminating nul "
+			  "%qD output truncated before terminating nul "
 			  "copying %E bytes from a string of the same "
 			  "length",
-			  stmt, func, cnt);
+			  func, cnt);
       else if (!cat_dstlen_bounded)
 	{
 	  if (wi::geu_p (lenrange[0], cntrange[1]))
@@ -3001,16 +3000,16 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
 	      if (cntrange[0] == cntrange[1])
 		return warning_n (callloc, OPT_Wstringop_truncation,
 				  cntrange[0].to_uhwi (),
-				  "%G%qD output truncated copying %E byte "
+				  "%qD output truncated copying %E byte "
 				  "from a string of length %wu",
-				  "%G%qD output truncated copying %E bytes "
+				  "%qD output truncated copying %E bytes "
 				  "from a string of length %wu",
-				  stmt, func, cnt, lenrange[0].to_uhwi ());
+				  func, cnt, lenrange[0].to_uhwi ());
 
 	      return warning_at (callloc, OPT_Wstringop_truncation,
-				 "%G%qD output truncated copying between %wu "
+				 "%qD output truncated copying between %wu "
 				 "and %wu bytes from a string of length %wu",
-				 stmt, func, cntrange[0].to_uhwi (),
+				 func, cntrange[0].to_uhwi (),
 				 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
 	    }
 	  else if (wi::geu_p (lenrange[1], cntrange[1]))
@@ -3020,16 +3019,16 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
 	      if (cntrange[0] == cntrange[1])
 		return warning_n (callloc, OPT_Wstringop_truncation,
 				  cntrange[0].to_uhwi (),
-				  "%G%qD output may be truncated copying %E "
+				  "%qD output may be truncated copying %E "
 				  "byte from a string of length %wu",
-				  "%G%qD output may be truncated copying %E "
+				  "%qD output may be truncated copying %E "
 				  "bytes from a string of length %wu",
-				  stmt, func, cnt, lenrange[1].to_uhwi ());
+				  func, cnt, lenrange[1].to_uhwi ());
 
 	      return warning_at (callloc, OPT_Wstringop_truncation,
-				 "%G%qD output may be truncated copying between "
+				 "%qD output may be truncated copying between "
 				 "%wu and %wu bytes from a string of length %wu",
-				 stmt, func, cntrange[0].to_uhwi (),
+				 func, cntrange[0].to_uhwi (),
 				 cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
 	    }
 	}
@@ -3043,9 +3042,9 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
 	     the lower bound of the specified count but shorter than the
 	     upper bound the copy may (but need not) be truncated.  */
 	  return warning_at (callloc, OPT_Wstringop_truncation,
-			     "%G%qD output may be truncated copying between "
+			     "%qD output may be truncated copying between "
 			     "%wu and %wu bytes from a string of length %wu",
-			     stmt, func, cntrange[0].to_uhwi (),
+			     func, cntrange[0].to_uhwi (),
 			     cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
 	}
     }
@@ -3072,8 +3071,8 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
 
       if (cntrange[0] == cntrange[1])
 	return warning_at (callloc, OPT_Wstringop_truncation,
-			   "%G%qD specified bound %E equals destination size",
-			   stmt, func, cnt);
+			   "%qD specified bound %E equals destination size",
+			   func, cnt);
     }
 
   return false;
@@ -3197,9 +3196,9 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
       && sisrc == silen
       && is_strlen_related_p (src, len)
       && warning_at (callloc, OPT_Wstringop_truncation,
-		     "%G%qD output truncated before terminating nul "
+		     "%qD output truncated before terminating nul "
 		     "copying as many bytes from a string as its length",
-		     stmt, func))
+		     func))
     warned = true;
   else if ((append_p || !dstsize || len == dstlenp1)
 	   && silen && is_strlen_related_p (src, silen->ptr))
@@ -3210,9 +3209,9 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
       opt_code opt = (append_p || dstsize
 		      ? OPT_Wstringop_overflow_ : OPT_Wstringop_truncation);
       warned = warning_at (callloc, opt,
-			   "%G%qD specified bound depends on the length "
+			   "%qD specified bound depends on the length "
 			   "of the source argument",
-			   stmt, func);
+			   func);
     }
   if (warned)
     {
@@ -4141,24 +4140,24 @@ maybe_warn_pointless_strcmp (gimple *stmt, HOST_WIDE_INT bound,
   if (siz <= minlen && bound == -1)
     warned = warning_at (stmt_loc, OPT_Wstring_compare,
 			 (at_least
-			  ? G_("%G%qD of a string of length %wu or more and "
+			  ? G_("%qD of a string of length %wu or more and "
 			       "an array of size %wu evaluates to nonzero")
-			  : G_("%G%qD of a string of length %wu and an array "
+			  : G_("%qD of a string of length %wu and an array "
 			       "of size %wu evaluates to nonzero")),
-			 stmt, callee, minlen, siz);
+			 callee, minlen, siz);
   else if (!at_least && siz <= HOST_WIDE_INT_MAX)
     {
       if (len[0] != HOST_WIDE_INT_MAX && len[1] != HOST_WIDE_INT_MAX)
 	warned = warning_at (stmt_loc, OPT_Wstring_compare,
-			     "%G%qD of strings of length %wu and %wu "
+			     "%qD of strings of length %wu and %wu "
 			     "and bound of %wu evaluates to nonzero",
-			     stmt, callee, len[0], len[1], bound);
+			     callee, len[0], len[1], bound);
       else
 	warned = warning_at (stmt_loc, OPT_Wstring_compare,
-			     "%G%qD of a string of length %wu, an array "
+			     "%qD of a string of length %wu, an array "
 			     "of size %wu and bound of %wu evaluates to "
 			     "nonzero",
-			     stmt, callee, minlen, siz, bound);
+			     callee, minlen, siz, bound);
     }
 
   if (!warned)
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index 99442d7f975..24ac031a693 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -444,7 +444,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
   if (wlims.always_executed)
     {
       if (warning_at (location, OPT_Wuninitialized,
-		      "%G%qE is used uninitialized", stmt, rhs))
+		      "%qE is used uninitialized", rhs))
 	{
 	  /* ???  This is only effective for decls as in
 	     gcc.dg/uninit-B-O0.c.  Avoid doing this for maybe-uninit
@@ -457,7 +457,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
     }
   else if (wlims.wmaybe_uninit)
     warned = warning_at (location, OPT_Wmaybe_uninitialized,
-			 "%G%qE may be used uninitialized", stmt, rhs);
+			 "%qE may be used uninitialized", rhs);
 
   return warned ? base : NULL_TREE;
 }

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 3/4] remove %K from error() calls in the aarch64/arm back ends (PR 98512)
  2021-06-11 14:46           ` Martin Sebor
@ 2021-06-30 19:56             ` Martin Sebor
  2021-07-01  8:01               ` Christophe LYON
  0 siblings, 1 reply; 44+ messages in thread
From: Martin Sebor @ 2021-06-30 19:56 UTC (permalink / raw)
  To: Martin Sebor via Gcc-patches, richard.sandiford, Christophe Lyon

[-- Attachment #1: Type: text/plain, Size: 1397 bytes --]

On 6/11/21 8:46 AM, Martin Sebor wrote:
> On 6/11/21 3:58 AM, Richard Sandiford wrote:
>> Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
>>> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
>>> index 7b37e1b602c..7cdc824730c 100644
>>> --- a/gcc/config/arm/arm.c
>>> +++ b/gcc/config/arm/arm.c
>>> @@ -13242,13 +13242,8 @@ bounds_check (rtx operand, HOST_WIDE_INT 
>>> low, HOST_WIDE_INT high,
>>>     lane = INTVAL (operand);
>>>     if (lane < low || lane >= high)
>>> -    {
>>> -      if (exp)
>>> -    error ("%K%s %wd out of range %wd - %wd",
>>> -           exp, desc, lane, low, high - 1);
>>> -      else
>>> -    error ("%s %wd out of range %wd - %wd", desc, lane, low, high - 1);
>>> -    }
>>> +    error_at (EXPR_LOCATION (exp),
>>> +          "%s %wd out of range %wd - %wd", desc, lane, low, high - 1);
>>>   }
>>>   /* Bounds-check lanes.  */
>>
>> This part doesn't look safe: “exp” is null when called from 
>> arm_const_bounds.
> 
> Doh!  Yes, will fix, thanks.

Attached is an updated patch with the test above restored.

Christophe, if you could apply it on top of patches 1 and 2 and run
the aarch64/arm tests that would be great!

Patch 1:
https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573859.html
Patch 2:
https://gcc.gnu.org/pipermail/gcc-patches/2021-June/574088.html

Thanks
Martin

[-- Attachment #2: gcc-98512-3.diff --]
[-- Type: text/x-patch, Size: 6239 bytes --]

Improve warning suppression for inlined functions.

gcc/ChangeLog:

	* config/aarch64/aarch64-builtins.c (aarch64_simd_expand_builtin):
	Remove %K and use error_at.
	(aarch64_expand_fcmla_builtin): Same.
	(aarch64_expand_builtin_tme): Same.
	(aarch64_expand_builtin_memtag): Same.
	* config/arm/arm-builtins.c (arm_expand_acle_builtin): Same.
	(arm_expand_builtin): Same.
	* config/arm/arm.c (bounds_check): Same.

diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 3cab3ec992c..9ed4b72d005 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -1598,8 +1598,9 @@ constant_arg:
 	      if (!(*insn_data[icode].operand[opc].predicate)
 		  (op[opc], mode))
 	      {
-		error ("%Kargument %d must be a constant immediate",
-		       exp, opc + 1 - have_retval);
+		error_at (EXPR_LOCATION (exp),
+			  "argument %d must be a constant immediate",
+			  opc + 1 - have_retval);
 		return const0_rtx;
 	      }
 	      break;
@@ -1669,10 +1670,13 @@ aarch64_simd_expand_builtin (int fcode, tree exp, rtx target)
 				       / UINTVAL (elementsize),
 				      exp);
           else
-	    error ("%Klane index must be a constant immediate", exp);
+	    error_at (EXPR_LOCATION (exp),
+		      "lane index must be a constant immediate");
 	}
       else
-	error ("%Ktotal size and element size must be a non-zero constant immediate", exp);
+	error_at (EXPR_LOCATION (exp),
+		  "total size and element size must be a non-zero "
+		  "constant immediate");
       /* Don't generate any RTL.  */
       return const0_rtx;
     }
@@ -1828,7 +1832,8 @@ aarch64_expand_fcmla_builtin (tree exp, rtx target, int fcode)
   /* Validate that the lane index is a constant.  */
   if (!CONST_INT_P (lane_idx))
     {
-      error ("%Kargument %d must be a constant immediate", exp, 4);
+      error_at (EXPR_LOCATION (exp),
+		"argument %d must be a constant immediate", 4);
       return const0_rtx;
     }
 
@@ -1917,7 +1922,8 @@ aarch64_expand_builtin_tme (int fcode, tree exp, rtx target)
 	  emit_insn (GEN_FCN (CODE_FOR_tcancel) (op0));
 	else
 	  {
-	    error ("%Kargument must be a 16-bit constant immediate", exp);
+	    error_at (EXPR_LOCATION (exp),
+		      "argument must be a 16-bit constant immediate");
 	    return const0_rtx;
 	  }
       }
@@ -2006,8 +2012,9 @@ aarch64_expand_builtin_memtag (int fcode, tree exp, rtx target)
 		  pat = GEN_FCN (icode) (target, op0, const0_rtx, op1);
 		  break;
 		}
-	      error ("%Kargument %d must be a constant immediate "
-		     "in range [0,15]", exp, 2);
+	      error_at (EXPR_LOCATION (exp),
+			"argument %d must be a constant immediate "
+			"in range [0,15]", 2);
 	      return const0_rtx;
 	    }
 	  else
diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c
index fa0fb0b16ab..3a9ff8f26b8 100644
--- a/gcc/config/arm/arm-builtins.c
+++ b/gcc/config/arm/arm-builtins.c
@@ -3092,26 +3092,30 @@ constant_arg:
 			  unsigned int cp_bit = (CONST_INT_P (op[argc])
 						 ? UINTVAL (op[argc]) : -1);
 			  if (IN_RANGE (cp_bit, 0, ARM_CDE_CONST_COPROC))
-			    error ("%Kcoprocessor %d is not enabled "
-				   "with +cdecp%d", exp, cp_bit, cp_bit);
+			    error_at (EXPR_LOCATION (exp),
+				      "coprocessor %d is not enabled "
+				      "with +cdecp%d", cp_bit, cp_bit);
 			  else
-			    error ("%Kcoproc must be a constant immediate in "
-				   "range [0-%d] enabled with +cdecp<N>", exp,
-				   ARM_CDE_CONST_COPROC);
+			    error_at (EXPR_LOCATION (exp),
+				      "coproc must be a constant immediate in "
+				      "range [0-%d] enabled with +cdecp<N>",
+				      ARM_CDE_CONST_COPROC);
 			}
 		      else
 			/* Here we mention the builtin name to follow the same
 			   format that the C/C++ frontends use for referencing
 			   a given argument index.  */
-			error ("%Kargument %d to %qE must be a constant immediate "
-			       "in range [0-%d]", exp, argc + 1,
+			error_at (EXPR_LOCATION (exp),
+				  "argument %d to %qE must be a constant "
+				  "immediate in range [0-%d]", argc + 1,
 			       arm_builtin_decls[fcode],
 			       cde_builtin_data[fcode -
 			       ARM_BUILTIN_CDE_PATTERN_START].imm_max);
 		    }
 		  else
-		    error ("%Kargument %d must be a constant immediate",
-			   exp, argc + 1);
+		    error_at (EXPR_LOCATION (exp),
+			      "argument %d must be a constant immediate",
+			      argc + 1);
 		  /* We have failed to expand the pattern, and are safely
 		     in to invalid code.  But the mid-end will still try to
 		     build an assignment for this node while it expands,
@@ -3328,11 +3332,13 @@ arm_expand_acle_builtin (int fcode, tree exp, rtx target)
       if (CONST_INT_P (sat_imm))
 	{
 	  if (!IN_RANGE (sat_imm, min_sat, max_sat))
-	    error ("%Ksaturation bit range must be in the range [%wd, %wd]",
-		   exp, UINTVAL (min_sat), UINTVAL (max_sat));
+	    error_at (EXPR_LOCATION (exp),
+		      "saturation bit range must be in the range [%wd, %wd]",
+		      UINTVAL (min_sat), UINTVAL (max_sat));
 	}
       else
-	error ("%Ksaturation bit range must be a constant immediate", exp);
+	error_at (EXPR_LOCATION (exp),
+		  "saturation bit range must be a constant immediate");
       /* Don't generate any RTL.  */
       return const0_rtx;
     }
@@ -3455,7 +3461,8 @@ arm_expand_builtin (tree exp,
       if (CONST_INT_P (lane_idx))
 	neon_lane_bounds (lane_idx, 0, TREE_INT_CST_LOW (nlanes), exp);
       else
-	error ("%Klane index must be a constant immediate", exp);
+	error_at (EXPR_LOCATION (exp),
+		  "lane index must be a constant immediate");
       /* Don't generate any RTL.  */
       return const0_rtx;
     }
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 7b37e1b602c..de37c903450 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -13244,8 +13244,8 @@ bounds_check (rtx operand, HOST_WIDE_INT low, HOST_WIDE_INT high,
   if (lane < low || lane >= high)
     {
       if (exp)
-	error ("%K%s %wd out of range %wd - %wd",
-	       exp, desc, lane, low, high - 1);
+	error_at (EXPR_LOCATION (exp),
+		  "%s %wd out of range %wd - %wd", desc, lane, low, high - 1);
       else
 	error ("%s %wd out of range %wd - %wd", desc, lane, low, high - 1);
     }

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 1/4] introduce diagnostic infrastructure changes (PR 98512)
  2021-06-15 23:00           ` Martin Sebor
  2021-06-28 18:10             ` [PING][PATCH " Martin Sebor
@ 2021-06-30 22:55             ` David Malcolm
  2021-07-01 19:43               ` Martin Sebor
  1 sibling, 1 reply; 44+ messages in thread
From: David Malcolm @ 2021-06-30 22:55 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches

On Tue, 2021-06-15 at 17:00 -0600, Martin Sebor wrote:
> On 6/11/21 11:04 AM, David Malcolm wrote:
> > On Thu, 2021-06-10 at 17:26 -0600, Martin Sebor wrote:
> > > This diff introduces the diagnostic infrastructure changes to
> > > support
> > > controlling warnings at any call site in the inlining stack and
> > > printing
> > > the inlining context without the %K and %G directives.
> > 
> > Thanks for working on this, looks very promising.
> > 
> > > Improve warning suppression for inlined functions.
> > > 
> > > Resolves:
> > > PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at
> > > declaration site
> > > PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective in
> > > conjunction with alias attribute
> > 
> > Am I right in thinking that you add test coverage for both of these
> > in
> > patch 2 of the kit?
> 
> Yes, the tests depend on the changes in patch 2 (some existing tests
> fail with just patch 1 applied because the initial location passed
> to warning_t() is different than with it).
> 
> 

[...]

> > 
> 
> 
> Yep, thanks.  Please see the attached revision.
> 
> Martin

Various nits inline below:

> diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
> index d58586f2526..3a22d4d26a6 100644
> --- a/gcc/diagnostic.c
> +++ b/gcc/diagnostic.c
> @@ -991,51 +991,93 @@ print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
>    pp_set_prefix (pp, saved_prefix);
>  }
>  
> -/* Update the diag_class of DIAGNOSTIC based on its location
> -   relative to any
> +/* Update the inlininig context in CONTEXT for a DIAGNOSTIC.  */
                 ^^^^^^^^^^^^^^^^^

It's inlining_info now, so please update this comment.

> +
> +static void
> +update_inlining_context (diagnostic_context *context,
> +			 diagnostic_info *diagnostic)

...and please rename to "get_any_inlining_info".

> +{
> +  auto &ilocs = diagnostic->m_iinfo.m_ilocs;
> +
> +  if (context->set_locations_cb)
> +    {
> +      /* Retrieve the locations into which the expression about to be
> +	 diagnosed has been inlined, including those of all the callers
> +	 all the way down the inlining stack.  */
> +      context->set_locations_cb (context, diagnostic);
> +      location_t loc = diagnostic->m_iinfo.m_ilocs.last ();


> +      if (diagnostic->m_iinfo.m_ao && loc != UNKNOWN_LOCATION)
> +	diagnostic->message.set_location (0, loc, SHOW_RANGE_WITH_CARET);

What is the purpose of the above two lines of code?
(I believe it's to replace the %G/%K stuff, right?)
Please can you add a suitable comment.


> +    }
> +  else
> +    {
> +      /* When there's no callback use just the one location provided
> +	 by the caller of the diagnostic function.  */
> +      location_t loc = diagnostic_location (diagnostic);
> +      ilocs.safe_push (loc);
> +      diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
> +    }
> +}
> +
> +/* Update the kind of DIAGNOSTIC based on its location(s), including
> +   any of those in its inlining context, relative to any
                                   ^^^^^^^

"stack" rather than "context" here; I think we're overusing the word "context".

>       #pragma GCC diagnostic
>     directives recorded within CONTEXT.
>  
> -   Return the new diag_class of DIAGNOSTIC if it was updated, or
> -   DK_UNSPECIFIED otherwise.  */
> +   Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
> +   otherwise.  */
>  
>  static diagnostic_t
>  update_effective_level_from_pragmas (diagnostic_context *context,
>  				     diagnostic_info *diagnostic)
>  {
> -  diagnostic_t diag_class = DK_UNSPECIFIED;
> -
> -  if (context->n_classification_history > 0)
> +  if (diagnostic->m_iinfo.m_allsyslocs && !context->dc_warn_system_headers)
>      {
> -      location_t location = diagnostic_location (diagnostic);
> +      /* Ignore the diagnostic if all the inlined locations are
> +	 in system headers and -Wno-system-headers is in effect.  */
> +      diagnostic->kind = DK_IGNORED;
> +      return DK_IGNORED;
> +    }
>  
> +  if (context->n_classification_history <= 0)
> +    return DK_UNSPECIFIED;
> +
> +  /* Iterate over the locations, checking the diagnostic disposition
> +     for the diagnostic at each.  If it's explicitly set as opposed
> +     to unspecified, update the disposition for this instance of
> +     the diagnostic and return it.  */
> +  for (location_t loc: diagnostic->m_iinfo.m_ilocs)
> +    {
>        /* FIXME: Stupid search.  Optimize later. */
>        for (int i = context->n_classification_history - 1; i >= 0; i --)
>  	{
> -	  if (linemap_location_before_p
> -	      (line_table,
> -	       context->classification_history[i].location,
> -	       location))
> +	  const diagnostic_classification_change_t &hist
> +	    = context->classification_history[i];
> +
> +	  location_t pragloc = hist.location;
> +	  if (!linemap_location_before_p (line_table, pragloc, loc))
> +	    continue;
> +
> +	  if (hist.kind == (int) DK_POP)
>  	    {
> -	      if (context->classification_history[i].kind == (int) DK_POP)
> -		{
> -		  i = context->classification_history[i].option;
> -		  continue;
> -		}
> -	      int option = context->classification_history[i].option;
> -	      /* The option 0 is for all the diagnostics.  */
> -	      if (option == 0 || option == diagnostic->option_index)
> -		{
> -		  diag_class = context->classification_history[i].kind;
> -		  if (diag_class != DK_UNSPECIFIED)
> -		    diagnostic->kind = diag_class;
> -		  break;
> -		}
> +	      /* Move on to the next region.  */
> +	      i = hist.option;
> +	      continue;
> +	    }
> +
> +	  int option = hist.option;
> +	  /* The option 0 is for all the diagnostics.  */
> +	  if (option == 0 || option == diagnostic->option_index)
> +	    {
> +	      diagnostic_t kind = hist.kind;
> +	      if (kind != DK_UNSPECIFIED)
> +		diagnostic->kind = kind;
> +	      return kind;
>  	    }
>  	}
>      }
>  
> -  return diag_class;
> +  return DK_UNSPECIFIED;
>  }
>  
>  /* Generate a URL string describing CWE.  The caller is responsible for
> @@ -1129,6 +1171,9 @@ static bool
>  diagnostic_enabled (diagnostic_context *context,
>  		    diagnostic_info *diagnostic)
>  {
> +  /* Update the inlining context for this diagnostic.  */
> +  update_inlining_context (context, diagnostic);

Please rename as described above.

[...]

Dave


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PING][PATCH 2/4] remove %G and %K from calls in front end and middle end (PR 98512)
  2021-06-30 19:45           ` Martin Sebor
@ 2021-06-30 23:35             ` David Malcolm
  2021-07-01 20:14               ` Martin Sebor
  0 siblings, 1 reply; 44+ messages in thread
From: David Malcolm @ 2021-06-30 23:35 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches; +Cc: Jeff Law, Aldy Hernandez

On Wed, 2021-06-30 at 13:45 -0600, Martin Sebor wrote:
> On 6/30/21 9:39 AM, Martin Sebor wrote:
> > Ping.  Attached is the same patch rebased on top the latest trunk.
> 
> Please see the attached patch instead.  The previous one had typo
> in it.
> 
> > 
> > As discussed in the review of Aldy's recent changes to the backwards
> > threader, he has run into the same bug the patch fixes.  Getting this
> > patch set reviewed and approved would be helpful in keeping him from
> > having to work around the bug.
> > 
> > https://gcc.gnu.org/pipermail/gcc/2021-June/236608.html
> > 
> > On 6/10/21 5:27 PM, Martin Sebor wrote:
> > > This diff removes the uses of %G and %K from all warning_at() calls
> > > throughout GCC front end and middle end.  The inlining context is
> > > included in diagnostic output whenever it's present.
> > 
> 

Thanks for writing the patch.

I went through the full patch, though my eyes may have glazed over in
places at all of the %G and %K removals.  I *think* you got them mostly
correct, apart from the following possible issues and nits...

> diff --git a/gcc/expr.c b/gcc/expr.c
> index 025033c9ecf..b9fe1cf91d7 100644
> --- a/gcc/expr.c
> +++ b/gcc/expr.c

[...]

> @@ -11425,10 +11425,10 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
>  					 DECL_ATTRIBUTES (fndecl))) != NULL)
>  	  {
>  	    const char *ident = lang_hooks.decl_printable_name (fndecl, 1);
> -	    warning_at (tree_nonartificial_location (exp),
> +	    warning_at (EXPR_LOCATION (exp),

Are we preserving the existing behavior for
__attribute__((__artificial__)) here?
Is this behavior handled somewhere else in the patch kit?

>  			OPT_Wattribute_warning,
> -			"%Kcall to %qs declared with attribute warning: %s",
> -			exp, identifier_to_locale (ident),
> +			"call to %qs declared with attribute warning: %s",
> +			identifier_to_locale (ident),
>  			TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
>  	  }
>  

[...]

> diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c
> index 02771e4cd60..efb8db98393 100644
> --- a/gcc/gimple-ssa-warn-restrict.c
> +++ b/gcc/gimple-ssa-warn-restrict.c

[...]

> @@ -1689,7 +1689,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
>  			  const builtin_memref &ref, offset_int wroff,
>  			  bool do_warn)
>  {
> -  location_t loc = gimple_or_expr_nonartificial_location (call, ref.ptr);
> +  location_t loc = gimple_location (call);

Likewise here.

> @@ -2065,7 +2065,7 @@ check_bounds_or_overlap (range_query *query,
>  	}
>      }
>  
> -  location_t loc = gimple_or_expr_nonartificial_location (call, dst);
> +  location_t loc = gimple_location (call);

Likewise here.

[...]

> diff --git a/gcc/testsuite/g++.dg/warn/Wdtor1.s b/gcc/testsuite/g++.dg/warn/Wdtor1.s
> new file mode 100644
> index 00000000000..e69de29bb2d

Is this an empty .s file?  Was this a misfire with "git add"?

[...]

> diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c
> index a7d921248c4..fdef9e6b3ea 100644
> --- a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c
> +++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c
> @@ -26,7 +26,7 @@ void g2 (struct A *p) { g1 (p); }
>  
>  #define NOIPA __attribute__ ((noipa))
>  
> -extern int array[];
> +extern int array[];           // { dg-message "declared here" "note on line 29" }
>  
>  /* Verify the warning is issued even for calls in a system header inlined
>     into a function outside the header.  */
> @@ -39,7 +39,7 @@ NOIPA void warn_g0 (struct A *p)
>    g0 (p);
>  }
>  
> -// { dg-message "inlined from 'warn_g0'" "" { target *-*-* } 0 }
> +// { dg-message "inlined from 'warn_g0'" "note on line 42" { target *-*-* } 0 }
>  
>  
>  /* Also verify the warning can be suppressed.  */
> @@ -65,8 +65,8 @@ NOIPA void warn_g1 (struct A *p)
>    g1 (p);
>  }
>  
> -// { dg-message "inlined from 'g1'" "" { target *-*-* } 0 }
> -// { dg-message "inlined from 'warn_g1'" "" { target *-*-* } 0 }
> +// { dg-message "inlined from 'g1'" "note on line 68" { target *-*-* } 0 }
> +// { dg-message "inlined from 'warn_g1'" "note on line 69" { target *-*-* } 0 }
>  
>  
>  NOIPA void nowarn_g1 (struct A *p)
> @@ -90,8 +90,8 @@ NOIPA void warn_g2 (struct A *p)
>    g2 (p);
>  }
>  
> -// { dg-message "inlined from 'g2'" "" { target *-*-* } 0 }
> -// { dg-message "inlined from 'warn_g2'" "" { target *-*-* } 0 }
> +// { dg-message "inlined from 'g2'" "note on line 93" { target *-*-* } 0 }
> +// { dg-message "inlined from 'warn_g2'" "note on line 94" { target *-*-* } 0 }

You've added descriptions to disambiguate all of the various directives
on line 0, which is good, but I don't like the use of line numbers in
the descriptions, since it will get very confusing if the numbering
changes.

Would it work to use the message text as the description e.g.

  // { dg-message "inlined from 'warn_g2'" "inlined from 'warn_g2'" { target *-*-* } 0 }

or somesuch?


> diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c
> new file mode 100644
> index 00000000000..979e1e3d78f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c
> @@ -0,0 +1,45 @@
> +/* Similar to Wfree-nonheap-object-4.c but without system headers:
> +   verify that warnings for the same call site from distinct callers
> +   include the correct function names in the inlining stack.
> +   { dg-do compile }
> +   { dg-options "-O2 -Wall" } */
> +
> +struct A
> +{
> +  void *p;
> +};
> +
> +void f0 (struct A *p)
> +{
> +  __builtin_free (p->p);      // { dg-warning "\\\[-Wfree-nonheap-object" }
> +}
> +
> +// Expect two instances of the text below:
> +// { dg-regexp "In function 'f0'," "f0 prefix" { target *-*-* } 0 }
> +// { dg-regexp "In function 'f0'," "f0 prefix" { target *-*-* } 0 }
> +
> +void f1 (struct A *p) { f0 (p); }
> +void f2 (struct A *p) { f1 (p); }
> +
> +extern int array[];
> +// Also expect two instances of the note:
> +// { dg-regexp "declared here" "note on line 24" { target *-*-* } .-2 }
> +// { dg-regexp "declared here" "note on line 24" { target *-*-* } .-3 }
> +
> +void foo (struct A *p)
> +{
> +  p->p = array + 1;
> +  f0 (p);
> +}
> +
> +// { dg-message "inlined from 'foo'" "note on line 35" { target *-*-* } 0 }
> +
> +
> +void bar (struct A *p)
> +{
> +  p->p = array + 2;
> +  f1 (p);
> +}
> +
> +// { dg-message "inlined from 'f1'" "note on line 44" { target *-*-* } 0 }
> +// { dg-message "inlined from 'bar'" "note on line 45" { target *-*-* } 0 }

Likewise here with the hardcoded line numbers.

[...]

> diff --git a/gcc/testsuite/gcc.dg/pragma-diag-9.c b/gcc/testsuite/gcc.dg/pragma-diag-9.c
> new file mode 100644
> index 00000000000..d7eac558128
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pragma-diag-9.c
> @@ -0,0 +1,134 @@
> +/* Verify that #pragma GCC diagnostic down the inlining stack suppresses
> +   a warning that would otherwise be issued for inlined calls higher up
> +   the inlining stack.
> +   { dg-do compile }
> +   { dg-options "-O2 -Wall -Wno-array-bounds" } */
> +
> +extern void* memset (void*, int, __SIZE_TYPE__);
> +
> +static void warn0 (int *p)
> +{
> +  memset (p, __LINE__, 3);    // { dg-warning "\\\[-Wstringop-overflow" }
> +}
> +
> +static void warn1 (int *p)
> +{
> +  warn0 (p + 1);
> +}
> +
> +static void warn2 (int *p)
> +{
> +  warn1 (p + 1);
> +}
> +
> +int a2[2];                    // { dg-message "at offset 12 into destination object 'a2' of size 8" }
> +
> +void warn3 (void)
> +{
> +  warn2 (a2 + 1);
> +}

After reading through this and trying to grok it, I see that this file
logically can be split into several parts: the "warn*" functions, then
the "nowarn*_ignore0" functions, then the "nowarn*_ignore_1" functions
etc.

Please add some kind of separator comment between each of these parts
to make it easy for the reader to see this structure.

> +
> +
> +static void ignore0 (int *p)
> +{
> +#pragma GCC diagnostic push
> +#pragma GCC diagnostic ignored "-Wstringop-overflow"
> +  memset (p, __LINE__, 3);
> +#pragma GCC diagnostic pop
> +}
> +
> +static void nowarn1_ignore0 (int *p)
> +{
> +  ignore0 (p + 1);
> +}
> +
> +static void nowarn2_ignore0 (int *p)
> +{
> +  nowarn1_ignore0 (p + 1);
> +}
> +
> +int b2[2];
> +
> +void nowarn3_ignore0 (void)
> +{
> +  nowarn2_ignore0 (b2 + 1);
> +}
> +
> +
> +static void nowarn0_ignore1 (int *p)
> +{
> +  memset (p, __LINE__, 3);
> +}
> +
> +static void ignore1 (int *p)
> +{
> +#pragma GCC diagnostic push
> +#pragma GCC diagnostic ignored "-Wstringop-overflow"
> +  nowarn0_ignore1 (p + 1);
> +#pragma GCC diagnostic pop
> +}
> +
> +void nowarn2_ignore1 (int *p)
> +{
> +  ignore1 (p + 1);
> +}
> +
> +int c2[2];
> +
> +void nowarn3_ignore1 (void)
> +{
> +  nowarn2_ignore1 (c2 + 1);
> +}
> +
> +
> +static void nowarn0_ignore2 (int *p)
> +{
> +  memset (p, __LINE__, 3);
> +}
> +
> +static void nowarn1_ignore2 (int *p)
> +{
> +  nowarn0_ignore2 (p + 1);
> +}
> +
> +static void ignore2 (int *p)
> +{
> +#pragma GCC diagnostic push
> +#pragma GCC diagnostic ignored "-Wstringop-overflow"
> +  nowarn1_ignore2 (p + 1);
> +#pragma GCC diagnostic pop
> +}
> +
> +int d2[2];
> +
> +void nowarn3_ignore2 (void)
> +{
> +  ignore2 (c2 + 1);
> +}
> +
> +
> +
> +static void nowarn0_ignore3 (int *p)
> +{
> +  memset (p, __LINE__, 3);
> +}
> +
> +static void nowarn1_ignore3 (int *p)
> +{
> +  nowarn0_ignore3 (p + 1);
> +}
> +
> +static void nowarn2_ignore3 (int *p)
> +{
> +  nowarn1_ignore3 (p + 1);
> +}
> +
> +int e2[2];
> +
> +void ignore3 (void)
> +{
> +#pragma GCC diagnostic push
> +#pragma GCC diagnostic ignored "-Wstringop-overflow"
> +  nowarn2_ignore3 (e2 + 1);
> +#pragma GCC diagnostic pop
> +}

[...]

Dave


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 4/4] remove %G and %K support from pretty printer and -Wformat (PR 98512)
  2021-06-10 23:30       ` [PATCH 4/4] remove %G and %K support from pretty printer and -Wformat " Martin Sebor
  2021-06-30 16:17         ` [PING][PATCH " Martin Sebor
@ 2021-06-30 23:38         ` David Malcolm
  2021-07-06 20:15           ` Martin Sebor
  1 sibling, 1 reply; 44+ messages in thread
From: David Malcolm @ 2021-06-30 23:38 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches

On Thu, 2021-06-10 at 17:30 -0600, Martin Sebor wrote:
> This final diff removes the handlers for %G and %K from the pretty
> printer and the support for the directives from c-format.c so that
> using them will be diagnosed.

I think this is OK once the other patches in the kit are approved.

Presumably if a new GCC tries to compile an older GCC that uses these
codes, we'll get warnings about them, but IIRC those are ignored in the
1st stage of the bootstrap, right?

Dave


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 3/4] remove %K from error() calls in the aarch64/arm back ends (PR 98512)
  2021-06-30 19:56             ` Martin Sebor
@ 2021-07-01  8:01               ` Christophe LYON
  2021-07-01 14:45                 ` Martin Sebor
  0 siblings, 1 reply; 44+ messages in thread
From: Christophe LYON @ 2021-07-01  8:01 UTC (permalink / raw)
  To: Martin Sebor, Martin Sebor via Gcc-patches, richard.sandiford,
	Christophe Lyon


On 30/06/2021 21:56, Martin Sebor via Gcc-patches wrote:
> On 6/11/21 8:46 AM, Martin Sebor wrote:
>> On 6/11/21 3:58 AM, Richard Sandiford wrote:
>>> Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
>>>> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
>>>> index 7b37e1b602c..7cdc824730c 100644
>>>> --- a/gcc/config/arm/arm.c
>>>> +++ b/gcc/config/arm/arm.c
>>>> @@ -13242,13 +13242,8 @@ bounds_check (rtx operand, HOST_WIDE_INT 
>>>> low, HOST_WIDE_INT high,
>>>>     lane = INTVAL (operand);
>>>>     if (lane < low || lane >= high)
>>>> -    {
>>>> -      if (exp)
>>>> -    error ("%K%s %wd out of range %wd - %wd",
>>>> -           exp, desc, lane, low, high - 1);
>>>> -      else
>>>> -    error ("%s %wd out of range %wd - %wd", desc, lane, low, high 
>>>> - 1);
>>>> -    }
>>>> +    error_at (EXPR_LOCATION (exp),
>>>> +          "%s %wd out of range %wd - %wd", desc, lane, low, high - 
>>>> 1);
>>>>   }
>>>>   /* Bounds-check lanes.  */
>>>
>>> This part doesn't look safe: “exp” is null when called from 
>>> arm_const_bounds.
>>
>> Doh!  Yes, will fix, thanks.
>
> Attached is an updated patch with the test above restored.
>
> Christophe, if you could apply it on top of patches 1 and 2 and run
> the aarch64/arm tests that would be great!
>
> Patch 1:
> https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573859.html
> Patch 2:
> https://gcc.gnu.org/pipermail/gcc-patches/2021-June/574088.html
>

Hi,


I hope I got it right, but there are a few regressions on aarch64/arm:

http://people.linaro.org/~christophe.lyon/cross-validation/gcc-test-patches/r12-1929-gf6bc9d9bddad7f9e3aad939bb6750770ac67f003-martin.patch

The patch I applied is 
https://people.linaro.org/~christophe.lyon/cross-validation/gcc-test-patches/r12-1929-gf6bc9d9bddad7f9e3aad939bb6750770ac67f003-martin.patch/commit.txt


The regressions are the same on aarch64/arm:

   Executed from: gcc.dg/format/format.exp
     gcc.dg/format/c90-printf-1.c    %s with NULL (test for warnings, line 243)
     gcc.dg/format/c90-printf-1.c    (test for excess errors)
     gcc.dg/format/c90-printf-1.c   -DWIDE  %s with NULL (test for warnings, line 243)
     gcc.dg/format/c90-printf-1.c   -DWIDE  (test for excess errors)
   Executed from: gcc.dg/dg.exp
     gcc.dg/pr79214.c  (test for warnings, line 25)
     gcc.dg/pr79214.c  (test for warnings, line 30)
     gcc.dg/pr79214.c  (test for warnings, line 35)
     gcc.dg/pr79214.c  (test for warnings, line 40)
     gcc.dg/pr79214.c  (test for warnings, line 45)
     gcc.dg/pr79214.c  (test for warnings, line 52)
     gcc.dg/pr79214.c  (test for warnings, line 59)
     gcc.dg/pr79214.c  (test for warnings, line 66)
     gcc.dg/pr79214.c  (test for warnings, line 73)
     gcc.dg/pr79214.c  (test for warnings, line 80)
     gcc.dg/pr79214.c  (test for warnings, line 87)


If you want to see the corresponding gcc.log, you can click on "log" in 
the red cells of the top-level report.


HTH


Christophe


> Thanks
> Martin

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 3/4] remove %K from error() calls in the aarch64/arm back ends (PR 98512)
  2021-07-01  8:01               ` Christophe LYON
@ 2021-07-01 14:45                 ` Martin Sebor
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Sebor @ 2021-07-01 14:45 UTC (permalink / raw)
  To: Christophe LYON, Martin Sebor via Gcc-patches, richard.sandiford,
	Christophe Lyon

On 7/1/21 2:01 AM, Christophe LYON wrote:
> 
> On 30/06/2021 21:56, Martin Sebor via Gcc-patches wrote:
>> On 6/11/21 8:46 AM, Martin Sebor wrote:
>>> On 6/11/21 3:58 AM, Richard Sandiford wrote:
>>>> Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
>>>>> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
>>>>> index 7b37e1b602c..7cdc824730c 100644
>>>>> --- a/gcc/config/arm/arm.c
>>>>> +++ b/gcc/config/arm/arm.c
>>>>> @@ -13242,13 +13242,8 @@ bounds_check (rtx operand, HOST_WIDE_INT 
>>>>> low, HOST_WIDE_INT high,
>>>>>     lane = INTVAL (operand);
>>>>>     if (lane < low || lane >= high)
>>>>> -    {
>>>>> -      if (exp)
>>>>> -    error ("%K%s %wd out of range %wd - %wd",
>>>>> -           exp, desc, lane, low, high - 1);
>>>>> -      else
>>>>> -    error ("%s %wd out of range %wd - %wd", desc, lane, low, high 
>>>>> - 1);
>>>>> -    }
>>>>> +    error_at (EXPR_LOCATION (exp),
>>>>> +          "%s %wd out of range %wd - %wd", desc, lane, low, high - 
>>>>> 1);
>>>>>   }
>>>>>   /* Bounds-check lanes.  */
>>>>
>>>> This part doesn't look safe: “exp” is null when called from 
>>>> arm_const_bounds.
>>>
>>> Doh!  Yes, will fix, thanks.
>>
>> Attached is an updated patch with the test above restored.
>>
>> Christophe, if you could apply it on top of patches 1 and 2 and run
>> the aarch64/arm tests that would be great!
>>
>> Patch 1:
>> https://gcc.gnu.org/pipermail/gcc-patches/2021-June/573859.html
>> Patch 2:
>> https://gcc.gnu.org/pipermail/gcc-patches/2021-June/574088.html
>>
> 
> Hi,
> 
> 
> I hope I got it right, but there are a few regressions on aarch64/arm:

Thanks!

> 
> http://people.linaro.org/~christophe.lyon/cross-validation/gcc-test-patches/r12-1929-gf6bc9d9bddad7f9e3aad939bb6750770ac67f003-martin.patch
> 
> The patch I applied is 
> https://people.linaro.org/~christophe.lyon/cross-validation/gcc-test-patches/r12-1929-gf6bc9d9bddad7f9e3aad939bb6750770ac67f003-martin.patch/commit.txt
> 
> 
> The regressions are the same on aarch64/arm:
> 
>    Executed from: gcc.dg/format/format.exp
>      gcc.dg/format/c90-printf-1.c    %s with NULL (test for warnings, line 243)
>      gcc.dg/format/c90-printf-1.c    (test for excess errors)
>      gcc.dg/format/c90-printf-1.c   -DWIDE  %s with NULL (test for warnings, line 243)
>      gcc.dg/format/c90-printf-1.c   -DWIDE  (test for excess errors)

The location of the warning has improved here leading to the test
failing where it looks for it in the wrong place (wrong column).
This is (or will be) fixed in the final patch by adjusting the test.



>    Executed from: gcc.dg/dg.exp
>      gcc.dg/pr79214.c  (test for warnings, line 25)
>      gcc.dg/pr79214.c  (test for warnings, line 30)
>      gcc.dg/pr79214.c  (test for warnings, line 35)
>      gcc.dg/pr79214.c  (test for warnings, line 40)
>      gcc.dg/pr79214.c  (test for warnings, line 45)
>      gcc.dg/pr79214.c  (test for warnings, line 52)
>      gcc.dg/pr79214.c  (test for warnings, line 59)
>      gcc.dg/pr79214.c  (test for warnings, line 66)
>      gcc.dg/pr79214.c  (test for warnings, line 73)
>      gcc.dg/pr79214.c  (test for warnings, line 80)
>      gcc.dg/pr79214.c  (test for warnings, line 87)

This is also expected (on all targets) and something I'll deal with
before committing.

> 
> 
> If you want to see the corresponding gcc.log, you can click on "log" in 
> the red cells of the top-level report.

Your results validate the aarch64 and arm changes so they're all
I needed.

Thanks again for your help!

Martin

> 
> 
> HTH
> 
> 
> Christophe
> 
> 
>> Thanks
>> Martin


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 1/4] introduce diagnostic infrastructure changes (PR 98512)
  2021-06-30 22:55             ` [PATCH " David Malcolm
@ 2021-07-01 19:43               ` Martin Sebor
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Sebor @ 2021-07-01 19:43 UTC (permalink / raw)
  To: David Malcolm, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 4824 bytes --]

On 6/30/21 4:55 PM, David Malcolm wrote:
> On Tue, 2021-06-15 at 17:00 -0600, Martin Sebor wrote:
>> On 6/11/21 11:04 AM, David Malcolm wrote:
>>> On Thu, 2021-06-10 at 17:26 -0600, Martin Sebor wrote:
>>>> This diff introduces the diagnostic infrastructure changes to
>>>> support
>>>> controlling warnings at any call site in the inlining stack and
>>>> printing
>>>> the inlining context without the %K and %G directives.
>>>
>>> Thanks for working on this, looks very promising.
>>>
>>>> Improve warning suppression for inlined functions.
>>>>
>>>> Resolves:
>>>> PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at
>>>> declaration site
>>>> PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective in
>>>> conjunction with alias attribute
>>>
>>> Am I right in thinking that you add test coverage for both of these
>>> in
>>> patch 2 of the kit?
>>
>> Yes, the tests depend on the changes in patch 2 (some existing tests
>> fail with just patch 1 applied because the initial location passed
>> to warning_t() is different than with it).
>>
>>
> 
> [...]
> 
>>>
>>
>>
>> Yep, thanks.  Please see the attached revision.
>>
>> Martin
> 
> Various nits inline below:
> 
>> diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
>> index d58586f2526..3a22d4d26a6 100644
>> --- a/gcc/diagnostic.c
>> +++ b/gcc/diagnostic.c
>> @@ -991,51 +991,93 @@ print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
>>     pp_set_prefix (pp, saved_prefix);
>>   }
>>   
>> -/* Update the diag_class of DIAGNOSTIC based on its location
>> -   relative to any
>> +/* Update the inlininig context in CONTEXT for a DIAGNOSTIC.  */
>                   ^^^^^^^^^^^^^^^^^
> 
> It's inlining_info now, so please update this comment.

Inlining_info is the name of the struct (per your request) that
captures what's commonly referred to as the inlining context:
the context from which a function call is made and into which
it's inlined.  Another common name for it is inlining stack.
These are also the terms using which I documented the purpose
of the struct in diagnostic.h.  As far as I know no one refers
to it as the "info of a function call" and while it's not wrong
it per se I don't think it helps make the comment clearer.

I've made the requested naming changes against my better judgment.

> 
>> +
>> +static void
>> +update_inlining_context (diagnostic_context *context,
>> +			 diagnostic_info *diagnostic)
> 
> ...and please rename to "get_any_inlining_info".

Done (with the same reservation as above).

> 
>> +{
>> +  auto &ilocs = diagnostic->m_iinfo.m_ilocs;
>> +
>> +  if (context->set_locations_cb)
>> +    {
>> +      /* Retrieve the locations into which the expression about to be
>> +	 diagnosed has been inlined, including those of all the callers
>> +	 all the way down the inlining stack.  */
>> +      context->set_locations_cb (context, diagnostic);
>> +      location_t loc = diagnostic->m_iinfo.m_ilocs.last ();
> 
> 
>> +      if (diagnostic->m_iinfo.m_ao && loc != UNKNOWN_LOCATION)
>> +	diagnostic->message.set_location (0, loc, SHOW_RANGE_WITH_CARET);
> 
> What is the purpose of the above two lines of code?
> (I believe it's to replace the %G/%K stuff, right?)
> Please can you add a suitable comment.

The purpose of this code was to restore the caret in case it was
suppressed for a rich location by a call to add_range().  I didn't
note down the test that failed and that prompted me to add it (it's
what I was chasing down when I noticed the semi_embedded_vec and
rich_location bugs), but removing it now doesn't trigger any
failures anymore.

>> +    }
>> +  else
>> +    {
>> +      /* When there's no callback use just the one location provided
>> +	 by the caller of the diagnostic function.  */
>> +      location_t loc = diagnostic_location (diagnostic);
>> +      ilocs.safe_push (loc);
>> +      diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
>> +    }
>> +}
>> +
>> +/* Update the kind of DIAGNOSTIC based on its location(s), including
>> +   any of those in its inlining context, relative to any
>                                     ^^^^^^^
> 
> "stack" rather than "context" here; I think we're overusing the word "context".

I don't foresee anyone getting confused by either but again, no
point in spending time arguing about it.  I used stack instead.

> 
...>>   /* Generate a URL string describing CWE.  The caller is 
responsible for
>> @@ -1129,6 +1171,9 @@ static bool
>>   diagnostic_enabled (diagnostic_context *context,
>>   		    diagnostic_info *diagnostic)
>>   {
>> +  /* Update the inlining context for this diagnostic.  */
>> +  update_inlining_context (context, diagnostic);
> 
> Please rename as described above.

Done.

The revised patch is in the attachment.  I plan to go with it unless
there are requests for code changes.

Martin

[-- Attachment #2: gcc-98512-1.diff --]
[-- Type: text/x-patch, Size: 11716 bytes --]

Improve warning suppression for inlined functions [PR 98512].

Resolves:
PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at declaration site
PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective in conjunction with alias attribute

gcc/ChangeLog:

	* diagnostic.c (get_any_inlining_info): New.
	(update_effective_level_from_pragmas): Handle inlining context.
	(diagnostic_enabled): Same.
	(diagnostic_report_diagnostic): Same.
	* diagnostic.h (struct diagnostic_info): Add ctor.
	(struct diagnostic_context): Add new member.
	* tree-diagnostic.c (set_inlining_locations): New.
	(tree_diagnostics_defaults): Set new callback pointer.

diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index d58586f2526..8361f68aace 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -991,51 +991,88 @@ print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
   pp_set_prefix (pp, saved_prefix);
 }
 
-/* Update the diag_class of DIAGNOSTIC based on its location
-   relative to any
+/* Update the inlining info in CONTEXT for a DIAGNOSTIC.  */
+
+static void
+get_any_inlining_info (diagnostic_context *context,
+		       diagnostic_info *diagnostic)
+{
+  auto &ilocs = diagnostic->m_iinfo.m_ilocs;
+
+  if (context->set_locations_cb)
+    /* Retrieve the locations into which the expression about to be
+       diagnosed has been inlined, including those of all the callers
+       all the way down the inlining stack.  */
+    context->set_locations_cb (context, diagnostic);
+  else
+    {
+      /* When there's no callback use just the one location provided
+	 by the caller of the diagnostic function.  */
+      location_t loc = diagnostic_location (diagnostic);
+      ilocs.safe_push (loc);
+      diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
+    }
+}
+
+/* Update the kind of DIAGNOSTIC based on its location(s), including
+   any of those in its inlining stack, relative to any
      #pragma GCC diagnostic
    directives recorded within CONTEXT.
 
-   Return the new diag_class of DIAGNOSTIC if it was updated, or
-   DK_UNSPECIFIED otherwise.  */
+   Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
+   otherwise.  */
 
 static diagnostic_t
 update_effective_level_from_pragmas (diagnostic_context *context,
 				     diagnostic_info *diagnostic)
 {
-  diagnostic_t diag_class = DK_UNSPECIFIED;
-
-  if (context->n_classification_history > 0)
+  if (diagnostic->m_iinfo.m_allsyslocs && !context->dc_warn_system_headers)
     {
-      location_t location = diagnostic_location (diagnostic);
+      /* Ignore the diagnostic if all the inlined locations are
+	 in system headers and -Wno-system-headers is in effect.  */
+      diagnostic->kind = DK_IGNORED;
+      return DK_IGNORED;
+    }
+
+  if (context->n_classification_history <= 0)
+    return DK_UNSPECIFIED;
 
+  /* Iterate over the locations, checking the diagnostic disposition
+     for the diagnostic at each.  If it's explicitly set as opposed
+     to unspecified, update the disposition for this instance of
+     the diagnostic and return it.  */
+  for (location_t loc: diagnostic->m_iinfo.m_ilocs)
+    {
       /* FIXME: Stupid search.  Optimize later. */
       for (int i = context->n_classification_history - 1; i >= 0; i --)
 	{
-	  if (linemap_location_before_p
-	      (line_table,
-	       context->classification_history[i].location,
-	       location))
+	  const diagnostic_classification_change_t &hist
+	    = context->classification_history[i];
+
+	  location_t pragloc = hist.location;
+	  if (!linemap_location_before_p (line_table, pragloc, loc))
+	    continue;
+
+	  if (hist.kind == (int) DK_POP)
 	    {
-	      if (context->classification_history[i].kind == (int) DK_POP)
-		{
-		  i = context->classification_history[i].option;
-		  continue;
-		}
-	      int option = context->classification_history[i].option;
-	      /* The option 0 is for all the diagnostics.  */
-	      if (option == 0 || option == diagnostic->option_index)
-		{
-		  diag_class = context->classification_history[i].kind;
-		  if (diag_class != DK_UNSPECIFIED)
-		    diagnostic->kind = diag_class;
-		  break;
-		}
+	      /* Move on to the next region.  */
+	      i = hist.option;
+	      continue;
+	    }
+
+	  int option = hist.option;
+	  /* The option 0 is for all the diagnostics.  */
+	  if (option == 0 || option == diagnostic->option_index)
+	    {
+	      diagnostic_t kind = hist.kind;
+	      if (kind != DK_UNSPECIFIED)
+		diagnostic->kind = kind;
+	      return kind;
 	    }
 	}
     }
 
-  return diag_class;
+  return DK_UNSPECIFIED;
 }
 
 /* Generate a URL string describing CWE.  The caller is responsible for
@@ -1129,6 +1166,9 @@ static bool
 diagnostic_enabled (diagnostic_context *context,
 		    diagnostic_info *diagnostic)
 {
+  /* Update the inlining stack for this diagnostic.  */
+  get_any_inlining_info (context, diagnostic);
+
   /* Diagnostics with no option or -fpermissive are always enabled.  */
   if (!diagnostic->option_index
       || diagnostic->option_index == permissive_error_option (context))
@@ -1194,9 +1234,17 @@ diagnostic_report_diagnostic (diagnostic_context *context,
 
   /* Give preference to being able to inhibit warnings, before they
      get reclassified to something else.  */
-  if ((diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
-      && !diagnostic_report_warnings_p (context, location))
-    return false;
+  bool report_warning_p = true;
+  if (diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
+    {
+      if (context->dc_inhibit_warnings)
+	return false;
+      /* Remember the result of the overall system header warning setting
+	 but proceed to also check the inlining context.  */
+      report_warning_p = diagnostic_report_warnings_p (context, location);
+      if (!report_warning_p && diagnostic->kind == DK_PEDWARN)
+	return false;
+    }
 
   if (diagnostic->kind == DK_PEDWARN)
     {
@@ -1204,7 +1252,7 @@ diagnostic_report_diagnostic (diagnostic_context *context,
       /* We do this to avoid giving the message for -pedantic-errors.  */
       orig_diag_kind = diagnostic->kind;
     }
- 
+
   if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
     return false;
 
@@ -1228,9 +1276,19 @@ diagnostic_report_diagnostic (diagnostic_context *context,
       && diagnostic->kind == DK_WARNING)
     diagnostic->kind = DK_ERROR;
 
+  diagnostic->message.x_data = &diagnostic->x_data;
+
+  /* Check to see if the diagnostic is enabled at the location and
+     not disabled by #pragma GCC diagnostic anywhere along the inlining
+     stack.  .  */
   if (!diagnostic_enabled (context, diagnostic))
     return false;
 
+  if (!report_warning_p && diagnostic->m_iinfo.m_allsyslocs)
+    /* Bail if the warning is not to be reported because all locations
+       in the inlining stack (if there is one) are in system headers.  */
+    return false;
+
   if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
     diagnostic_check_max_errors (context);
 
@@ -1270,8 +1328,6 @@ diagnostic_report_diagnostic (diagnostic_context *context,
     }
   context->diagnostic_group_emission_count++;
 
-  diagnostic->message.x_data = &diagnostic->x_data;
-  diagnostic->x_data = NULL;
   pp_format (context->printer, &diagnostic->message);
   (*diagnostic_starter (context)) (context, diagnostic);
   pp_output_formatted_text (context->printer);
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 1b9d6b1f64d..9d02615fb7a 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -87,6 +87,11 @@ enum diagnostics_extra_output_kind
    list in diagnostic.def.  */
 struct diagnostic_info
 {
+  diagnostic_info ()
+    : message (), richloc (), metadata (), x_data (), kind (), option_index (),
+      m_iinfo ()
+  { }
+
   /* Text to be formatted.  */
   text_info message;
 
@@ -103,6 +108,18 @@ struct diagnostic_info
   diagnostic_t kind;
   /* Which OPT_* directly controls this diagnostic.  */
   int option_index;
+
+  /* Inlining context containing locations for each call site along
+     the inlining stack.  */
+  struct inlining_info
+  {
+    /* Locations along the inlining stack.  */
+    auto_vec<location_t, 8> m_ilocs;
+    /* The abstract origin of the location.  */
+    void *m_ao;
+    /* Set if every M_ILOCS element is in a system header.  */
+    bool m_allsyslocs;
+  } m_iinfo;
 };
 
 /* Each time a diagnostic's classification is changed with a pragma,
@@ -343,6 +360,12 @@ struct diagnostic_context
 
   /* Callback for final cleanup.  */
   void (*final_cb) (diagnostic_context *context);
+
+  /* Callback to set the locations of call sites along the inlining
+     stack corresponding to a diagnostic location.  Needed to traverse
+     the BLOCK_SUPERCONTEXT() chain hanging off the LOCATION_BLOCK()
+     of a diagnostic's location.  */
+  void (*set_locations_cb)(diagnostic_context *, diagnostic_info *);
 };
 
 static inline void
diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
index 95b8ef30070..1b636d72a29 100644
--- a/gcc/tree-diagnostic.c
+++ b/gcc/tree-diagnostic.c
@@ -305,6 +305,73 @@ default_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
   return true;
 }
 
+/* Set the locations of call sites along the inlining stack corresponding
+   to the DIAGNOSTIC location.  */
+
+static void
+set_inlining_locations (diagnostic_context *,
+			diagnostic_info *diagnostic)
+{
+  location_t loc = diagnostic_location (diagnostic);
+  tree block = LOCATION_BLOCK (loc);
+
+  /* Count the number of locations in system headers.  When all are,
+     warnings are suppressed by -Wno-system-headers.  Otherwise, they
+     involve some user code, possibly inlined into a function in a system
+     header, and are not treated as coming from system headers.  */
+  unsigned nsyslocs = 0;
+
+  /* Use a reference to the vector of locations for convenience.  */
+  auto &ilocs = diagnostic->m_iinfo.m_ilocs;
+
+  while (block && TREE_CODE (block) == BLOCK
+	 && BLOCK_ABSTRACT_ORIGIN (block))
+    {
+      tree ao = BLOCK_ABSTRACT_ORIGIN (block);
+      if (TREE_CODE (ao) == FUNCTION_DECL)
+	{
+	  if (!diagnostic->m_iinfo.m_ao)
+	    diagnostic->m_iinfo.m_ao = block;
+
+	  location_t bsloc = BLOCK_SOURCE_LOCATION (block);
+	  ilocs.safe_push (bsloc);
+	  if (in_system_header_at (bsloc))
+	    ++nsyslocs;
+	}
+      else if (TREE_CODE (ao) != BLOCK)
+	break;
+
+      block = BLOCK_SUPERCONTEXT (block);
+    }
+
+  if (ilocs.length ())
+    {
+      /* When there is an inlining context use the macro expansion
+	 location for the original location and bump up NSYSLOCS if
+	 it's in a system header since it's not counted above.  */
+      location_t sysloc = expansion_point_location_if_in_system_header (loc);
+      if (sysloc != loc)
+	{
+	  loc = sysloc;
+	  ++nsyslocs;
+	}
+    }
+  else
+    {
+      /* When there's no inlining context use the original location
+	 and set NSYSLOCS accordingly.  */
+      nsyslocs = in_system_header_at (loc) != 0;
+    }
+
+  ilocs.safe_push (loc);
+
+  /* Set if all locations are in a system header.  */
+  diagnostic->m_iinfo.m_allsyslocs = nsyslocs == ilocs.length ();
+
+  if (tree *ao = pp_ti_abstract_origin (&diagnostic->message))
+    *ao = (tree)diagnostic->m_iinfo.m_ao;
+}
+
 /* Sets CONTEXT to use language independent diagnostics.  */
 void
 tree_diagnostics_defaults (diagnostic_context *context)
@@ -314,4 +381,5 @@ tree_diagnostics_defaults (diagnostic_context *context)
   diagnostic_format_decoder (context) = default_tree_printer;
   context->print_path = default_tree_diagnostic_path_printer;
   context->make_json_for_path = default_tree_make_json_for_path;
+  context->set_locations_cb = set_inlining_locations;
 }

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PING][PATCH 2/4] remove %G and %K from calls in front end and middle end (PR 98512)
  2021-06-30 23:35             ` David Malcolm
@ 2021-07-01 20:14               ` Martin Sebor
  2021-07-02  6:56                 ` Aldy Hernandez
  2021-07-02 20:52                 ` David Malcolm
  0 siblings, 2 replies; 44+ messages in thread
From: Martin Sebor @ 2021-07-01 20:14 UTC (permalink / raw)
  To: David Malcolm, gcc-patches; +Cc: Jeff Law, Aldy Hernandez

[-- Attachment #1: Type: text/plain, Size: 7822 bytes --]

On 6/30/21 5:35 PM, David Malcolm wrote:
> On Wed, 2021-06-30 at 13:45 -0600, Martin Sebor wrote:
>> On 6/30/21 9:39 AM, Martin Sebor wrote:
>>> Ping.  Attached is the same patch rebased on top the latest trunk.
>>
>> Please see the attached patch instead.  The previous one had typo
>> in it.
>>
>>>
>>> As discussed in the review of Aldy's recent changes to the backwards
>>> threader, he has run into the same bug the patch fixes.  Getting this
>>> patch set reviewed and approved would be helpful in keeping him from
>>> having to work around the bug.
>>>
>>> https://gcc.gnu.org/pipermail/gcc/2021-June/236608.html
>>>
>>> On 6/10/21 5:27 PM, Martin Sebor wrote:
>>>> This diff removes the uses of %G and %K from all warning_at() calls
>>>> throughout GCC front end and middle end.  The inlining context is
>>>> included in diagnostic output whenever it's present.
>>>
>>
> 
> Thanks for writing the patch.
> 
> I went through the full patch, though my eyes may have glazed over in
> places at all of the %G and %K removals.  I *think* you got them mostly
> correct, apart from the following possible issues and nits...
> 
>> diff --git a/gcc/expr.c b/gcc/expr.c
>> index 025033c9ecf..b9fe1cf91d7 100644
>> --- a/gcc/expr.c
>> +++ b/gcc/expr.c
> 
> [...]
> 
>> @@ -11425,10 +11425,10 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
>>   					 DECL_ATTRIBUTES (fndecl))) != NULL)
>>   	  {
>>   	    const char *ident = lang_hooks.decl_printable_name (fndecl, 1);
>> -	    warning_at (tree_nonartificial_location (exp),
>> +	    warning_at (EXPR_LOCATION (exp),
> 
> Are we preserving the existing behavior for
> __attribute__((__artificial__)) here?
> Is this behavior handled somewhere else in the patch kit?

Yes.  The warning infrastructure (set_inlining_locations) uses
the location of the site into which the statement has been inlined
regardless of whether the inlined function is artificial.

> 
>>   			OPT_Wattribute_warning,
>> -			"%Kcall to %qs declared with attribute warning: %s",
>> -			exp, identifier_to_locale (ident),
>> +			"call to %qs declared with attribute warning: %s",
>> +			identifier_to_locale (ident),
>>   			TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
>>   	  }
>>   
> 
> [...]
> 
>> diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c
>> index 02771e4cd60..efb8db98393 100644
>> --- a/gcc/gimple-ssa-warn-restrict.c
>> +++ b/gcc/gimple-ssa-warn-restrict.c
> 
> [...]
> 
>> @@ -1689,7 +1689,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
>>   			  const builtin_memref &ref, offset_int wroff,
>>   			  bool do_warn)
>>   {
>> -  location_t loc = gimple_or_expr_nonartificial_location (call, ref.ptr);
>> +  location_t loc = gimple_location (call);
> 
> Likewise here.
> 
>> @@ -2065,7 +2065,7 @@ check_bounds_or_overlap (range_query *query,
>>   	}
>>       }
>>   
>> -  location_t loc = gimple_or_expr_nonartificial_location (call, dst);
>> +  location_t loc = gimple_location (call);
> 
> Likewise here.
> 
> [...]
> 
>> diff --git a/gcc/testsuite/g++.dg/warn/Wdtor1.s b/gcc/testsuite/g++.dg/warn/Wdtor1.s
>> new file mode 100644
>> index 00000000000..e69de29bb2d
> 
> Is this an empty .s file?  Was this a misfire with "git add"?

It must have been, yes.

> 
> [...]
>> @@ -90,8 +90,8 @@ NOIPA void warn_g2 (struct A *p)
>>     g2 (p);
>>   }
>>   
>> -// { dg-message "inlined from 'g2'" "" { target *-*-* } 0 }
>> -// { dg-message "inlined from 'warn_g2'" "" { target *-*-* } 0 }
>> +// { dg-message "inlined from 'g2'" "note on line 93" { target *-*-* } 0 }
>> +// { dg-message "inlined from 'warn_g2'" "note on line 94" { target *-*-* } 0 }
> 
> You've added descriptions to disambiguate all of the various directives
> on line 0, which is good, but I don't like the use of line numbers in
> the descriptions, since it will get very confusing if the numbering
> changes.
> 
> Would it work to use the message text as the description e.g.
> 
>    // { dg-message "inlined from 'warn_g2'" "inlined from 'warn_g2'" { target *-*-* } 0 }
> 
> or somesuch?

It would certainly work, they're just informational labels printed
by DejaGnu when the assertions fail.  I added them to help me see
what they went with while working with the test.  I'm not concerned
about the line numbers changing.  If they do and someone notices,
they can update them, the same way they might want to if they
rename the functions they're inlined into.

> 
> 
>> diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c
>> new file mode 100644
>> index 00000000000..979e1e3d78f
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c
>> @@ -0,0 +1,45 @@
>> +/* Similar to Wfree-nonheap-object-4.c but without system headers:
>> +   verify that warnings for the same call site from distinct callers
>> +   include the correct function names in the inlining stack.
>> +   { dg-do compile }
>> +   { dg-options "-O2 -Wall" } */
>> +
>> +struct A
>> +{
>> +  void *p;
>> +};
>> +
>> +void f0 (struct A *p)
>> +{
>> +  __builtin_free (p->p);      // { dg-warning "\\\[-Wfree-nonheap-object" }
>> +}
>> +
>> +// Expect two instances of the text below:
>> +// { dg-regexp "In function 'f0'," "f0 prefix" { target *-*-* } 0 }
>> +// { dg-regexp "In function 'f0'," "f0 prefix" { target *-*-* } 0 }
>> +
>> +void f1 (struct A *p) { f0 (p); }
>> +void f2 (struct A *p) { f1 (p); }
>> +
>> +extern int array[];
>> +// Also expect two instances of the note:
>> +// { dg-regexp "declared here" "note on line 24" { target *-*-* } .-2 }
>> +// { dg-regexp "declared here" "note on line 24" { target *-*-* } .-3 }
>> +
>> +void foo (struct A *p)
>> +{
>> +  p->p = array + 1;
>> +  f0 (p);
>> +}
>> +
>> +// { dg-message "inlined from 'foo'" "note on line 35" { target *-*-* } 0 }
>> +
>> +
>> +void bar (struct A *p)
>> +{
>> +  p->p = array + 2;
>> +  f1 (p);
>> +}
>> +
>> +// { dg-message "inlined from 'f1'" "note on line 44" { target *-*-* } 0 }
>> +// { dg-message "inlined from 'bar'" "note on line 45" { target *-*-* } 0 }
> 
> Likewise here with the hardcoded line numbers.
> 
> [...]
> 
>> diff --git a/gcc/testsuite/gcc.dg/pragma-diag-9.c b/gcc/testsuite/gcc.dg/pragma-diag-9.c
>> new file mode 100644
>> index 00000000000..d7eac558128
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/pragma-diag-9.c
>> @@ -0,0 +1,134 @@
>> +/* Verify that #pragma GCC diagnostic down the inlining stack suppresses
>> +   a warning that would otherwise be issued for inlined calls higher up
>> +   the inlining stack.
>> +   { dg-do compile }
>> +   { dg-options "-O2 -Wall -Wno-array-bounds" } */
>> +
>> +extern void* memset (void*, int, __SIZE_TYPE__);
>> +
>> +static void warn0 (int *p)
>> +{
>> +  memset (p, __LINE__, 3);    // { dg-warning "\\\[-Wstringop-overflow" }
>> +}
>> +
>> +static void warn1 (int *p)
>> +{
>> +  warn0 (p + 1);
>> +}
>> +
>> +static void warn2 (int *p)
>> +{
>> +  warn1 (p + 1);
>> +}
>> +
>> +int a2[2];                    // { dg-message "at offset 12 into destination object 'a2' of size 8" }
>> +
>> +void warn3 (void)
>> +{
>> +  warn2 (a2 + 1);
>> +}
> 
> After reading through this and trying to grok it, I see that this file
> logically can be split into several parts: the "warn*" functions, then
> the "nowarn*_ignore0" functions, then the "nowarn*_ignore_1" functions
> etc.
> 
> Please add some kind of separator comment between each of these parts
> to make it easy for the reader to see this structure.

Sure, I've added a comment.

Attached is the revised patch for reference.  Since it just removes
the uses of the %K and %G directives made redundant by the first
patch in the series I'll go ahead and commit it as obvious in a day
or so after patch 1 unless someone has further questions or requests
for changes.

Thanks!

Martin

[-- Attachment #2: gcc-98512-2.diff --]
[-- Type: text/x-patch, Size: 84074 bytes --]

Improve warning suppression for inlined functions.

Resolves:
PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at declaration site
PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective in conjunction with alias attribute

gcc/ChangeLog:

	* builtins.c (warn_string_no_nul): Remove %G.
	(maybe_warn_for_bound): Same.
	(warn_for_access): Same.
	(check_access): Same.
	(check_strncat_sizes): Same.
	(expand_builtin_strncat): Same.
	(expand_builtin_strncmp): Same.
	(expand_builtin): Same.
	(expand_builtin_object_size): Same.
	(warn_dealloc_offset): Same.
	(maybe_emit_free_warning): Same.
	* calls.c (maybe_warn_alloc_args_overflow): Same.
	(maybe_warn_nonstring_arg): Same.
	(maybe_warn_rdwr_sizes): Same.
	* expr.c (expand_expr_real_1): Remove %K.
	* gimple-fold.c (gimple_fold_builtin_strncpy): Remove %G.
	(gimple_fold_builtin_strncat): Same.
	* gimple-ssa-sprintf.c (format_directive): Same.
	(handle_printf_call): Same.
	* gimple-ssa-warn-alloca.c (pass_walloca::execute): Same.
	* gimple-ssa-warn-restrict.c (maybe_diag_overlap): Same.
	(maybe_diag_access_bounds): Same.  Call gimple_location.
	(check_bounds_or_overlap): Same.
	* trans-mem.c (ipa_tm_scan_irr_block): Remove %K.  Simplify.
	* tree-ssa-ccp.c (pass_post_ipa_warn::execute): Remove %G.
	* tree-ssa-strlen.c (maybe_warn_overflow): Same.
	(maybe_diag_stxncpy_trunc): Same.
	(handle_builtin_stxncpy_strncat): Same.
	(maybe_warn_pointless_strcmp): Same.
	* tree-ssa-uninit.c (maybe_warn_operand): Same.

gcc/testsuite/ChangeLog:

	* gcc.dg/Wfree-nonheap-object-4.c: Tighten up.
	* gcc.dg/Wobjsize-1.c: Prune expected output.
	* gcc.dg/Warray-bounds-71.c: New test.
	* gcc.dg/Warray-bounds-71.h: New test header.
	* gcc.dg/Warray-bounds-72.c: New test.
	* gcc.dg/Warray-bounds-73.c: New test.
	* gcc.dg/Warray-bounds-74.c: New test.
	* gcc.dg/Warray-bounds-75.c: New test.
	* gcc.dg/Wfree-nonheap-object-5.c: New test.
	* gcc.dg/pragma-diag-10.c: New test.
	* gcc.dg/pragma-diag-9.c: New test.
	* gcc.dg/uninit-suppress_3.c: New test.


diff --git a/gcc/builtins.c b/gcc/builtins.c
index e5e39386a93..e52fe4291c8 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -1126,30 +1126,30 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
 	{
 	  if (wi::ltu_p (maxsiz, bndrng[0]))
 	    warned = warning_at (loc, opt,
-				 "%K%qD specified bound %s exceeds "
+				 "%qD specified bound %s exceeds "
 				 "maximum object size %E",
-				 expr, func, bndstr, maxobjsize);
+				 func, bndstr, maxobjsize);
 	  else
 	    {
 	      bool maybe = wi::to_wide (size) == bndrng[0];
 	      warned = warning_at (loc, opt,
 				   exact
-				   ? G_("%K%qD specified bound %s exceeds "
+				   ? G_("%qD specified bound %s exceeds "
 					"the size %E of unterminated array")
 				   : (maybe
-				      ? G_("%K%qD specified bound %s may "
+				      ? G_("%qD specified bound %s may "
 					   "exceed the size of at most %E "
 					   "of unterminated array")
-				      : G_("%K%qD specified bound %s exceeds "
+				      : G_("%qD specified bound %s exceeds "
 					   "the size of at most %E "
 					   "of unterminated array")),
-				   expr, func, bndstr, size);
+				   func, bndstr, size);
 	    }
 	}
       else
 	warned = warning_at (loc, opt,
-			     "%K%qD argument missing terminating nul",
-			     expr, func);
+			     "%qD argument missing terminating nul",
+			     func);
     }
   else
     {
@@ -3969,35 +3969,34 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func,
 	    warned = (func
 		      ? warning_at (loc, opt,
 				    (maybe
-				     ? G_("%K%qD specified bound %E may "
+				     ? G_("%qD specified bound %E may "
 					  "exceed maximum object size %E")
-				     : G_("%K%qD specified bound %E "
+				     : G_("%qD specified bound %E "
 					  "exceeds maximum object size %E")),
-				    exp, func, bndrng[0], maxobjsize)
+				    func, bndrng[0], maxobjsize)
 		      : warning_at (loc, opt,
 				    (maybe
-				     ? G_("%Kspecified bound %E may "
+				     ? G_("specified bound %E may "
 					  "exceed maximum object size %E")
-				     : G_("%Kspecified bound %E "
+				     : G_("specified bound %E "
 					  "exceeds maximum object size %E")),
-				    exp, bndrng[0], maxobjsize));
+				    bndrng[0], maxobjsize));
 	  else
 	    warned = (func
 		      ? warning_at (loc, opt,
 				    (maybe
-				     ? G_("%K%qD specified bound [%E, %E] may "
+				     ? G_("%qD specified bound [%E, %E] may "
 					  "exceed maximum object size %E")
-				     : G_("%K%qD specified bound [%E, %E] "
+				     : G_("%qD specified bound [%E, %E] "
 					  "exceeds maximum object size %E")),
-				    exp, func,
-				    bndrng[0], bndrng[1], maxobjsize)
+				    func, bndrng[0], bndrng[1], maxobjsize)
 		      : warning_at (loc, opt,
 				    (maybe
-				     ? G_("%Kspecified bound [%E, %E] may "
+				     ? G_("specified bound [%E, %E] may "
 					  "exceed maximum object size %E")
-				     : G_("%Kspecified bound [%E, %E] "
+				     : G_("specified bound [%E, %E] "
 					  "exceeds maximum object size %E")),
-				    exp, bndrng[0], bndrng[1], maxobjsize));
+				    bndrng[0], bndrng[1], maxobjsize));
 	}
       else if (!size || tree_int_cst_le (bndrng[0], size))
 	return false;
@@ -4005,34 +4004,34 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func,
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD specified bound %E may exceed "
+				 ? G_("%qD specified bound %E may exceed "
 				      "source size %E")
-				 : G_("%K%qD specified bound %E exceeds "
+				 : G_("%qD specified bound %E exceeds "
 				      "source size %E")),
-				exp, func, bndrng[0], size)
+				func, bndrng[0], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kspecified bound %E may exceed "
+				 ? G_("specified bound %E may exceed "
 				      "source size %E")
-				 : G_("%Kspecified bound %E exceeds "
+				 : G_("specified bound %E exceeds "
 				      "source size %E")),
-				exp, bndrng[0], size));
+				bndrng[0], size));
       else
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD specified bound [%E, %E] may "
+				 ? G_("%qD specified bound [%E, %E] may "
 				      "exceed source size %E")
-				 : G_("%K%qD specified bound [%E, %E] exceeds "
+				 : G_("%qD specified bound [%E, %E] exceeds "
 				      "source size %E")),
-				exp, func, bndrng[0], bndrng[1], size)
+				func, bndrng[0], bndrng[1], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kspecified bound [%E, %E] may exceed "
+				 ? G_("specified bound [%E, %E] may exceed "
 				      "source size %E")
-				 : G_("%Kspecified bound [%E, %E] exceeds "
+				 : G_("specified bound [%E, %E] exceeds "
 				      "source size %E")),
-				exp, bndrng[0], bndrng[1], size));
+				bndrng[0], bndrng[1], size));
       if (warned)
 	{
 	  if (pad && pad->src.ref)
@@ -4057,35 +4056,34 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func,
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD specified size %E may "
+				 ? G_("%qD specified size %E may "
 				      "exceed maximum object size %E")
-				 : G_("%K%qD specified size %E "
+				 : G_("%qD specified size %E "
 				      "exceeds maximum object size %E")),
-				exp, func, bndrng[0], maxobjsize)
+				func, bndrng[0], maxobjsize)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kspecified size %E may exceed "
+				 ? G_("specified size %E may exceed "
 				      "maximum object size %E")
-				 : G_("%Kspecified size %E exceeds "
+				 : G_("specified size %E exceeds "
 				      "maximum object size %E")),
-				exp, bndrng[0], maxobjsize));
+				bndrng[0], maxobjsize));
       else
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD specified size between %E and %E "
+				 ? G_("%qD specified size between %E and %E "
 				      "may exceed maximum object size %E")
-				 : G_("%K%qD specified size between %E and %E "
+				 : G_("%qD specified size between %E and %E "
 				      "exceeds maximum object size %E")),
-				exp, func,
-				bndrng[0], bndrng[1], maxobjsize)
+				func, bndrng[0], bndrng[1], maxobjsize)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kspecified size between %E and %E "
+				 ? G_("specified size between %E and %E "
 				      "may exceed maximum object size %E")
-				 : G_("%Kspecified size between %E and %E "
+				 : G_("specified size between %E and %E "
 				      "exceeds maximum object size %E")),
-				exp, bndrng[0], bndrng[1], maxobjsize));
+				bndrng[0], bndrng[1], maxobjsize));
     }
   else if (!size || tree_int_cst_le (bndrng[0], size))
     return false;
@@ -4093,34 +4091,34 @@ maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func,
     warned = (func
 	      ? warning_at (loc, opt,
 			    (maybe
-			     ? G_("%K%qD specified bound %E may exceed "
+			     ? G_("%qD specified bound %E may exceed "
 				  "destination size %E")
-			     : G_("%K%qD specified bound %E exceeds "
+			     : G_("%qD specified bound %E exceeds "
 				  "destination size %E")),
-			    exp, func, bndrng[0], size)
+			    func, bndrng[0], size)
 	      : warning_at (loc, opt,
 			    (maybe
-			     ? G_("%Kspecified bound %E may exceed "
+			     ? G_("specified bound %E may exceed "
 				  "destination size %E")
-			     : G_("%Kspecified bound %E exceeds "
+			     : G_("specified bound %E exceeds "
 				  "destination size %E")),
-			    exp, bndrng[0], size));
+			    bndrng[0], size));
   else
     warned = (func
 	      ? warning_at (loc, opt,
 			    (maybe
-			     ? G_("%K%qD specified bound [%E, %E] may exceed "
+			     ? G_("%qD specified bound [%E, %E] may exceed "
 				  "destination size %E")
-			     : G_("%K%qD specified bound [%E, %E] exceeds "
+			     : G_("%qD specified bound [%E, %E] exceeds "
 				  "destination size %E")),
-			    exp, func, bndrng[0], bndrng[1], size)
+			    func, bndrng[0], bndrng[1], size)
 	      : warning_at (loc, opt,
 			    (maybe
-			     ? G_("%Kspecified bound [%E, %E] exceeds "
+			     ? G_("specified bound [%E, %E] exceeds "
 				  "destination size %E")
-			     : G_("%Kspecified bound [%E, %E] exceeds "
+			     : G_("specified bound [%E, %E] exceeds "
 				  "destination size %E")),
-			    exp, bndrng[0], bndrng[1], size));
+			    bndrng[0], bndrng[1], size));
 
   if (warned)
     {
@@ -4158,65 +4156,63 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
 	warned = (func
 		  ? warning_n (loc, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%K%qD may access %E byte in a region "
+				? G_("%qD may access %E byte in a region "
 				     "of size %E")
-				: G_("%K%qD accessing %E byte in a region "
+				: G_("%qD accessing %E byte in a region "
 				     "of size %E")),
 				(maybe
-				 ? G_ ("%K%qD may access %E bytes in a region "
+				 ? G_ ("%qD may access %E bytes in a region "
 				       "of size %E")
-				 : G_ ("%K%qD accessing %E bytes in a region "
+				 : G_ ("%qD accessing %E bytes in a region "
 				       "of size %E")),
-			       exp, func, range[0], size)
+			       func, range[0], size)
 		  : warning_n (loc, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%Kmay access %E byte in a region "
+				? G_("may access %E byte in a region "
 				     "of size %E")
-				: G_("%Kaccessing %E byte in a region "
+				: G_("accessing %E byte in a region "
 				     "of size %E")),
 			       (maybe
-				? G_("%Kmay access %E bytes in a region "
+				? G_("may access %E bytes in a region "
 				     "of size %E")
-				: G_("%Kaccessing %E bytes in a region "
+				: G_("accessing %E bytes in a region "
 				     "of size %E")),
-			       exp, range[0], size));
+			       range[0], size));
       else if (tree_int_cst_sign_bit (range[1]))
 	{
 	  /* Avoid printing the upper bound if it's invalid.  */
 	  warned = (func
 		    ? warning_at (loc, opt,
 				  (maybe
-				   ? G_("%K%qD may access %E or more bytes "
+				   ? G_("%qD may access %E or more bytes "
 					"in a region of size %E")
-				   : G_("%K%qD accessing %E or more bytes "
+				   : G_("%qD accessing %E or more bytes "
 					"in a region of size %E")),
-				  exp, func, range[0], size)
+				  func, range[0], size)
 		    : warning_at (loc, opt,
 				  (maybe
-				   ? G_("%Kmay access %E or more bytes "
+				   ? G_("may access %E or more bytes "
 					"in a region of size %E")
-				   : G_("%Kaccessing %E or more bytes "
+				   : G_("accessing %E or more bytes "
 					"in a region of size %E")),
-				  exp, range[0], size));
+				  range[0], size));
 	}
       else
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD may access between %E and %E "
+				 ? G_("%qD may access between %E and %E "
 				      "bytes in a region of size %E")
-				 : G_("%K%qD accessing between %E and %E "
+				 : G_("%qD accessing between %E and %E "
 				      "bytes in a region of size %E")),
-				exp, func, range[0], range[1],
-				size)
+				func, range[0], range[1], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kmay access between %E and %E bytes "
+				 ? G_("may access between %E and %E bytes "
 				      "in a region of size %E")
-				 : G_("%Kaccessing between %E and %E bytes "
+				 : G_("accessing between %E and %E bytes "
 				      "in a region of size %E")),
-				exp, range[0], range[1],
-				size));
+				range[0], range[1], size));
       return warned;
     }
 
@@ -4226,69 +4222,67 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
 	warned = (func
 		  ? warning_n (loc, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%K%qD may write %E byte into a region "
+				? G_("%qD may write %E byte into a region "
 				     "of size %E")
-				: G_("%K%qD writing %E byte into a region "
+				: G_("%qD writing %E byte into a region "
 				     "of size %E overflows the destination")),
 			       (maybe
-				? G_("%K%qD may write %E bytes into a region "
+				? G_("%qD may write %E bytes into a region "
 				     "of size %E")
-				: G_("%K%qD writing %E bytes into a region "
+				: G_("%qD writing %E bytes into a region "
 				     "of size %E overflows the destination")),
-			       exp, func, range[0], size)
+			       func, range[0], size)
 		  : warning_n (loc, opt, tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%Kmay write %E byte into a region "
+				? G_("may write %E byte into a region "
 				     "of size %E")
-				: G_("%Kwriting %E byte into a region "
+				: G_("writing %E byte into a region "
 				     "of size %E overflows the destination")),
 			       (maybe
-				? G_("%Kmay write %E bytes into a region "
+				? G_("may write %E bytes into a region "
 				     "of size %E")
-				: G_("%Kwriting %E bytes into a region "
+				: G_("writing %E bytes into a region "
 				     "of size %E overflows the destination")),
-			       exp, range[0], size));
+			       range[0], size));
       else if (tree_int_cst_sign_bit (range[1]))
 	{
 	  /* Avoid printing the upper bound if it's invalid.  */
 	  warned = (func
 		    ? warning_at (loc, opt,
 				  (maybe
-				   ? G_("%K%qD may write %E or more bytes "
+				   ? G_("%qD may write %E or more bytes "
 					"into a region of size %E")
-				   : G_("%K%qD writing %E or more bytes "
+				   : G_("%qD writing %E or more bytes "
 					"into a region of size %E overflows "
 					"the destination")),
-				  exp, func, range[0], size)
+				  func, range[0], size)
 		    : warning_at (loc, opt,
 				  (maybe
-				   ? G_("%Kmay write %E or more bytes into "
+				   ? G_("may write %E or more bytes into "
 					"a region of size %E")
-				   : G_("%Kwriting %E or more bytes into "
+				   : G_("writing %E or more bytes into "
 					"a region of size %E overflows "
 					"the destination")),
-				  exp, range[0], size));
+				  range[0], size));
 	}
       else
 	warned = (func
 		  ? warning_at (loc, opt,
 				(maybe
-				 ? G_("%K%qD may write between %E and %E bytes "
+				 ? G_("%qD may write between %E and %E bytes "
 				      "into a region of size %E")
-				 : G_("%K%qD writing between %E and %E bytes "
+				 : G_("%qD writing between %E and %E bytes "
 				      "into a region of size %E overflows "
 				      "the destination")),
-				exp, func, range[0], range[1],
-				size)
+				func, range[0], range[1], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kmay write between %E and %E bytes "
+				 ? G_("may write between %E and %E bytes "
 				      "into a region of size %E")
-				 : G_("%Kwriting between %E and %E bytes "
+				 : G_("writing between %E and %E bytes "
 				      "into a region of size %E overflows "
 				      "the destination")),
-				exp, range[0], range[1],
-				size));
+				range[0], range[1], size));
       return warned;
     }
 
@@ -4299,64 +4293,64 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
 		  ? warning_n (loc, OPT_Wstringop_overread,
 			       tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%K%qD may read %E byte from a region "
+				? G_("%qD may read %E byte from a region "
 				     "of size %E")
-				: G_("%K%qD reading %E byte from a region "
+				: G_("%qD reading %E byte from a region "
 				     "of size %E")),
 			       (maybe
-				? G_("%K%qD may read %E bytes from a region "
+				? G_("%qD may read %E bytes from a region "
 				     "of size %E")
-				: G_("%K%qD reading %E bytes from a region "
+				: G_("%qD reading %E bytes from a region "
 				     "of size %E")),
-			       exp, func, range[0], size)
+			       func, range[0], size)
 		  : warning_n (loc, OPT_Wstringop_overread,
 			       tree_to_uhwi (range[0]),
 			       (maybe
-				? G_("%Kmay read %E byte from a region "
+				? G_("may read %E byte from a region "
 				     "of size %E")
-				: G_("%Kreading %E byte from a region "
+				: G_("reading %E byte from a region "
 				     "of size %E")),
 			       (maybe
-				? G_("%Kmay read %E bytes from a region "
+				? G_("may read %E bytes from a region "
 				     "of size %E")
-				: G_("%Kreading %E bytes from a region "
+				: G_("reading %E bytes from a region "
 				     "of size %E")),
-			       exp, range[0], size));
+			       range[0], size));
       else if (tree_int_cst_sign_bit (range[1]))
 	{
 	  /* Avoid printing the upper bound if it's invalid.  */
 	  warned = (func
 		    ? warning_at (loc, OPT_Wstringop_overread,
 				  (maybe
-				   ? G_("%K%qD may read %E or more bytes "
+				   ? G_("%qD may read %E or more bytes "
 					"from a region of size %E")
-				   : G_("%K%qD reading %E or more bytes "
+				   : G_("%qD reading %E or more bytes "
 					"from a region of size %E")),
-				  exp, func, range[0], size)
+				  func, range[0], size)
 		    : warning_at (loc, OPT_Wstringop_overread,
 				  (maybe
-				   ? G_("%Kmay read %E or more bytes "
+				   ? G_("may read %E or more bytes "
 					"from a region of size %E")
-				   : G_("%Kreading %E or more bytes "
+				   : G_("reading %E or more bytes "
 					"from a region of size %E")),
-				  exp, range[0], size));
+				  range[0], size));
 	}
       else
 	warned = (func
 		  ? warning_at (loc, OPT_Wstringop_overread,
 				(maybe
-				 ? G_("%K%qD may read between %E and %E bytes "
+				 ? G_("%qD may read between %E and %E bytes "
 				      "from a region of size %E")
-				 : G_("%K%qD reading between %E and %E bytes "
+				 : G_("%qD reading between %E and %E bytes "
 				      "from a region of size %E")),
-				exp, func, range[0], range[1], size)
+				func, range[0], range[1], size)
 		  : warning_at (loc, opt,
 				(maybe
-				 ? G_("%Kmay read between %E and %E bytes "
+				 ? G_("may read between %E and %E bytes "
 				      "from a region of size %E")
-				 : G_("%Kreading between %E and %E bytes "
+				 : G_("reading between %E and %E bytes "
 				      "from a region of size %E")),
-				exp, range[0], range[1], size));
+				range[0], range[1], size));
 
       if (warned)
 	suppress_warning (exp, OPT_Wstringop_overread);
@@ -4369,37 +4363,37 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
     warned = (func
 	      ? warning_n (loc, OPT_Wstringop_overread,
 			   tree_to_uhwi (range[0]),
-			   "%K%qD expecting %E byte in a region of size %E",
-			   "%K%qD expecting %E bytes in a region of size %E",
-			   exp, func, range[0], size)
+			   "%qD expecting %E byte in a region of size %E",
+			   "%qD expecting %E bytes in a region of size %E",
+			   func, range[0], size)
 	      : warning_n (loc, OPT_Wstringop_overread,
 			   tree_to_uhwi (range[0]),
-			   "%Kexpecting %E byte in a region of size %E",
-			   "%Kexpecting %E bytes in a region of size %E",
-			   exp, range[0], size));
+			   "expecting %E byte in a region of size %E",
+			   "expecting %E bytes in a region of size %E",
+			   range[0], size));
   else if (tree_int_cst_sign_bit (range[1]))
     {
       /* Avoid printing the upper bound if it's invalid.  */
       warned = (func
 		? warning_at (loc, OPT_Wstringop_overread,
-			      "%K%qD expecting %E or more bytes in a region "
+			      "%qD expecting %E or more bytes in a region "
 			      "of size %E",
-			      exp, func, range[0], size)
+			      func, range[0], size)
 		: warning_at (loc, OPT_Wstringop_overread,
-			      "%Kexpecting %E or more bytes in a region "
+			      "expecting %E or more bytes in a region "
 			      "of size %E",
-			      exp, range[0], size));
+			      range[0], size));
     }
   else
     warned = (func
 	      ? warning_at (loc, OPT_Wstringop_overread,
-			    "%K%qD expecting between %E and %E bytes in "
+			    "%qD expecting between %E and %E bytes in "
 			    "a region of size %E",
-			    exp, func, range[0], range[1], size)
+			    func, range[0], range[1], size)
 	      : warning_at (loc, OPT_Wstringop_overread,
-			    "%Kexpecting between %E and %E bytes in "
+			    "expecting between %E and %E bytes in "
 			    "a region of size %E",
-			    exp, range[0], range[1], size));
+			    range[0], range[1], size));
 
   if (warned)
     suppress_warning (exp, OPT_Wstringop_overread);
@@ -4759,7 +4753,7 @@ check_access (tree exp, tree dstwrite,
       && TREE_CODE (range[0]) == INTEGER_CST
       && tree_int_cst_lt (maxobjsize, range[0]))
     {
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       maybe_warn_for_bound (OPT_Wstringop_overflow_, loc, exp, func, range,
 			    NULL_TREE, pad);
       return false;
@@ -4787,7 +4781,7 @@ check_access (tree exp, tree dstwrite,
 		  && warning_suppressed_p (pad->dst.ref, opt)))
 	    return false;
 
-	  location_t loc = tree_inlined_location (exp);
+	  location_t loc = EXPR_LOCATION (exp);
 	  bool warned = false;
 	  if (dstwrite == slen && at_least_one)
 	    {
@@ -4796,15 +4790,15 @@ check_access (tree exp, tree dstwrite,
 		 at least one byte past the end of the destination.  */
 	      warned = (func
 			? warning_at (loc, opt,
-				      "%K%qD writing %E or more bytes into "
+				      "%qD writing %E or more bytes into "
 				      "a region of size %E overflows "
 				      "the destination",
-				      exp, func, range[0], dstsize)
+				      func, range[0], dstsize)
 			: warning_at (loc, opt,
-				      "%Kwriting %E or more bytes into "
+				      "writing %E or more bytes into "
 				      "a region of size %E overflows "
 				      "the destination",
-				      exp, range[0], dstsize));
+				      range[0], dstsize));
 	    }
 	  else
 	    {
@@ -4840,7 +4834,7 @@ check_access (tree exp, tree dstwrite,
 	 PAD is nonnull and BNDRNG is valid.  */
       get_size_range (maxread, range, pad ? pad->src.bndrng : NULL);
 
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       tree size = dstsize;
       if (pad && pad->mode == access_read_only)
 	size = wide_int_to_tree (sizetype, pad->src.sizrng[1]);
@@ -4901,7 +4895,7 @@ check_access (tree exp, tree dstwrite,
 	      && warning_suppressed_p (pad->src.ref, opt)))
 	return false;
 
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       const bool read
 	= mode == access_read_only || mode == access_read_write;
       const bool maybe = pad && pad->dst.parmarray;
@@ -6481,10 +6475,10 @@ check_strncat_sizes (tree exp, tree objsize)
   if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (objsize)
       && tree_int_cst_equal (objsize, maxread))
     {
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       warning_at (loc, OPT_Wstringop_overflow_,
-		  "%K%qD specified bound %E equals destination size",
-		  exp, get_callee_fndecl (exp), maxread);
+		  "%qD specified bound %E equals destination size",
+		  get_callee_fndecl (exp), maxread);
 
       return false;
     }
@@ -6554,10 +6548,10 @@ expand_builtin_strncat (tree exp, rtx)
   if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (destsize)
       && tree_int_cst_equal (destsize, maxread))
     {
-      location_t loc = tree_inlined_location (exp);
+      location_t loc = EXPR_LOCATION (exp);
       warning_at (loc, OPT_Wstringop_overflow_,
-		  "%K%qD specified bound %E equals destination size",
-		  exp, get_callee_fndecl (exp), maxread);
+		  "%qD specified bound %E equals destination size",
+		  get_callee_fndecl (exp), maxread);
 
       return NULL_RTX;
     }
@@ -7330,7 +7324,7 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
       || !check_nul_terminated_array (exp, arg2, arg3))
     return NULL_RTX;
 
-  location_t loc = tree_inlined_location (exp);
+  location_t loc = EXPR_LOCATION (exp);
   tree len1 = c_strlen (arg1, 1);
   tree len2 = c_strlen (arg2, 1);
 
@@ -10006,13 +10000,13 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
     case BUILT_IN_VA_ARG_PACK:
       /* All valid uses of __builtin_va_arg_pack () are removed during
 	 inlining.  */
-      error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
+      error ("invalid use of %<__builtin_va_arg_pack ()%>");
       return const0_rtx;
 
     case BUILT_IN_VA_ARG_PACK_LEN:
       /* All valid uses of __builtin_va_arg_pack_len () are removed during
 	 inlining.  */
-      error ("%Kinvalid use of %<__builtin_va_arg_pack_len ()%>", exp);
+      error ("invalid use of %<__builtin_va_arg_pack_len ()%>");
       return const0_rtx;
 
       /* Return the address of the first anonymous stack arg.  */
@@ -12961,8 +12955,8 @@ expand_builtin_object_size (tree exp)
 
   if (!validate_arglist (exp, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
     {
-      error ("%Kfirst argument of %qD must be a pointer, second integer constant",
-	     exp, fndecl);
+      error ("first argument of %qD must be a pointer, second integer constant",
+	     fndecl);
       expand_builtin_trap ();
       return const0_rtx;
     }
@@ -12974,8 +12968,8 @@ expand_builtin_object_size (tree exp)
       || tree_int_cst_sgn (ost) < 0
       || compare_tree_int (ost, 3) > 0)
     {
-      error ("%Klast argument of %qD is not integer constant between 0 and 3",
-	     exp, fndecl);
+      error ("last argument of %qD is not integer constant between 0 and 3",
+	      fndecl);
       expand_builtin_trap ();
       return const0_rtx;
     }
@@ -13787,8 +13781,8 @@ warn_dealloc_offset (location_t loc, tree exp, const access_ref &aref)
     }
 
   if (!warning_at (loc, OPT_Wfree_nonheap_object,
-		   "%K%qD called on pointer %qE with nonzero offset%s",
-		   exp, dealloc_decl, aref.ref, offstr))
+		   "%qD called on pointer %qE with nonzero offset%s",
+		   dealloc_decl, aref.ref, offstr))
     return false;
 
   if (DECL_P (aref.ref))
@@ -13843,15 +13837,15 @@ maybe_emit_free_warning (tree exp)
     return;
 
   tree dealloc_decl = get_callee_fndecl (exp);
-  location_t loc = tree_inlined_location (exp);
+  location_t loc = EXPR_LOCATION (exp);
 
   if (DECL_P (ref) || EXPR_P (ref))
     {
       /* Diagnose freeing a declared object.  */
       if (aref.ref_declared ()
 	  && warning_at (loc, OPT_Wfree_nonheap_object,
-			 "%K%qD called on unallocated object %qD",
-			 exp, dealloc_decl, ref))
+			 "%qD called on unallocated object %qD",
+			 dealloc_decl, ref))
 	{
 	  loc = (DECL_P (ref)
 		 ? DECL_SOURCE_LOCATION (ref)
@@ -13870,8 +13864,8 @@ maybe_emit_free_warning (tree exp)
   else if (CONSTANT_CLASS_P (ref))
     {
       if (warning_at (loc, OPT_Wfree_nonheap_object,
-		      "%K%qD called on a pointer to an unallocated "
-		      "object %qE", exp, dealloc_decl, ref))
+		      "%qD called on a pointer to an unallocated "
+		      "object %qE", dealloc_decl, ref))
 	{
 	  if (TREE_CODE (ptr) == SSA_NAME)
 	    {
@@ -13909,18 +13903,18 @@ maybe_emit_free_warning (tree exp)
 		     ? OPT_Wmismatched_new_delete
 		     : OPT_Wmismatched_dealloc);
 		  warned = warning_at (loc, opt,
-				       "%K%qD called on pointer returned "
+				       "%qD called on pointer returned "
 				       "from a mismatched allocation "
-				       "function", exp, dealloc_decl);
+				       "function", dealloc_decl);
 		}
 	    }
 	  else if (gimple_call_builtin_p (def_stmt, BUILT_IN_ALLOCA)
 	    	   || gimple_call_builtin_p (def_stmt,
 	    				     BUILT_IN_ALLOCA_WITH_ALIGN))
 	    warned = warning_at (loc, OPT_Wfree_nonheap_object,
-				 "%K%qD called on pointer to "
+				 "%qD called on pointer to "
 				 "an unallocated object",
-				 exp, dealloc_decl);
+				 dealloc_decl);
 	  else if (warn_dealloc_offset (loc, exp, aref))
 	    return;
 
diff --git a/gcc/calls.c b/gcc/calls.c
index f8a4b79e7f8..d2413a280cf 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1435,8 +1435,8 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 	  if (tree_int_cst_lt (args[i], integer_zero_node))
 	    {
 	      warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-				   "%Kargument %i value %qE is negative",
-				   exp, idx[i] + 1, args[i]);
+				   "argument %i value %qE is negative",
+				   idx[i] + 1, args[i]);
 	    }
 	  else if (integer_zerop (args[i]))
 	    {
@@ -1452,8 +1452,8 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 		  : !lookup_attribute ("returns_nonnull",
 				       TYPE_ATTRIBUTES (fntype)))
 		warned = warning_at (loc, OPT_Walloc_zero,
-				     "%Kargument %i value is zero",
-				     exp, idx[i] + 1);
+				     "argument %i value is zero",
+				     idx[i] + 1);
 	    }
 	  else if (tree_int_cst_lt (maxobjsize, args[i]))
 	    {
@@ -1470,9 +1470,9 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 		continue;
 
 	      warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-				   "%Kargument %i value %qE exceeds "
+				   "argument %i value %qE exceeds "
 				   "maximum object size %E",
-				   exp, idx[i] + 1, args[i], maxobjsize);
+				   idx[i] + 1, args[i], maxobjsize);
 	    }
 	}
       else if (TREE_CODE (args[i]) == SSA_NAME
@@ -1484,16 +1484,16 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 	      && tree_int_cst_le (argrange[i][1], integer_zero_node))
 	    {
 	      warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-				   "%Kargument %i range [%E, %E] is negative",
-				   exp, idx[i] + 1,
+				   "argument %i range [%E, %E] is negative",
+				   idx[i] + 1,
 				   argrange[i][0], argrange[i][1]);
 	    }
 	  else if (tree_int_cst_lt (maxobjsize, argrange[i][0]))
 	    {
 	      warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-				   "%Kargument %i range [%E, %E] exceeds "
+				   "argument %i range [%E, %E] exceeds "
 				   "maximum object size %E",
-				   exp, idx[i] + 1,
+				   idx[i] + 1,
 				   argrange[i][0], argrange[i][1],
 				   maxobjsize);
 	    }
@@ -1521,15 +1521,15 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
 
       if (vflow)
 	warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-			     "%Kproduct %<%E * %E%> of arguments %i and %i "
+			     "product %<%E * %E%> of arguments %i and %i "
 			     "exceeds %<SIZE_MAX%>",
-			     exp, argrange[0][0], argrange[1][0],
+			     argrange[0][0], argrange[1][0],
 			     idx[0] + 1, idx[1] + 1);
       else if (wi::ltu_p (wi::to_wide (maxobjsize, szprec), prod))
 	warned = warning_at (loc, OPT_Walloc_size_larger_than_,
-			     "%Kproduct %<%E * %E%> of arguments %i and %i "
+			     "product %<%E * %E%> of arguments %i and %i "
 			     "exceeds maximum object size %E",
-			     exp, argrange[0][0], argrange[1][0],
+			     argrange[0][0], argrange[1][0],
 			     idx[0] + 1, idx[1] + 1,
 			     maxobjsize);
 
@@ -1729,14 +1729,14 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
 	  bool warned = false;
 	  if (tree_int_cst_equal (bndrng[0], bndrng[1]))
 	    warned = warning_at (loc, OPT_Wstringop_overread,
-				 "%K%qD specified bound %E "
+				 "%qD specified bound %E "
 				 "exceeds maximum object size %E",
-				 exp, fndecl, bndrng[0], maxobjsize);
+				 fndecl, bndrng[0], maxobjsize);
 	  else
 	    warned = warning_at (loc, OPT_Wstringop_overread,
-				 "%K%qD specified bound [%E, %E] "
+				 "%qD specified bound [%E, %E] "
 				 "exceeds maximum object size %E",
-				 exp, fndecl, bndrng[0], bndrng[1],
+				 fndecl, bndrng[0], bndrng[1],
 				 maxobjsize);
 	  if (warned)
 	    suppress_warning (exp, OPT_Wstringop_overread);
@@ -2068,16 +2068,16 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 		= access.second.array_as_string (ptrtype);
 
 	      if (warning_at (loc, OPT_Wstringop_overflow_,
-			      "%Kbound argument %i value %s is "
+			      "bound argument %i value %s is "
 			      "negative for a variable length array "
 			      "argument %i of type %s",
-			      exp, sizidx + 1, sizstr,
+			      sizidx + 1, sizstr,
 			      ptridx + 1, argtypestr.c_str ()))
 		arg_warned = OPT_Wstringop_overflow_;
 	    }
 	  else if (warning_at (loc, OPT_Wstringop_overflow_,
-			       "%Kargument %i value %s is negative",
-			       exp, sizidx + 1, sizstr))
+			       "argument %i value %s is negative",
+			       sizidx + 1, sizstr))
 	    arg_warned = OPT_Wstringop_overflow_;
 
 	  if (arg_warned != no_warning)
@@ -2124,20 +2124,19 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 		    = access.second.array_as_string (ptrtype);
 
 		  if (warning_at (loc, OPT_Wnonnull,
-				  "%Kargument %i of variable length "
+				  "argument %i of variable length "
 				  "array %s is null but "
 				  "the corresponding bound argument "
 				  "%i value is %s",
-				  exp, sizidx + 1, argtypestr.c_str (),
+				  sizidx + 1, argtypestr.c_str (),
 				  ptridx + 1, sizstr))
 		    arg_warned = OPT_Wnonnull;
 		}
 	      else if (warning_at (loc, OPT_Wnonnull,
-				   "%Kargument %i is null but "
+				   "argument %i is null but "
 				   "the corresponding size argument "
 				   "%i value is %s",
-				   exp, ptridx + 1, sizidx + 1,
-				   sizstr))
+				   ptridx + 1, sizidx + 1, sizstr))
 		arg_warned = OPT_Wnonnull;
 	    }
 	  else if (access_size && access.second.static_p)
@@ -2145,10 +2144,9 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 	      /* Warn about null pointers for [static N] array arguments
 		 but do not warn for ordinary (i.e., nonstatic) arrays.  */
 	      if (warning_at (loc, OPT_Wnonnull,
-			      "%Kargument %i to %<%T[static %E]%> "
+			      "argument %i to %<%T[static %E]%> "
 			      "is null where non-null expected",
-			      exp, ptridx + 1, argtype,
-			      access_size))
+			      ptridx + 1, argtype, access_size))
 		arg_warned = OPT_Wnonnull;		
 	    }
 
diff --git a/gcc/expr.c b/gcc/expr.c
index 025033c9ecf..b9fe1cf91d7 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -11401,7 +11401,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
       /* All valid uses of __builtin_va_arg_pack () are removed during
 	 inlining.  */
       if (CALL_EXPR_VA_ARG_PACK (exp))
-	error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp);
+	error ("invalid use of %<__builtin_va_arg_pack ()%>");
       {
 	tree fndecl = get_callee_fndecl (exp), attr;
 
@@ -11413,7 +11413,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 					 DECL_ATTRIBUTES (fndecl))) != NULL)
 	  {
 	    const char *ident = lang_hooks.decl_printable_name (fndecl, 1);
-	    error ("%Kcall to %qs declared with attribute error: %s", exp,
+	    error ("call to %qs declared with attribute error: %s",
 		   identifier_to_locale (ident),
 		   TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
 	  }
@@ -11425,10 +11425,10 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 					 DECL_ATTRIBUTES (fndecl))) != NULL)
 	  {
 	    const char *ident = lang_hooks.decl_printable_name (fndecl, 1);
-	    warning_at (tree_nonartificial_location (exp),
+	    warning_at (EXPR_LOCATION (exp),
 			OPT_Wattribute_warning,
-			"%Kcall to %qs declared with attribute warning: %s",
-			exp, identifier_to_locale (ident),
+			"call to %qs declared with attribute warning: %s",
+			identifier_to_locale (ident),
 			TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
 	  }
 
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 68031538145..1401092aa9b 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -2115,13 +2115,13 @@ gimple_fold_builtin_strncpy (gimple_stmt_iterator *gsi,
 	  tree slen = get_maxval_strlen (src, SRK_STRLEN);
 	  if (slen && !integer_zerop (slen))
 	    warning_at (loc, OPT_Wstringop_truncation,
-			"%G%qD destination unchanged after copying no bytes "
+			"%qD destination unchanged after copying no bytes "
 			"from a string of length %E",
-			stmt, fndecl, slen);
+			fndecl, slen);
 	  else
 	    warning_at (loc, OPT_Wstringop_truncation,
-			"%G%qD destination unchanged after copying no bytes",
-			stmt, fndecl);
+			"%qD destination unchanged after copying no bytes",
+			fndecl);
 	}
 
       replace_call_with_value (gsi, dest);
@@ -2498,11 +2498,11 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
 	  location_t loc = gimple_location (stmt);
 	  nowarn = warning_at (loc, OPT_Wstringop_overflow_,
 			       cmpdst == 0
-			       ? G_("%G%qD specified bound %E equals "
+			       ? G_("%qD specified bound %E equals "
 				    "destination size")
-			       : G_("%G%qD specified bound %E exceeds "
+			       : G_("%qD specified bound %E exceeds "
 				    "destination size %wu"),
-			       stmt, fndecl, len, dstsize);
+			       fndecl, len, dstsize);
 	  if (nowarn)
 	    suppress_warning (stmt, OPT_Wstringop_overflow_);
 	}
@@ -2518,8 +2518,8 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
 	 of the destination is unknown (it's not an uncommon mistake
 	 to specify as the bound to strncpy the length of the source).  */
       if (warning_at (loc, OPT_Wstringop_overflow_,
-		      "%G%qD specified bound %E equals source length",
-		      stmt, fndecl, len))
+		      "%qD specified bound %E equals source length",
+		      fndecl, len))
 	suppress_warning (stmt, OPT_Wstringop_overflow_);
     }
 
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index 41e3be6f9f4..f38fb03f068 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -3115,9 +3115,8 @@ format_directive (const call_info &info,
   if (fmtres.nullp)
     {
       fmtwarn (dirloc, argloc, NULL, info.warnopt (),
-	       "%G%<%.*s%> directive argument is null",
-	       info.callstmt, dirlen,
-	       target_to_host (hostdir, sizeof hostdir, dir.beg));
+	       "%<%.*s%> directive argument is null",
+	       dirlen, target_to_host (hostdir, sizeof hostdir, dir.beg));
 
       /* Don't bother processing the rest of the format string.  */
       res->warned = true;
@@ -4620,8 +4619,7 @@ handle_printf_call (gimple_stmt_iterator *gsi, pointer_query &ptr_qry)
 	     is not constant.  */
 	  location_t loc = gimple_location (info.callstmt);
 	  warning_at (EXPR_LOC_OR_LOC (dstptr, loc),
-		      info.warnopt (), "%Gnull destination pointer",
-		      info.callstmt);
+		      info.warnopt (), "null destination pointer");
 	  return false;
 	}
 
@@ -4650,8 +4648,7 @@ handle_printf_call (gimple_stmt_iterator *gsi, pointer_query &ptr_qry)
     {
       location_t loc = gimple_location (info.callstmt);
       warning_at (EXPR_LOC_OR_LOC (info.format, loc),
-		  info.warnopt (), "%Gnull format string",
-		  info.callstmt);
+		  info.warnopt (), "null format string");
       return false;
     }
 
diff --git a/gcc/gimple-ssa-warn-alloca.c b/gcc/gimple-ssa-warn-alloca.c
index 72480f1d8cb..4fc7125d378 100644
--- a/gcc/gimple-ssa-warn-alloca.c
+++ b/gcc/gimple-ssa-warn-alloca.c
@@ -283,7 +283,7 @@ pass_walloca::execute (function *fun)
 	    }
 	  else if (warn_alloca)
 	    {
-	      warning_at (loc, OPT_Walloca, "%Guse of %<alloca%>", stmt);
+	      warning_at (loc, OPT_Walloca, "use of %<alloca%>");
 	      continue;
 	    }
 	  else if (warn_alloca_limit < 0)
@@ -322,11 +322,10 @@ pass_walloca::execute (function *fun)
 		auto_diagnostic_group d;
 		if (warning_at (loc, wcode,
 				(is_vla
-				 ? G_("%Gargument to variable-length "
+				 ? G_("argument to variable-length "
 				      "array may be too large")
-				 : G_("%Gargument to %<alloca%> may be too "
-				      "large")),
-				stmt)
+				 : G_("argument to %<alloca%> may be too "
+				      "large")))
 		    && t.limit != 0)
 		  {
 		    print_decu (t.limit, buff);
@@ -342,10 +341,9 @@ pass_walloca::execute (function *fun)
 		auto_diagnostic_group d;
 		if (warning_at (loc, wcode,
 				(is_vla
-				 ? G_("%Gargument to variable-length"
+				 ? G_("argument to variable-length"
 				      " array is too large")
-				 : G_("%Gargument to %<alloca%> is too large")),
-				stmt)
+				 : G_("argument to %<alloca%> is too large")))
 		    && t.limit != 0)
 		  {
 		    print_decu (t.limit, buff);
@@ -361,22 +359,20 @@ pass_walloca::execute (function *fun)
 
 	      warning_at (loc, wcode,
 			  (is_vla
-			   ? G_("%Gunbounded use of variable-length array")
-			   : G_("%Gunbounded use of %<alloca%>")),
-			  stmt);
+			   ? G_("unbounded use of variable-length array")
+			   : G_("unbounded use of %<alloca%>")));
 	      break;
 	    case ALLOCA_IN_LOOP:
 	      gcc_assert (!is_vla);
 	      warning_at (loc, wcode,
-			  "%Guse of %<alloca%> within a loop", stmt);
+			  "use of %<alloca%> within a loop");
 	      break;
 	    case ALLOCA_ARG_IS_ZERO:
 	      warning_at (loc, wcode,
 			  (is_vla
-			   ? G_("%Gargument to variable-length array "
+			   ? G_("argument to variable-length array "
 				"is zero")
-			   : G_("%Gargument to %<alloca%> is zero")),
-			  stmt);
+			   : G_("argument to %<alloca%> is zero")));
 	      break;
 	    default:
 	      gcc_unreachable ();
diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c
index 02771e4cd60..efb8db98393 100644
--- a/gcc/gimple-ssa-warn-restrict.c
+++ b/gcc/gimple-ssa-warn-restrict.c
@@ -1494,36 +1494,36 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
 	    warning_at (loc, OPT_Wrestrict,
 			sizrange[0] == 1
 			? (ovlsiz[0] == 1
-			   ? G_("%G%qD accessing %wu byte at offsets %s "
+			   ? G_("%qD accessing %wu byte at offsets %s "
 				"and %s overlaps %wu byte at offset %s")
-			   :  G_("%G%qD accessing %wu byte at offsets %s "
+			   :  G_("%qD accessing %wu byte at offsets %s "
 				 "and %s overlaps %wu bytes at offset "
 				 "%s"))
 			: (ovlsiz[0] == 1
-			   ? G_("%G%qD accessing %wu bytes at offsets %s "
+			   ? G_("%qD accessing %wu bytes at offsets %s "
 				"and %s overlaps %wu byte at offset %s")
-			   : G_("%G%qD accessing %wu bytes at offsets %s "
+			   : G_("%qD accessing %wu bytes at offsets %s "
 				"and %s overlaps %wu bytes at offset "
 				"%s")),
-			call, func, sizrange[0],
+			func, sizrange[0],
 			offstr[0], offstr[1], ovlsiz[0], offstr[2]);
 	  else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
 	    warning_n (loc, OPT_Wrestrict, sizrange[0],
-		       "%G%qD accessing %wu byte at offsets %s "
+		       "%qD accessing %wu byte at offsets %s "
 		       "and %s overlaps between %wu and %wu bytes "
 		       "at offset %s",
-		       "%G%qD accessing %wu bytes at offsets %s "
+		       "%qD accessing %wu bytes at offsets %s "
 		       "and %s overlaps between %wu and %wu bytes "
 		       "at offset %s",
-		       call, func, sizrange[0], offstr[0], offstr[1],
+		       func, sizrange[0], offstr[0], offstr[1],
 		       ovlsiz[0], ovlsiz[1], offstr[2]);
 	  else
 	    warning_n (loc, OPT_Wrestrict, sizrange[0],
-		       "%G%qD accessing %wu byte at offsets %s and "
+		       "%qD accessing %wu byte at offsets %s and "
 		       "%s overlaps %wu or more bytes at offset %s",
-		       "%G%qD accessing %wu bytes at offsets %s and "
+		       "%qD accessing %wu bytes at offsets %s and "
 		       "%s overlaps %wu or more bytes at offset %s",
-		       call, func, sizrange[0],
+		       func, sizrange[0],
 		       offstr[0], offstr[1], ovlsiz[0], offstr[2]);
 	  return true;
 	}
@@ -1532,28 +1532,28 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
 	{
 	  if (ovlsiz[0] == ovlsiz[1])
 	    warning_n (loc, OPT_Wrestrict, ovlsiz[0],
-		       "%G%qD accessing between %wu and %wu bytes "
+		       "%qD accessing between %wu and %wu bytes "
 		       "at offsets %s and %s overlaps %wu byte at "
 		       "offset %s",
-		       "%G%qD accessing between %wu and %wu bytes "
+		       "%qD accessing between %wu and %wu bytes "
 		       "at offsets %s and %s overlaps %wu bytes "
 		       "at offset %s",
-		       call, func, sizrange[0], sizrange[1],
+		       func, sizrange[0], sizrange[1],
 		       offstr[0], offstr[1], ovlsiz[0], offstr[2]);
 	  else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
 	    warning_at (loc, OPT_Wrestrict,
-			"%G%qD accessing between %wu and %wu bytes at "
+			"%qD accessing between %wu and %wu bytes at "
 			"offsets %s and %s overlaps between %wu and %wu "
 			"bytes at offset %s",
-			call, func, sizrange[0], sizrange[1],
+			func, sizrange[0], sizrange[1],
 			offstr[0], offstr[1], ovlsiz[0], ovlsiz[1],
 			offstr[2]);
 	  else
 	    warning_at (loc, OPT_Wrestrict,
-			"%G%qD accessing between %wu and %wu bytes at "
+			"%qD accessing between %wu and %wu bytes at "
 			"offsets %s and %s overlaps %wu or more bytes "
 			"at offset %s",
-			call, func, sizrange[0], sizrange[1],
+			func, sizrange[0], sizrange[1],
 			offstr[0], offstr[1], ovlsiz[0], offstr[2]);
 	  return true;
 	}
@@ -1563,24 +1563,24 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
 
       if (ovlsiz[0] == ovlsiz[1])
 	warning_n (loc, OPT_Wrestrict, ovlsiz[0],
-		   "%G%qD accessing %wu or more bytes at offsets "
+		   "%qD accessing %wu or more bytes at offsets "
 		   "%s and %s overlaps %wu byte at offset %s",
-		   "%G%qD accessing %wu or more bytes at offsets "
+		   "%qD accessing %wu or more bytes at offsets "
 		   "%s and %s overlaps %wu bytes at offset %s",
-		   call, func, sizrange[0], offstr[0], offstr[1],
+		   func, sizrange[0], offstr[0], offstr[1],
 		   ovlsiz[0], offstr[2]);
       else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
 	warning_at (loc, OPT_Wrestrict,
-		    "%G%qD accessing %wu or more bytes at offsets %s "
+		    "%qD accessing %wu or more bytes at offsets %s "
 		    "and %s overlaps between %wu and %wu bytes "
 		    "at offset %s",
-		    call, func, sizrange[0], offstr[0], offstr[1],
+		    func, sizrange[0], offstr[0], offstr[1],
 		    ovlsiz[0], ovlsiz[1], offstr[2]);
       else
 	warning_at (loc, OPT_Wrestrict,
-		    "%G%qD accessing %wu or more bytes at offsets %s "
+		    "%qD accessing %wu or more bytes at offsets %s "
 		    "and %s overlaps %wu or more bytes at offset %s",
-		    call, func, sizrange[0], offstr[0], offstr[1],
+		    func, sizrange[0], offstr[0], offstr[1],
 		    ovlsiz[0], offstr[2]);
       return true;
     }
@@ -1606,36 +1606,36 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
 	{
 	  if (open_range)
 	    warning_n (loc, OPT_Wrestrict, sizrange[1],
-		       "%G%qD accessing %wu byte may overlap "
+		       "%qD accessing %wu byte may overlap "
 		       "%wu byte",
-		       "%G%qD accessing %wu bytes may overlap "
+		       "%qD accessing %wu bytes may overlap "
 		       "%wu byte",
-		       call, func, sizrange[1], ovlsiz[1]);
+		       func, sizrange[1], ovlsiz[1]);
 	  else
 	    warning_n (loc, OPT_Wrestrict, sizrange[1],
-		       "%G%qD accessing %wu byte at offsets %s "
+		       "%qD accessing %wu byte at offsets %s "
 		       "and %s may overlap %wu byte at offset %s",
-		       "%G%qD accessing %wu bytes at offsets %s "
+		       "%qD accessing %wu bytes at offsets %s "
 		       "and %s may overlap %wu byte at offset %s",
-		       call, func, sizrange[1], offstr[0], offstr[1],
+		       func, sizrange[1], offstr[0], offstr[1],
 		       ovlsiz[1], offstr[2]);
 	  return true;
 	}
 
       if (open_range)
 	warning_n (loc, OPT_Wrestrict, sizrange[1],
-		   "%G%qD accessing %wu byte may overlap "
+		   "%qD accessing %wu byte may overlap "
 		   "up to %wu bytes",
-		   "%G%qD accessing %wu bytes may overlap "
+		   "%qD accessing %wu bytes may overlap "
 		   "up to %wu bytes",
-		   call, func, sizrange[1], ovlsiz[1]);
+		   func, sizrange[1], ovlsiz[1]);
       else
 	warning_n (loc, OPT_Wrestrict, sizrange[1],
-		   "%G%qD accessing %wu byte at offsets %s and "
+		   "%qD accessing %wu byte at offsets %s and "
 		   "%s may overlap up to %wu bytes at offset %s",
-		   "%G%qD accessing %wu bytes at offsets %s and "
+		   "%qD accessing %wu bytes at offsets %s and "
 		   "%s may overlap up to %wu bytes at offset %s",
-		   call, func, sizrange[1], offstr[0], offstr[1],
+		   func, sizrange[1], offstr[0], offstr[1],
 		   ovlsiz[1], offstr[2]);
       return true;
     }
@@ -1644,30 +1644,30 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
     {
       if (open_range)
 	warning_n (loc, OPT_Wrestrict, ovlsiz[1],
-		   "%G%qD accessing between %wu and %wu bytes "
+		   "%qD accessing between %wu and %wu bytes "
 		   "may overlap %wu byte",
-		   "%G%qD accessing between %wu and %wu bytes "
+		   "%qD accessing between %wu and %wu bytes "
 		   "may overlap up to %wu bytes",
-		   call, func, sizrange[0], sizrange[1], ovlsiz[1]);
+		   func, sizrange[0], sizrange[1], ovlsiz[1]);
       else
 	warning_n (loc, OPT_Wrestrict, ovlsiz[1],
-		   "%G%qD accessing between %wu and %wu bytes "
+		   "%qD accessing between %wu and %wu bytes "
 		   "at offsets %s and %s may overlap %wu byte "
 		   "at offset %s",
-		   "%G%qD accessing between %wu and %wu bytes "
+		   "%qD accessing between %wu and %wu bytes "
 		   "at offsets %s and %s may overlap up to %wu "
 		   "bytes at offset %s",
-		   call, func, sizrange[0], sizrange[1],
+		   func, sizrange[0], sizrange[1],
 		   offstr[0], offstr[1], ovlsiz[1], offstr[2]);
       return true;
     }
 
   warning_n (loc, OPT_Wrestrict, ovlsiz[1],
-	     "%G%qD accessing %wu or more bytes at offsets %s "
+	     "%qD accessing %wu or more bytes at offsets %s "
 	     "and %s may overlap %wu byte at offset %s",
-	     "%G%qD accessing %wu or more bytes at offsets %s "
+	     "%qD accessing %wu or more bytes at offsets %s "
 	     "and %s may overlap up to %wu bytes at offset %s",
-	     call, func, sizrange[0], offstr[0], offstr[1],
+	     func, sizrange[0], offstr[0], offstr[1],
 	     ovlsiz[1], offstr[2]);
 
   return true;
@@ -1689,7 +1689,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 			  const builtin_memref &ref, offset_int wroff,
 			  bool do_warn)
 {
-  location_t loc = gimple_or_expr_nonartificial_location (call, ref.ptr);
+  location_t loc = gimple_location (call);
   const offset_int maxobjsize = ref.maxobjsize;
 
   /* Check for excessive size first and regardless of warning options
@@ -1709,15 +1709,15 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	{
 	  if (ref.sizrange[0] == ref.sizrange[1])
 	    warned = warning_at (loc, opt,
-				 "%G%qD specified bound %wu "
+				 "%qD specified bound %wu "
 				 "exceeds maximum object size %wu",
-				 call, func, ref.sizrange[0].to_uhwi (),
+				 func, ref.sizrange[0].to_uhwi (),
 				 maxobjsize.to_uhwi ());
 	  else
 	    warned = warning_at (loc, opt,
-				 "%G%qD specified bound between %wu and %wu "
+				 "%qD specified bound between %wu and %wu "
 				 "exceeds maximum object size %wu",
-				 call, func, ref.sizrange[0].to_uhwi (),
+				 func, ref.sizrange[0].to_uhwi (),
 				 ref.sizrange[1].to_uhwi (),
 				 maxobjsize.to_uhwi ());
 	  return warned ? opt : no_warning;
@@ -1776,9 +1776,9 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	{
 	  auto_diagnostic_group d;
 	  if (warning_at (loc, opt,
-			  "%G%qD pointer overflow between offset %s "
+			  "%qD pointer overflow between offset %s "
 			  "and size %s accessing array %qD with type %qT",
-			  call, func, rangestr[0], rangestr[1], ref.base, type))
+			  func, rangestr[0], rangestr[1], ref.base, type))
 	    {
 	      inform (DECL_SOURCE_LOCATION (ref.base),
 		      "array %qD declared here", ref.base);
@@ -1786,15 +1786,15 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	    }
 	  else
 	    warned = warning_at (loc, opt,
-				 "%G%qD pointer overflow between offset %s "
+				 "%qD pointer overflow between offset %s "
 				 "and size %s",
-				 call, func, rangestr[0], rangestr[1]);
+				 func, rangestr[0], rangestr[1]);
 	}
       else
 	warned = warning_at (loc, opt,
-			     "%G%qD pointer overflow between offset %s "
+			     "%qD pointer overflow between offset %s "
 			     "and size %s",
-			     call, func, rangestr[0], rangestr[1]);
+			     func, rangestr[0], rangestr[1]);
     }
   else if (oobref == ref.base)
     {
@@ -1809,20 +1809,20 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	  if ((ref.basesize < maxobjsize
 	       && warning_at (loc, opt,
 			      form
-			      ? G_("%G%qD forming offset %s is out of "
+			      ? G_("%qD forming offset %s is out of "
 				   "the bounds [0, %wu] of object %qD with "
 				   "type %qT")
-			      : G_("%G%qD offset %s is out of the bounds "
+			      : G_("%qD offset %s is out of the bounds "
 				   "[0, %wu] of object %qD with type %qT"),
-			      call, func, rangestr[0], ref.basesize.to_uhwi (),
+			      func, rangestr[0], ref.basesize.to_uhwi (),
 			      ref.base, TREE_TYPE (ref.base)))
 	      || warning_at (loc, opt,
 			     form
-			     ? G_("%G%qD forming offset %s is out of "
+			     ? G_("%qD forming offset %s is out of "
 				  "the bounds of object %qD with type %qT")
-			     : G_("%G%qD offset %s is out of the bounds "
+			     : G_("%qD offset %s is out of the bounds "
 				  "of object %qD with type %qT"),
-			     call, func, rangestr[0],
+			     func, rangestr[0],
 			     ref.base, TREE_TYPE (ref.base)))
 	    {
 	      inform (DECL_SOURCE_LOCATION (ref.base),
@@ -1833,17 +1833,17 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
       else if (ref.basesize < maxobjsize)
 	warned = warning_at (loc, opt,
 			     form
-			     ? G_("%G%qD forming offset %s is out "
+			     ? G_("%qD forming offset %s is out "
 				  "of the bounds [0, %wu]")
-			     : G_("%G%qD offset %s is out "
+			     : G_("%qD offset %s is out "
 				  "of the bounds [0, %wu]"),
-			     call, func, rangestr[0], ref.basesize.to_uhwi ());
+			     func, rangestr[0], ref.basesize.to_uhwi ());
       else
 	warned = warning_at (loc, opt,
 			     form
-			     ? G_("%G%qD forming offset %s is out of bounds")
-			     : G_("%G%qD offset %s is out of bounds"),
-			     call, func, rangestr[0]);
+			     ? G_("%qD forming offset %s is out of bounds")
+			     : G_("%qD offset %s is out of bounds"),
+			     func, rangestr[0]);
     }
   else if (TREE_CODE (ref.ref) == MEM_REF)
     {
@@ -1854,9 +1854,9 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
       type = TYPE_MAIN_VARIANT (type);
 
       if (warning_at (loc, opt,
-		      "%G%qD offset %s from the object at %qE is out "
+		      "%qD offset %s from the object at %qE is out "
 		      "of the bounds of %qT",
-		      call, func, rangestr[0], ref.base, type))
+		      func, rangestr[0], ref.base, type))
 	{
 	  if (TREE_CODE (ref.ref) == COMPONENT_REF)
 	    refop = TREE_OPERAND (ref.ref, 1);
@@ -1872,10 +1872,10 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
       tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref));
 
       if (warning_at (loc, opt,
-		      "%G%qD offset %s from the object at %qE is out "
+		      "%qD offset %s from the object at %qE is out "
 		      "of the bounds of referenced subobject %qD with "
 		      "type %qT at offset %wi",
-		      call, func, rangestr[0], ref.base,
+		      func, rangestr[0], ref.base,
 		      TREE_OPERAND (ref.ref, 1), type,
 		      ref.refoff.to_shwi ()))
 	{
@@ -2065,7 +2065,7 @@ check_bounds_or_overlap (range_query *query,
 	}
     }
 
-  location_t loc = gimple_or_expr_nonartificial_location (call, dst);
+  location_t loc = gimple_location (call);
   if (operand_equal_p (dst, src, 0))
     {
       /* Issue -Wrestrict unless the pointers are null (those do
@@ -2075,8 +2075,8 @@ check_bounds_or_overlap (range_query *query,
       if (!integer_zerop (dst) && !warning_suppressed_p (call, OPT_Wrestrict))
 	{
 	  warning_at (loc, OPT_Wrestrict,
-		      "%G%qD source argument is the same as destination",
-		      call, func);
+		      "%qD source argument is the same as destination",
+		      func);
 	  suppress_warning (call, OPT_Wrestrict);
 	  return OPT_Wrestrict;
 	}
diff --git a/gcc/testsuite/g++.dg/warn/Wdtor1.s b/gcc/testsuite/g++.dg/warn/Wdtor1.s
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-71.c b/gcc/testsuite/gcc.dg/Warray-bounds-71.c
new file mode 100644
index 00000000000..425bb122909
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-71.c
@@ -0,0 +1,7 @@
+/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic
+   works at any call site in an inlining stack
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+#define IGNORE '1'
+#include "Warray-bounds-71.h"
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-71.h b/gcc/testsuite/gcc.dg/Warray-bounds-71.h
new file mode 100644
index 00000000000..89d1068a266
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-71.h
@@ -0,0 +1,46 @@
+/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic
+   works at any call site in an inlining stack
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+int a[4];
+
+void f1 (int *p, int i)
+{
+#pragma GCC diagnostic push
+#if IGNORE == '1'
+#  pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+  p[i + 1] = 0;
+#pragma GCC diagnostic pop
+}
+
+void f2 (int *p, int i)
+{
+#pragma GCC diagnostic push
+#if IGNORE == '2'
+#  pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+  f1 (p + 1, i + 1);
+#pragma GCC diagnostic pop
+}
+
+void f3 (int *p, int i)
+{
+#pragma GCC diagnostic push
+#if IGNORE == '3'
+#  pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+  f2 (p + 1, i + 1);
+#pragma GCC diagnostic pop
+}
+
+void f4 (void)
+{
+#pragma GCC diagnostic push
+#if IGNORE == '4'
+#  pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+  f3 (a, 1);
+#pragma GCC diagnostic pop
+}
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-72.c b/gcc/testsuite/gcc.dg/Warray-bounds-72.c
new file mode 100644
index 00000000000..eb3f664c0c8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-72.c
@@ -0,0 +1,7 @@
+/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic
+   works at any call site in an inlining stack
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+#define IGNORE '2'
+#include "Warray-bounds-71.h"
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-73.c b/gcc/testsuite/gcc.dg/Warray-bounds-73.c
new file mode 100644
index 00000000000..50e20835293
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-73.c
@@ -0,0 +1,7 @@
+/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic
+   works at any call site in an inlining stack
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+#define IGNORE '3'
+#include "Warray-bounds-71.h"
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-74.c b/gcc/testsuite/gcc.dg/Warray-bounds-74.c
new file mode 100644
index 00000000000..c59a876e073
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-74.c
@@ -0,0 +1,7 @@
+/* Verify that -Warray-bounds suppression via #pragma GCC diagnostic
+   works at any call site in an inlining stack
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+#define IGNORE '4'
+#include "Warray-bounds-71.h"
diff --git a/gcc/testsuite/gcc.dg/Warray-bounds-75.c b/gcc/testsuite/gcc.dg/Warray-bounds-75.c
new file mode 100644
index 00000000000..306b1768b0e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-bounds-75.c
@@ -0,0 +1,12 @@
+/* Sanity test for Warray-bounds-7[1-4].c.  Also verify the expected
+   inlining stack.
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+#include "Warray-bounds-71.h"
+
+// { dg-regexp "In function 'f1'," "In function f1" { target *-*-* } 0 }
+// { dg-regexp "inlined from 'f2' at \[^\\n\\r\]+\[\\n\\r\]" "inlined from f2" { target *-*-* } 0 }
+// { dg-regexp "inlined from 'f3' at \[^\\n\\r\]+\[\\n\\r\]" "inlined from f3" { target *-*-* } 0 }
+// { dg-regexp "inlined from 'f4' at \[^\\n\\r\]+\[\\n\\r\]" "inlined from f4" { target *-*-* } 0 }
+// { dg-message "Warray-bounds-71.h:\\d+:\\d+: warning: array subscript 6 is outside array bounds of 'int\\\[4]'" "warning" { target *-*-* } 0 }
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c
index a7d921248c4..fdef9e6b3ea 100644
--- a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-4.c
@@ -26,7 +26,7 @@ void g2 (struct A *p) { g1 (p); }
 
 #define NOIPA __attribute__ ((noipa))
 
-extern int array[];
+extern int array[];           // { dg-message "declared here" "note on line 29" }
 
 /* Verify the warning is issued even for calls in a system header inlined
    into a function outside the header.  */
@@ -39,7 +39,7 @@ NOIPA void warn_g0 (struct A *p)
   g0 (p);
 }
 
-// { dg-message "inlined from 'warn_g0'" "" { target *-*-* } 0 }
+// { dg-message "inlined from 'warn_g0'" "note on line 42" { target *-*-* } 0 }
 
 
 /* Also verify the warning can be suppressed.  */
@@ -65,8 +65,8 @@ NOIPA void warn_g1 (struct A *p)
   g1 (p);
 }
 
-// { dg-message "inlined from 'g1'" "" { target *-*-* } 0 }
-// { dg-message "inlined from 'warn_g1'" "" { target *-*-* } 0 }
+// { dg-message "inlined from 'g1'" "note on line 68" { target *-*-* } 0 }
+// { dg-message "inlined from 'warn_g1'" "note on line 69" { target *-*-* } 0 }
 
 
 NOIPA void nowarn_g1 (struct A *p)
@@ -90,8 +90,8 @@ NOIPA void warn_g2 (struct A *p)
   g2 (p);
 }
 
-// { dg-message "inlined from 'g2'" "" { target *-*-* } 0 }
-// { dg-message "inlined from 'warn_g2'" "" { target *-*-* } 0 }
+// { dg-message "inlined from 'g2'" "note on line 93" { target *-*-* } 0 }
+// { dg-message "inlined from 'warn_g2'" "note on line 94" { target *-*-* } 0 }
 
 
 NOIPA void nowarn_g2 (struct A *p)
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c
new file mode 100644
index 00000000000..979e1e3d78f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-5.c
@@ -0,0 +1,45 @@
+/* Similar to Wfree-nonheap-object-4.c but without system headers:
+   verify that warnings for the same call site from distinct callers
+   include the correct function names in the inlining stack.
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+struct A
+{
+  void *p;
+};
+
+void f0 (struct A *p)
+{
+  __builtin_free (p->p);      // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+// Expect two instances of the text below:
+// { dg-regexp "In function 'f0'," "f0 prefix" { target *-*-* } 0 }
+// { dg-regexp "In function 'f0'," "f0 prefix" { target *-*-* } 0 }
+
+void f1 (struct A *p) { f0 (p); }
+void f2 (struct A *p) { f1 (p); }
+
+extern int array[];
+// Also expect two instances of the note:
+// { dg-regexp "declared here" "note on line 24" { target *-*-* } .-2 }
+// { dg-regexp "declared here" "note on line 24" { target *-*-* } .-3 }
+
+void foo (struct A *p)
+{
+  p->p = array + 1;
+  f0 (p);
+}
+
+// { dg-message "inlined from 'foo'" "note on line 35" { target *-*-* } 0 }
+
+
+void bar (struct A *p)
+{
+  p->p = array + 2;
+  f1 (p);
+}
+
+// { dg-message "inlined from 'f1'" "note on line 44" { target *-*-* } 0 }
+// { dg-message "inlined from 'bar'" "note on line 45" { target *-*-* } 0 }
diff --git a/gcc/testsuite/gcc.dg/Wobjsize-1.c b/gcc/testsuite/gcc.dg/Wobjsize-1.c
index e80c8add3bb..2bd2f93897b 100644
--- a/gcc/testsuite/gcc.dg/Wobjsize-1.c
+++ b/gcc/testsuite/gcc.dg/Wobjsize-1.c
@@ -4,13 +4,17 @@
 #include "Wobjsize-1.h"
 
 char buf[6];
-/* { dg-warning "writing" "" { target *-*-* } .-1 } */
 
 int main(int argc, char **argv)
 {
-  strcpy (buf,"hello ");
+  strcpy (buf,"hello ");    /* { dg-warning "\\\[-Wstringop-overflow" } */
   return 0;
 }
 
-/* { dg-message "file included" "included" { target *-*-* } 0 } */
-/* { dg-message "inlined from" "inlined" { target *-*-* } 0 } */
+/* { dg-message "file included" "included" { target *-*-* } 0 }
+   { dg-message "inlined from" "inlined" { target *-*-* } 0 }
+
+   The test might emit two warnings, one for the strcpy call and
+   another for the inlined call to __builtin___strcpy_chk() called
+   from strcpy().
+   { dg-prune-output "writing 7 bytes into a region of size 6" } */
diff --git a/gcc/testsuite/gcc.dg/pragma-diag-10.c b/gcc/testsuite/gcc.dg/pragma-diag-10.c
new file mode 100644
index 00000000000..127b299939a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pragma-diag-10.c
@@ -0,0 +1,20 @@
+/* PR middle-end/98512 - #pragma GCC diagnostic ignored ineffective
+   in conjunction with alias attribute
+   { dg-do compile }
+   { dg-options "-O2 -Wall" } */
+
+void *
+__rawmemchr_ppc (const void *s, int c)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+#pragma GCC diagnostic ignored "-Wstringop-overread"
+  if (c != 0)
+    return __builtin_memchr (s, c, (unsigned long)-1);    // { dg-bogus "specified bound \\d+ exceeds maximum object size" }
+#pragma GCC diagnostic pop
+
+  return (char *)s + __builtin_strlen (s);
+}
+
+extern __typeof (__rawmemchr_ppc) __EI___rawmemchr_ppc
+  __attribute__((alias ("__rawmemchr_ppc")));
diff --git a/gcc/testsuite/gcc.dg/pragma-diag-9.c b/gcc/testsuite/gcc.dg/pragma-diag-9.c
new file mode 100644
index 00000000000..9aac379caf2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pragma-diag-9.c
@@ -0,0 +1,141 @@
+/* Verify that #pragma GCC diagnostic down the inlining stack suppresses
+   a warning that would otherwise be issued for inlined calls higher up
+   the inlining stack.
+   { dg-do compile }
+   { dg-options "-O2 -Wall -Wno-array-bounds" } */
+
+extern void* memset (void*, int, __SIZE_TYPE__);
+
+static void warn0 (int *p)
+{
+  memset (p, __LINE__, 3);    // { dg-warning "\\\[-Wstringop-overflow" }
+}
+
+static void warn1 (int *p)
+{
+  warn0 (p + 1);
+}
+
+static void warn2 (int *p)
+{
+  warn1 (p + 1);
+}
+
+int a2[2];                    // { dg-message "at offset 12 into destination object 'a2' of size 8" }
+
+void warn3 (void)
+{
+  warn2 (a2 + 1);
+}
+
+
+// Verify suppression at the innermost frame of the inlining stack.
+
+static void ignore0 (int *p)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  memset (p, __LINE__, 3);
+#pragma GCC diagnostic pop
+}
+
+static void nowarn1_ignore0 (int *p)
+{
+  ignore0 (p + 1);
+}
+
+static void nowarn2_ignore0 (int *p)
+{
+  nowarn1_ignore0 (p + 1);
+}
+
+int b2[2];
+
+void nowarn3_ignore0 (void)
+{
+  nowarn2_ignore0 (b2 + 1);
+}
+
+
+// Verify suppression at the second innermost frame of the inlining stack.
+
+static void nowarn0_ignore1 (int *p)
+{
+  memset (p, __LINE__, 3);
+}
+
+static void ignore1 (int *p)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  nowarn0_ignore1 (p + 1);
+#pragma GCC diagnostic pop
+}
+
+void nowarn2_ignore1 (int *p)
+{
+  ignore1 (p + 1);
+}
+
+int c2[2];
+
+void nowarn3_ignore1 (void)
+{
+  nowarn2_ignore1 (c2 + 1);
+}
+
+
+// Verify suppression at the third innermost frame of the inlining stack.
+
+static void nowarn0_ignore2 (int *p)
+{
+  memset (p, __LINE__, 3);
+}
+
+static void nowarn1_ignore2 (int *p)
+{
+  nowarn0_ignore2 (p + 1);
+}
+
+static void ignore2 (int *p)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  nowarn1_ignore2 (p + 1);
+#pragma GCC diagnostic pop
+}
+
+int d2[2];
+
+void nowarn3_ignore2 (void)
+{
+  ignore2 (c2 + 1);
+}
+
+
+// Verify suppression at the outermost frame of the inlining stack.
+
+static void nowarn0_ignore3 (int *p)
+{
+  memset (p, __LINE__, 3);
+}
+
+static void nowarn1_ignore3 (int *p)
+{
+  nowarn0_ignore3 (p + 1);
+}
+
+static void nowarn2_ignore3 (int *p)
+{
+  nowarn1_ignore3 (p + 1);
+}
+
+int e2[2];
+
+void ignore3 (void)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+  nowarn2_ignore3 (e2 + 1);
+#pragma GCC diagnostic pop
+}
diff --git a/gcc/testsuite/gcc.dg/uninit-suppress_3.c b/gcc/testsuite/gcc.dg/uninit-suppress_3.c
new file mode 100644
index 00000000000..7bbe9edc605
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/uninit-suppress_3.c
@@ -0,0 +1,98 @@
+/* PR middle-end/98871 - Cannot silence -Wmaybe-uninitialized at declaration
+   site
+   { dg-do compile }
+   { dg-options "-O1 -Wall" } */
+
+struct A
+{
+  int x;
+};
+
+// Verify that suppression works at every inlining level.
+
+static int f0 (int *x)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+
+  return ++*x;
+
+#pragma GCC diagnostic pop
+}
+
+static int f1 (int *p, int n)
+{
+  struct A a;
+  for (int i = 0; i < n; ++i) {
+    if (p[i] > 1) {
+      a = (struct A){p[i]};
+    }
+  }
+	
+  return f0 (&a.x);
+}
+
+int f2 (void)
+{
+  int a[] = { 1, 2, 3, 4 };
+  return f1 (a, 4);
+}
+
+
+static int g0 (int *x)
+{
+  return ++*x;
+}
+
+static int g1 (int *p, int n)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+
+  struct A a;
+  for (int i = 0; i < n; ++i) {
+    if (p[i] > 1) {
+      a = (struct A){p[i]};
+    }
+  }
+	
+  return g0 (&a.x);
+
+#pragma GCC diagnostic pop
+}
+
+int g2 (void)
+{
+  int a[] = { 1, 2, 3, 4, 5 };
+  return g1 (a, 5);
+}
+
+
+static int h0 (int *x)
+{
+  return ++*x;
+}
+
+static int h1 (int *p, int n)
+{
+  struct A a;
+  for (int i = 0; i < n; ++i) {
+    if (p[i] > 1) {
+      a = (struct A){p[i]};
+    }
+  }
+	
+  return h0 (&a.x);
+}
+
+int h2 (void)
+{
+  int a[] = { 1, 2, 3, 4, 5, 6 };
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+
+  return h1 (a, 6);
+
+#pragma GCC diagnostic pop
+}
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index e74bd1f5ec0..c270d039b15 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -4413,12 +4413,8 @@ ipa_tm_scan_irr_block (basic_block bb)
 	     is to wrap it in a __tm_waiver block.  This is not
 	     yet implemented, so we can't check for it.  */
 	  if (is_tm_safe (current_function_decl))
-	    {
-	      tree t = build1 (NOP_EXPR, void_type_node, size_zero_node);
-	      SET_EXPR_LOCATION (t, gimple_location (stmt));
-	      error ("%K%<asm%> not allowed in %<transaction_safe%> function",
-		     t);
-	    }
+	    error_at (gimple_location (stmt),
+		      "%<asm%> not allowed in %<transaction_safe%> function");
 	  return true;
 
 	default:
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 42585412325..9ce6214d7e2 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -3563,7 +3563,7 @@ pass_post_ipa_warn::execute (function *fun)
 	      if (argno == 0)
 		{
 		  if (warning_at (loc, OPT_Wnonnull,
-				  "%G%qs pointer is null", stmt, "this")
+				  "%qs pointer is null", "this")
 		      && fndecl)
 		    inform (DECL_SOURCE_LOCATION (fndecl),
 			    "in a call to non-static member function %qD",
@@ -3572,8 +3572,8 @@ pass_post_ipa_warn::execute (function *fun)
 		}
 
 	      if (!warning_at (loc, OPT_Wnonnull,
-			       "%Gargument %u null where non-null "
-			       "expected", stmt, argno))
+			       "argument %u null where non-null "
+			       "expected", argno))
 		continue;
 
 	      tree fndecl = gimple_call_fndecl (stmt);
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 13ea107da17..94257df1067 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -2022,13 +2022,12 @@ maybe_warn_overflow (gimple *stmt, tree len, pointer_query &ptr_qry,
 
       warned = (writefn
 		? warning_at (loc, OPT_Wstringop_overflow_,
-			      "%G%qD writing one too many bytes into a region "
+			      "%qD writing one too many bytes into a region "
 			      "of a size that depends on %<strlen%>",
-			      stmt, writefn)
+			      writefn)
 		: warning_at (loc, OPT_Wstringop_overflow_,
-			      "%Gwriting one too many bytes into a region "
-			      "of a size that depends on %<strlen%>",
-			      stmt));
+			      "writing one too many bytes into a region "
+			      "of a size that depends on %<strlen%>"));
     }
   else if (lenrng[0] == lenrng[1])
     {
@@ -2036,65 +2035,65 @@ maybe_warn_overflow (gimple *stmt, tree len, pointer_query &ptr_qry,
 	warned = (writefn
 		  ? warning_n (loc, OPT_Wstringop_overflow_,
 			       lenrng[0].to_uhwi (),
-			       "%G%qD writing %wu byte into a region "
+			       "%qD writing %wu byte into a region "
 			       "of size %wu",
-			       "%G%qD writing %wu bytes into a region "
+			       "%qD writing %wu bytes into a region "
 			       "of size %wu",
-			       stmt, writefn, lenrng[0].to_uhwi (),
+			       writefn, lenrng[0].to_uhwi (),
 			       spcrng[0].to_uhwi ())
 		  : warning_n (loc, OPT_Wstringop_overflow_,
 			       lenrng[0].to_uhwi (),
-			       "%Gwriting %wu byte into a region "
+			       "writing %wu byte into a region "
 			       "of size %wu",
-			       "%Gwriting %wu bytes into a region "
+			       "writing %wu bytes into a region "
 			       "of size %wu",
-			       stmt, lenrng[0].to_uhwi (),
+			       lenrng[0].to_uhwi (),
 			       spcrng[0].to_uhwi ()));
       else
 	warned = (writefn
 		  ? warning_n (loc, OPT_Wstringop_overflow_,
 			       lenrng[0].to_uhwi (),
-			       "%G%qD writing %wu byte into a region "
+			       "%qD writing %wu byte into a region "
 			       "of size between %wu and %wu",
-			       "%G%qD writing %wu bytes into a region "
+			       "%qD writing %wu bytes into a region "
 			       "of size between %wu and %wu",
-			       stmt, writefn, lenrng[0].to_uhwi (),
+			       writefn, lenrng[0].to_uhwi (),
 			       spcrng[0].to_uhwi (), spcrng[1].to_uhwi ())
 		  : warning_n (loc, OPT_Wstringop_overflow_,
 			       lenrng[0].to_uhwi (),
-			       "%Gwriting %wu byte into a region "
+			       "writing %wu byte into a region "
 			       "of size between %wu and %wu",
-			       "%Gwriting %wu bytes into a region "
+			       "writing %wu bytes into a region "
 			       "of size between %wu and %wu",
-			       stmt, lenrng[0].to_uhwi (),
+			       lenrng[0].to_uhwi (),
 			       spcrng[0].to_uhwi (), spcrng[1].to_uhwi ()));
     }
   else if (spcrng[0] == spcrng[1])
     warned = (writefn
 	      ? warning_at (loc, OPT_Wstringop_overflow_,
-			    "%G%qD writing between %wu and %wu bytes "
+			    "%qD writing between %wu and %wu bytes "
 			    "into a region of size %wu",
-			    stmt, writefn, lenrng[0].to_uhwi (),
+			    writefn, lenrng[0].to_uhwi (),
 			    lenrng[1].to_uhwi (),
 			    spcrng[0].to_uhwi ())
 	      : warning_at (loc, OPT_Wstringop_overflow_,
-			    "%Gwriting between %wu and %wu bytes "
+			    "writing between %wu and %wu bytes "
 			    "into a region of size %wu",
-			    stmt, lenrng[0].to_uhwi (),
+			    lenrng[0].to_uhwi (),
 			    lenrng[1].to_uhwi (),
 			    spcrng[0].to_uhwi ()));
   else
     warned = (writefn
 	      ? warning_at (loc, OPT_Wstringop_overflow_,
-			    "%G%qD writing between %wu and %wu bytes "
+			    "%qD writing between %wu and %wu bytes "
 			    "into a region of size between %wu and %wu",
-			    stmt, writefn, lenrng[0].to_uhwi (),
+			    writefn, lenrng[0].to_uhwi (),
 			    lenrng[1].to_uhwi (),
 			    spcrng[0].to_uhwi (), spcrng[1].to_uhwi ())
 	      : warning_at (loc, OPT_Wstringop_overflow_,
-			    "%Gwriting between %wu and %wu bytes "
+			    "writing between %wu and %wu bytes "
 			    "into a region of size between %wu and %wu",
-			    stmt, lenrng[0].to_uhwi (),
+			    lenrng[0].to_uhwi (),
 			    lenrng[1].to_uhwi (),
 			    spcrng[0].to_uhwi (), spcrng[1].to_uhwi ()));
 
@@ -2985,13 +2984,13 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
       if (lenrange[0] == cntrange[1] && cntrange[0] == cntrange[1])
 	return warning_n (callloc, OPT_Wstringop_truncation,
 			  cntrange[0].to_uhwi (),
-			  "%G%qD output truncated before terminating "
+			  "%qD output truncated before terminating "
 			  "nul copying %E byte from a string of the "
 			  "same length",
-			  "%G%qD output truncated before terminating nul "
+			  "%qD output truncated before terminating nul "
 			  "copying %E bytes from a string of the same "
 			  "length",
-			  stmt, func, cnt);
+			  func, cnt);
       else if (!cat_dstlen_bounded)
 	{
 	  if (wi::geu_p (lenrange[0], cntrange[1]))
@@ -3001,16 +3000,16 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
 	      if (cntrange[0] == cntrange[1])
 		return warning_n (callloc, OPT_Wstringop_truncation,
 				  cntrange[0].to_uhwi (),
-				  "%G%qD output truncated copying %E byte "
+				  "%qD output truncated copying %E byte "
 				  "from a string of length %wu",
-				  "%G%qD output truncated copying %E bytes "
+				  "%qD output truncated copying %E bytes "
 				  "from a string of length %wu",
-				  stmt, func, cnt, lenrange[0].to_uhwi ());
+				  func, cnt, lenrange[0].to_uhwi ());
 
 	      return warning_at (callloc, OPT_Wstringop_truncation,
-				 "%G%qD output truncated copying between %wu "
+				 "%qD output truncated copying between %wu "
 				 "and %wu bytes from a string of length %wu",
-				 stmt, func, cntrange[0].to_uhwi (),
+				 func, cntrange[0].to_uhwi (),
 				 cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
 	    }
 	  else if (wi::geu_p (lenrange[1], cntrange[1]))
@@ -3020,16 +3019,16 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
 	      if (cntrange[0] == cntrange[1])
 		return warning_n (callloc, OPT_Wstringop_truncation,
 				  cntrange[0].to_uhwi (),
-				  "%G%qD output may be truncated copying %E "
+				  "%qD output may be truncated copying %E "
 				  "byte from a string of length %wu",
-				  "%G%qD output may be truncated copying %E "
+				  "%qD output may be truncated copying %E "
 				  "bytes from a string of length %wu",
-				  stmt, func, cnt, lenrange[1].to_uhwi ());
+				  func, cnt, lenrange[1].to_uhwi ());
 
 	      return warning_at (callloc, OPT_Wstringop_truncation,
-				 "%G%qD output may be truncated copying between "
+				 "%qD output may be truncated copying between "
 				 "%wu and %wu bytes from a string of length %wu",
-				 stmt, func, cntrange[0].to_uhwi (),
+				 func, cntrange[0].to_uhwi (),
 				 cntrange[1].to_uhwi (), lenrange[1].to_uhwi ());
 	    }
 	}
@@ -3043,9 +3042,9 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
 	     the lower bound of the specified count but shorter than the
 	     upper bound the copy may (but need not) be truncated.  */
 	  return warning_at (callloc, OPT_Wstringop_truncation,
-			     "%G%qD output may be truncated copying between "
+			     "%qD output may be truncated copying between "
 			     "%wu and %wu bytes from a string of length %wu",
-			     stmt, func, cntrange[0].to_uhwi (),
+			     func, cntrange[0].to_uhwi (),
 			     cntrange[1].to_uhwi (), lenrange[0].to_uhwi ());
 	}
     }
@@ -3072,8 +3071,8 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
 
       if (cntrange[0] == cntrange[1])
 	return warning_at (callloc, OPT_Wstringop_truncation,
-			   "%G%qD specified bound %E equals destination size",
-			   stmt, func, cnt);
+			   "%qD specified bound %E equals destination size",
+			   func, cnt);
     }
 
   return false;
@@ -3197,9 +3196,9 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
       && sisrc == silen
       && is_strlen_related_p (src, len)
       && warning_at (callloc, OPT_Wstringop_truncation,
-		     "%G%qD output truncated before terminating nul "
+		     "%qD output truncated before terminating nul "
 		     "copying as many bytes from a string as its length",
-		     stmt, func))
+		     func))
     warned = true;
   else if ((append_p || !dstsize || len == dstlenp1)
 	   && silen && is_strlen_related_p (src, silen->ptr))
@@ -3210,9 +3209,9 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
       opt_code opt = (append_p || dstsize
 		      ? OPT_Wstringop_overflow_ : OPT_Wstringop_truncation);
       warned = warning_at (callloc, opt,
-			   "%G%qD specified bound depends on the length "
+			   "%qD specified bound depends on the length "
 			   "of the source argument",
-			   stmt, func);
+			   func);
     }
   if (warned)
     {
@@ -4141,24 +4140,24 @@ maybe_warn_pointless_strcmp (gimple *stmt, HOST_WIDE_INT bound,
   if (siz <= minlen && bound == -1)
     warned = warning_at (stmt_loc, OPT_Wstring_compare,
 			 (at_least
-			  ? G_("%G%qD of a string of length %wu or more and "
+			  ? G_("%qD of a string of length %wu or more and "
 			       "an array of size %wu evaluates to nonzero")
-			  : G_("%G%qD of a string of length %wu and an array "
+			  : G_("%qD of a string of length %wu and an array "
 			       "of size %wu evaluates to nonzero")),
-			 stmt, callee, minlen, siz);
+			 callee, minlen, siz);
   else if (!at_least && siz <= HOST_WIDE_INT_MAX)
     {
       if (len[0] != HOST_WIDE_INT_MAX && len[1] != HOST_WIDE_INT_MAX)
 	warned = warning_at (stmt_loc, OPT_Wstring_compare,
-			     "%G%qD of strings of length %wu and %wu "
+			     "%qD of strings of length %wu and %wu "
 			     "and bound of %wu evaluates to nonzero",
-			     stmt, callee, len[0], len[1], bound);
+			     callee, len[0], len[1], bound);
       else
 	warned = warning_at (stmt_loc, OPT_Wstring_compare,
-			     "%G%qD of a string of length %wu, an array "
+			     "%qD of a string of length %wu, an array "
 			     "of size %wu and bound of %wu evaluates to "
 			     "nonzero",
-			     stmt, callee, minlen, siz, bound);
+			     callee, minlen, siz, bound);
     }
 
   if (!warned)
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index 99442d7f975..24ac031a693 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -444,7 +444,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
   if (wlims.always_executed)
     {
       if (warning_at (location, OPT_Wuninitialized,
-		      "%G%qE is used uninitialized", stmt, rhs))
+		      "%qE is used uninitialized", rhs))
 	{
 	  /* ???  This is only effective for decls as in
 	     gcc.dg/uninit-B-O0.c.  Avoid doing this for maybe-uninit
@@ -457,7 +457,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
     }
   else if (wlims.wmaybe_uninit)
     warned = warning_at (location, OPT_Wmaybe_uninitialized,
-			 "%G%qE may be used uninitialized", stmt, rhs);
+			 "%qE may be used uninitialized", rhs);
 
   return warned ? base : NULL_TREE;
 }

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PING][PATCH 2/4] remove %G and %K from calls in front end and middle end (PR 98512)
  2021-07-01 20:14               ` Martin Sebor
@ 2021-07-02  6:56                 ` Aldy Hernandez
  2021-07-02 21:53                   ` Jeff Law
  2021-07-02 20:52                 ` David Malcolm
  1 sibling, 1 reply; 44+ messages in thread
From: Aldy Hernandez @ 2021-07-02  6:56 UTC (permalink / raw)
  To: Martin Sebor, David Malcolm, gcc-patches; +Cc: Jeff Law



On 7/1/21 10:14 PM, Martin Sebor wrote:
> On 6/30/21 5:35 PM, David Malcolm wrote:
>> On Wed, 2021-06-30 at 13:45 -0600, Martin Sebor wrote:
>>> On 6/30/21 9:39 AM, Martin Sebor wrote:

>>> @@ -90,8 +90,8 @@ NOIPA void warn_g2 (struct A *p)
>>>     g2 (p);
>>>   }
>>> -// { dg-message "inlined from 'g2'" "" { target *-*-* } 0 }
>>> -// { dg-message "inlined from 'warn_g2'" "" { target *-*-* } 0 }
>>> +// { dg-message "inlined from 'g2'" "note on line 93" { target *-*-* 
>>> } 0 }
>>> +// { dg-message "inlined from 'warn_g2'" "note on line 94" { target 
>>> *-*-* } 0 }
>>
>> You've added descriptions to disambiguate all of the various directives
>> on line 0, which is good, but I don't like the use of line numbers in
>> the descriptions, since it will get very confusing if the numbering
>> changes.
>>
>> Would it work to use the message text as the description e.g.
>>
>>    // { dg-message "inlined from 'warn_g2'" "inlined from 'warn_g2'" { 
>> target *-*-* } 0 }
>>
>> or somesuch?
> 
> It would certainly work, they're just informational labels printed
> by DejaGnu when the assertions fail.  I added them to help me see
> what they went with while working with the test.  I'm not concerned
> about the line numbers changing.  If they do and someone notices,
> they can update them, the same way they might want to if they
> rename the functions they're inlined into.

I agree with David.  Having too specific tests adds an extra maintenance 
burden.  You may not mind updating all the line numbers when anything 
changes, but others may certainly mind.

Aldy


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PING][PATCH 2/4] remove %G and %K from calls in front end and middle end (PR 98512)
  2021-07-01 20:14               ` Martin Sebor
  2021-07-02  6:56                 ` Aldy Hernandez
@ 2021-07-02 20:52                 ` David Malcolm
  2021-07-02 22:15                   ` Martin Sebor
  1 sibling, 1 reply; 44+ messages in thread
From: David Malcolm @ 2021-07-02 20:52 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches; +Cc: Jeff Law, Aldy Hernandez

On Thu, 2021-07-01 at 14:14 -0600, Martin Sebor wrote:
> On 6/30/21 5:35 PM, David Malcolm wrote:
> > On Wed, 2021-06-30 at 13:45 -0600, Martin Sebor wrote:
> > > On 6/30/21 9:39 AM, Martin Sebor wrote:
> > > > Ping.  Attached is the same patch rebased on top the latest
> > > > trunk.
> > > 
> > > Please see the attached patch instead.  The previous one had typo
> > > in it.
> > > 
> > > > 
> > > > As discussed in the review of Aldy's recent changes to the
> > > > backwards
> > > > threader, he has run into the same bug the patch fixes. 
> > > > Getting this
> > > > patch set reviewed and approved would be helpful in keeping him
> > > > from
> > > > having to work around the bug.
> > > > 
> > > > https://gcc.gnu.org/pipermail/gcc/2021-June/236608.html
> > > > 
> > > > On 6/10/21 5:27 PM, Martin Sebor wrote:
> > > > > This diff removes the uses of %G and %K from all warning_at()
> > > > > calls
> > > > > throughout GCC front end and middle end.  The inlining
> > > > > context is
> > > > > included in diagnostic output whenever it's present.
> > > > 
> > > 
> > 
> > Thanks for writing the patch.
> > 
> > I went through the full patch, though my eyes may have glazed over
> > in
> > places at all of the %G and %K removals.  I *think* you got them
> > mostly
> > correct, apart from the following possible issues and nits...
> > 
> > > diff --git a/gcc/expr.c b/gcc/expr.c
> > > index 025033c9ecf..b9fe1cf91d7 100644
> > > --- a/gcc/expr.c
> > > +++ b/gcc/expr.c
> > 
> > [...]
> > 
> > > @@ -11425,10 +11425,10 @@ expand_expr_real_1 (tree exp, rtx
> > > target, machine_mode tmode,
> > >                                          DECL_ATTRIBUTES
> > > (fndecl))) != NULL)
> > >           {
> > >             const char *ident = lang_hooks.decl_printable_name
> > > (fndecl, 1);
> > > -           warning_at (tree_nonartificial_location (exp),
> > > +           warning_at (EXPR_LOCATION (exp),
> > 
> > Are we preserving the existing behavior for
> > __attribute__((__artificial__)) here?
> > Is this behavior handled somewhere else in the patch kit?
> 
> Yes.  The warning infrastructure (set_inlining_locations) uses
> the location of the site into which the statement has been inlined
> regardless of whether the inlined function is artificial.

Do we have test coverage for this, though?

[...]

> 
> > > @@ -90,8 +90,8 @@ NOIPA void warn_g2 (struct A *p)
> > >     g2 (p);
> > >   }
> > >   
> > > -// { dg-message "inlined from 'g2'" "" { target *-*-* } 0 }
> > > -// { dg-message "inlined from 'warn_g2'" "" { target *-*-* } 0 }
> > > +// { dg-message "inlined from 'g2'" "note on line 93" { target
> > > *-*-* } 0 }
> > > +// { dg-message "inlined from 'warn_g2'" "note on line 94" {
> > > target *-*-* } 0 }
> > 
> > You've added descriptions to disambiguate all of the various
> > directives
> > on line 0, which is good, but I don't like the use of line numbers
> > in
> > the descriptions, since it will get very confusing if the numbering
> > changes.
> > 
> > Would it work to use the message text as the description e.g.
> > 
> >    // { dg-message "inlined from 'warn_g2'" "inlined from
> > 'warn_g2'" { target *-*-* } 0 }
> > 
> > or somesuch?
> 
> It would certainly work, they're just informational labels printed
> by DejaGnu when the assertions fail.  I added them to help me see
> what they went with while working with the test.  I'm not concerned
> about the line numbers changing.  If they do and someone notices,
> they can update them, the same way they might want to if they
> rename the functions they're inlined into.

[...]

> > 
> > After reading through this and trying to grok it, I see that this
> > file
> > logically can be split into several parts: the "warn*" functions,
> > then
> > the "nowarn*_ignore0" functions, then the "nowarn*_ignore_1"
> > functions
> > etc.
> > 
> > Please add some kind of separator comment between each of these
> > parts
> > to make it easy for the reader to see this structure.
> 
> Sure, I've added a comment.
> 

Thanks.

> Attached is the revised patch for reference.  Since it just removes
> the uses of the %K and %G directives made redundant by the first
> patch in the series I'll go ahead and commit it as obvious in a day
> or so after patch 1 unless someone has further questions or requests
> for changes.

Please can you look into the "__artificial__" test coverage, and
address the line number thing above.

Dave


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PING][PATCH 2/4] remove %G and %K from calls in front end and middle end (PR 98512)
  2021-07-02  6:56                 ` Aldy Hernandez
@ 2021-07-02 21:53                   ` Jeff Law
  0 siblings, 0 replies; 44+ messages in thread
From: Jeff Law @ 2021-07-02 21:53 UTC (permalink / raw)
  To: Aldy Hernandez, Martin Sebor, David Malcolm, gcc-patches; +Cc: Jeff Law



On 7/2/2021 12:56 AM, Aldy Hernandez via Gcc-patches wrote:
>
>
> On 7/1/21 10:14 PM, Martin Sebor wrote:
>> On 6/30/21 5:35 PM, David Malcolm wrote:
>>> On Wed, 2021-06-30 at 13:45 -0600, Martin Sebor wrote:
>>>> On 6/30/21 9:39 AM, Martin Sebor wrote:
>
>>>> @@ -90,8 +90,8 @@ NOIPA void warn_g2 (struct A *p)
>>>>     g2 (p);
>>>>   }
>>>> -// { dg-message "inlined from 'g2'" "" { target *-*-* } 0 }
>>>> -// { dg-message "inlined from 'warn_g2'" "" { target *-*-* } 0 }
>>>> +// { dg-message "inlined from 'g2'" "note on line 93" { target 
>>>> *-*-* } 0 }
>>>> +// { dg-message "inlined from 'warn_g2'" "note on line 94" { 
>>>> target *-*-* } 0 }
>>>
>>> You've added descriptions to disambiguate all of the various directives
>>> on line 0, which is good, but I don't like the use of line numbers in
>>> the descriptions, since it will get very confusing if the numbering
>>> changes.
>>>
>>> Would it work to use the message text as the description e.g.
>>>
>>>    // { dg-message "inlined from 'warn_g2'" "inlined from 'warn_g2'" 
>>> { target *-*-* } 0 }
>>>
>>> or somesuch?
>>
>> It would certainly work, they're just informational labels printed
>> by DejaGnu when the assertions fail.  I added them to help me see
>> what they went with while working with the test.  I'm not concerned
>> about the line numbers changing.  If they do and someone notices,
>> they can update them, the same way they might want to if they
>> rename the functions they're inlined into.
>
> I agree with David.  Having too specific tests adds an extra 
> maintenance burden.  You may not mind updating all the line numbers 
> when anything changes, but others may certainly mind.
I agree in general, but if the thing we're testing for was a bug in the 
line number handling, then we probably do want to check the line #s.

jeff

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PING][PATCH 2/4] remove %G and %K from calls in front end and middle end (PR 98512)
  2021-07-02 20:52                 ` David Malcolm
@ 2021-07-02 22:15                   ` Martin Sebor
  0 siblings, 0 replies; 44+ messages in thread
From: Martin Sebor @ 2021-07-02 22:15 UTC (permalink / raw)
  To: David Malcolm, gcc-patches; +Cc: Jeff Law, Aldy Hernandez

[-- Attachment #1: Type: text/plain, Size: 2016 bytes --]

On 7/2/21 2:52 PM, David Malcolm wrote:
...
>>>> @@ -11425,10 +11425,10 @@ expand_expr_real_1 (tree exp, rtx
>>>> target, machine_mode tmode,
>>>>                                           DECL_ATTRIBUTES
>>>> (fndecl))) != NULL)
>>>>            {
>>>>              const char *ident = lang_hooks.decl_printable_name
>>>> (fndecl, 1);
>>>> -           warning_at (tree_nonartificial_location (exp),
>>>> +           warning_at (EXPR_LOCATION (exp),
>>>
>>> Are we preserving the existing behavior for
>>> __attribute__((__artificial__)) here?
>>> Is this behavior handled somewhere else in the patch kit?
>>
>> Yes.  The warning infrastructure (set_inlining_locations) uses
>> the location of the site into which the statement has been inlined
>> regardless of whether the inlined function is artificial.
> 
> Do we have test coverage for this, though?
> 
> [...]
>> Attached is the revised patch for reference.  Since it just removes
>> the uses of the %K and %G directives made redundant by the first
>> patch in the series I'll go ahead and commit it as obvious in a day
>> or so after patch 1 unless someone has further questions or requests
>> for changes.
> 
> Please can you look into the "__artificial__" test coverage, and
> address the line number thing above.

There are a bunch of tests for it but I couldn't find one that
verifies the inlining stack.  I always struggle with the DejaGnu
directives for these things (I couldn't get dg-multiline-output
to do what I wanted) so I cribbed the approach from
plugin/diagnostic-test-inlining-*.c.

Since I was changing the directives I got rid of the line numbers
from their comments but instead hardcoded them in the search pattern,
making the tests tighter.  That's a good thing but it does of course
mean that when new lines are added to the tests the directives will
fail and the patterns will need to be updated.

Attached is a patch with just the test I'm adding.

Martin

[-- Attachment #2: Wfree-nonheap-object-6.c.diff --]
[-- Type: text/x-patch, Size: 1834 bytes --]

diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-6.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-6.c
new file mode 100644
index 00000000000..c109558838b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-6.c
@@ -0,0 +1,49 @@
+/* Similar to Wfree-nonheap-object-5.c but with attribute artificial:
+   verify that warnings for the same call site from distinct callers
+   include the correct function names in the inlining stack.
+   { dg-do compile }
+   { dg-options "-O1 -Wall" } */
+
+struct A
+{
+  void *p;
+};
+
+__attribute__ ((always_inline, artificial))
+inline void f0 (struct A *p)
+{
+  __builtin_free (p->p);      // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+// Expect two instances of the text below:
+// { dg-regexp "In function 'f0'," "first f0 prefix" { target *-*-* } 0 }
+// { dg-regexp "In function 'f0'," "second f0 prefix" { target *-*-* } 0 }
+
+__attribute__ ((always_inline, artificial))
+inline void f1 (struct A *p) { f0 (p); }
+__attribute__ ((always_inline, artificial))
+inline void f2 (struct A *p) { f1 (p); }
+
+extern int array[];
+// Also expect two instances of the note:
+// { dg-regexp "declared here" "first note for array" { target *-*-* } .-2 }
+// { dg-regexp "declared here" "second note for array" { target *-*-* } .-3 }
+
+void foo (struct A *p)
+{
+  p->p = array + 1;
+  f0 (p);
+}
+
+// { dg-regexp " +inlined from 'foo' at \[^:\]+Wfree-nonheap-object-6.c:35:\\d+:" "inlined from foo" }
+
+
+void bar (struct A *p)
+{
+  p->p = array + 2;
+  f2 (p);
+}
+
+// { dg-regexp " +inlined from 'f1' at \[^:\]+Wfree-nonheap-object-6.c:23:\\d+," "inlined from f1" }
+// { dg-regexp " +inlined from 'f2' at \[^:\]+Wfree-nonheap-object-6.c:25:\\d+," "inlined from f2" }
+// { dg-regexp " +inlined from 'bar' at \[^:\]+Wfree-nonheap-object-6.c:44:\\d+:" "inlined from bar" }

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 4/4] remove %G and %K support from pretty printer and -Wformat (PR 98512)
  2021-06-30 23:38         ` [PATCH " David Malcolm
@ 2021-07-06 20:15           ` Martin Sebor
  2021-07-07  9:38             ` Andreas Schwab
  0 siblings, 1 reply; 44+ messages in thread
From: Martin Sebor @ 2021-07-06 20:15 UTC (permalink / raw)
  To: David Malcolm, gcc-patches

On 6/30/21 5:38 PM, David Malcolm wrote:
> On Thu, 2021-06-10 at 17:30 -0600, Martin Sebor wrote:
>> This final diff removes the handlers for %G and %K from the pretty
>> printer and the support for the directives from c-format.c so that
>> using them will be diagnosed.
> 
> I think this is OK once the other patches in the kit are approved.
> 
> Presumably if a new GCC tries to compile an older GCC that uses these
> codes, we'll get warnings about them, but IIRC those are ignored in the
> 1st stage of the bootstrap, right?

Yes, I believe so.  Sorry for the delay in responding, or if
I already answered the question.  I'm not sure which.

I have committed this in r12-2089.

Thanks

Martin

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 4/4] remove %G and %K support from pretty printer and -Wformat (PR 98512)
  2021-07-06 20:15           ` Martin Sebor
@ 2021-07-07  9:38             ` Andreas Schwab
  2021-07-07  9:47               ` Christophe Lyon
  0 siblings, 1 reply; 44+ messages in thread
From: Andreas Schwab @ 2021-07-07  9:38 UTC (permalink / raw)
  To: Martin Sebor via Gcc-patches

This broke bootstrap on aarch64.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 4/4] remove %G and %K support from pretty printer and -Wformat (PR 98512)
  2021-07-07  9:38             ` Andreas Schwab
@ 2021-07-07  9:47               ` Christophe Lyon
  2021-07-07 10:12                 ` Andreas Schwab
  0 siblings, 1 reply; 44+ messages in thread
From: Christophe Lyon @ 2021-07-07  9:47 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Martin Sebor via Gcc-patches

On Wed, Jul 7, 2021 at 11:38 AM Andreas Schwab <schwab@linux-m68k.org>
wrote:

> This broke bootstrap on aarch64.
>
>
This is https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101363

Christophe



> Andreas.
>
> --
> Andreas Schwab, schwab@linux-m68k.org
> GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
> "And now for something completely different."
>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH 4/4] remove %G and %K support from pretty printer and -Wformat (PR 98512)
  2021-07-07  9:47               ` Christophe Lyon
@ 2021-07-07 10:12                 ` Andreas Schwab
  0 siblings, 0 replies; 44+ messages in thread
From: Andreas Schwab @ 2021-07-07 10:12 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: Martin Sebor via Gcc-patches

On Jul 07 2021, Christophe Lyon wrote:

> On Wed, Jul 7, 2021 at 11:38 AM Andreas Schwab <schwab@linux-m68k.org>
> wrote:
>
>> This broke bootstrap on aarch64.
>>
>>
> This is https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101363

Nope.  This is a *bootstap* failure.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."

^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2021-07-07 10:12 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-19 18:58 [PATCH] improve warning suppression for inlined functions (PR 98465, 98512) Martin Sebor
2021-01-21 17:34 ` Florian Weimer
2021-01-21 18:24   ` Martin Sebor
2021-01-21 19:01     ` Florian Weimer
2021-01-21 20:24       ` Martin Sebor
2021-01-21 23:46 ` Martin Sebor
2021-01-30  2:56   ` PING " Martin Sebor
2021-02-06 17:12     ` PING 2 " Martin Sebor
2021-02-15  0:40       ` PING 3 " Martin Sebor
2021-05-19 13:41   ` David Malcolm
2021-06-10 23:24     ` [PATCH 0/4] improve warning suppression for inlined functions (PR 98512) Martin Sebor
2021-06-10 23:26       ` [PATCH 1/4] introduce diagnostic infrastructure changes " Martin Sebor
2021-06-11 17:04         ` David Malcolm
2021-06-15 23:00           ` Martin Sebor
2021-06-28 18:10             ` [PING][PATCH " Martin Sebor
2021-06-30 22:55             ` [PATCH " David Malcolm
2021-07-01 19:43               ` Martin Sebor
2021-06-10 23:27       ` [PATCH 2/4] remove %G and %K from calls in front end and middle end " Martin Sebor
2021-06-30 15:39         ` [PING][PATCH " Martin Sebor
2021-06-30 19:45           ` Martin Sebor
2021-06-30 23:35             ` David Malcolm
2021-07-01 20:14               ` Martin Sebor
2021-07-02  6:56                 ` Aldy Hernandez
2021-07-02 21:53                   ` Jeff Law
2021-07-02 20:52                 ` David Malcolm
2021-07-02 22:15                   ` Martin Sebor
2021-06-10 23:28       ` [PATCH 3/4] remove %K from error() calls in the aarch64/arm back ends " Martin Sebor
2021-06-11  7:53         ` Christophe Lyon
2021-06-11 13:10           ` Christophe Lyon
2021-06-11 14:47             ` Martin Sebor
2021-06-11  9:58         ` Richard Sandiford
2021-06-11 14:46           ` Martin Sebor
2021-06-30 19:56             ` Martin Sebor
2021-07-01  8:01               ` Christophe LYON
2021-07-01 14:45                 ` Martin Sebor
2021-06-10 23:30       ` [PATCH 4/4] remove %G and %K support from pretty printer and -Wformat " Martin Sebor
2021-06-30 16:17         ` [PING][PATCH " Martin Sebor
2021-06-30 23:38         ` [PATCH " David Malcolm
2021-07-06 20:15           ` Martin Sebor
2021-07-07  9:38             ` Andreas Schwab
2021-07-07  9:47               ` Christophe Lyon
2021-07-07 10:12                 ` Andreas Schwab
2021-02-19  4:28 ` [PATCH] improve warning suppression for inlined functions (PR 98465, 98512) Jeff Law
2021-02-19 10:57   ` Florian Weimer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).