--- gcc/c-family/c-common.h.jj	2022-01-20 11:30:45.329581659 +0100
+++ gcc/c-family/c-common.h	2022-01-20 19:36:35.195601009 +0100
@@ -853,7 +853,8 @@ extern void check_function_arguments_rec
 					      (void *, tree,
 					       unsigned HOST_WIDE_INT),
 					      void *, tree,
-					      unsigned HOST_WIDE_INT);
+					      unsigned HOST_WIDE_INT,
+					      opt_code);
 extern bool check_builtin_function_arguments (location_t, vec<location_t>,
 					      tree, tree, int, tree *);
 extern void check_function_format (const_tree, tree, int, tree *,
--- gcc/c-family/c-common.cc.jj	2022-01-20 11:30:45.329581659 +0100
+++ gcc/c-family/c-common.cc	2022-01-20 19:41:02.787901300 +0100
@@ -5592,7 +5592,7 @@ check_function_nonnull (nonnull_arg_ctx
       firstarg = 1;
       if (!closure)
 	check_function_arguments_recurse (check_nonnull_arg, &ctx, argarray[0],
-					  firstarg);
+					  firstarg, OPT_Wnonnull);
     }
 
   tree attrs = lookup_attribute ("nonnull", TYPE_ATTRIBUTES (ctx.fntype));
@@ -5611,7 +5611,7 @@ check_function_nonnull (nonnull_arg_ctx
   if (a != NULL_TREE)
     for (int i = firstarg; i < nargs; i++)
       check_function_arguments_recurse (check_nonnull_arg, &ctx, argarray[i],
-					i + 1);
+					i + 1, OPT_Wnonnull);
   else
     {
       /* Walk the argument list.  If we encounter an argument number we
@@ -5627,7 +5627,8 @@ check_function_nonnull (nonnull_arg_ctx
 
 	  if (a != NULL_TREE)
 	    check_function_arguments_recurse (check_nonnull_arg, &ctx,
-					      argarray[i], i + 1);
+					      argarray[i], i + 1,
+					      OPT_Wnonnull);
 	}
     }
   return ctx.warned_p;
@@ -6095,14 +6096,16 @@ check_function_arguments (location_t loc
 
 /* Generic argument checking recursion routine.  PARAM is the argument to
    be checked.  PARAM_NUM is the number of the argument.  CALLBACK is invoked
-   once the argument is resolved.  CTX is context for the callback.  */
+   once the argument is resolved.  CTX is context for the callback.
+   OPT is the warning for which this is done.  */
 void
 check_function_arguments_recurse (void (*callback)
 				  (void *, tree, unsigned HOST_WIDE_INT),
 				  void *ctx, tree param,
-				  unsigned HOST_WIDE_INT param_num)
+				  unsigned HOST_WIDE_INT param_num,
+				  opt_code opt)
 {
-  if (warning_suppressed_p (param))
+  if (opt != OPT_Wformat_ && warning_suppressed_p (param))
     return;
 
   if (CONVERT_EXPR_P (param)
@@ -6111,7 +6114,8 @@ check_function_arguments_recurse (void (
     {
       /* Strip coercion.  */
       check_function_arguments_recurse (callback, ctx,
-					TREE_OPERAND (param, 0), param_num);
+					TREE_OPERAND (param, 0), param_num,
+					opt);
       return;
     }
 
@@ -6148,7 +6152,8 @@ check_function_arguments_recurse (void (
 	      if (i == format_num)
 		{
 		  check_function_arguments_recurse (callback, ctx,
-						    inner_arg, param_num);
+						    inner_arg, param_num,
+						    opt);
 		  found_format_arg = true;
 		  break;
 		}
@@ -6170,10 +6175,10 @@ check_function_arguments_recurse (void (
 	  /* Check both halves of the conditional expression.  */
 	  check_function_arguments_recurse (callback, ctx,
 					    TREE_OPERAND (param, 1),
-					    param_num);
+					    param_num, opt);
 	  check_function_arguments_recurse (callback, ctx,
 					    TREE_OPERAND (param, 2),
-					    param_num);
+					    param_num, opt);
 	  return;
 	}
     }
--- gcc/c-family/c-format.cc.jj	2022-01-20 11:30:45.346581418 +0100
+++ gcc/c-family/c-format.cc	2022-01-20 19:46:21.021500071 +0100
@@ -1531,7 +1531,7 @@ check_format_info (function_format_info
   format_ctx.arglocs = arglocs;
 
   check_function_arguments_recurse (check_format_arg, &format_ctx,
-				    format_tree, arg_num);
+				    format_tree, arg_num, OPT_Wformat_);
 
   location_t loc = format_ctx.res->format_string_loc;
 
--- gcc/testsuite/c-c++-common/Wformat-pr104148.c.jj	2022-01-20 19:53:24.852638396 +0100
+++ gcc/testsuite/c-c++-common/Wformat-pr104148.c	2022-01-20 19:52:57.579015595 +0100
@@ -0,0 +1,33 @@
+/* PR c++/104148 */
+/* { dg-do compile } */
+/* { dg-options "-Wformat" } */
+
+char *foo (const char *) __attribute__((format_arg(1)));
+void bar (const char *, ...) __attribute__((format(printf, 1, 2)));
+
+void
+baz (int x)
+{
+  bar ("%ld", x);			/* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */
+  bar (x ? "%ld" : "%ld", x);		/* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */
+  bar (x ? "%ld" : "%lld", x);		/* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */
+					/* { dg-warning "format '%lld' expects argument of type 'long long int', but argument 2 has type 'int'" "" { target *-*-* } .-1 } */
+  bar (foo ("%ld"), x);			/* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */
+  bar (x ? foo ("%ld") : "%ld", x);	/* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */
+  bar (x ? foo ("%ld") : "%lld", x);	/* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */
+					/* { dg-warning "format '%lld' expects argument of type 'long long int', but argument 2 has type 'int'" "" { target *-*-* } .-1 } */
+  bar (foo (x ? "%ld" : "%ld"), x);	/* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */
+  bar (foo (x ? "%ld" : "%lld"), x);	/* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */
+					/* { dg-warning "format '%lld' expects argument of type 'long long int', but argument 2 has type 'int'" "" { target *-*-* } .-1 } */
+  bar (("%ld"), x);			/* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */
+  bar ((x ? "%ld" : "%ld"), x);		/* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */
+  bar ((x ? "%ld" : "%lld"), x);	/* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */
+					/* { dg-warning "format '%lld' expects argument of type 'long long int', but argument 2 has type 'int'" "" { target *-*-* } .-1 } */
+  bar ((foo ("%ld")), x);		/* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */
+  bar ((x ? foo ("%ld") : "%ld"), x);	/* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */
+  bar ((x ? foo ("%ld") : "%lld"), x);	/* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */
+					/* { dg-warning "format '%lld' expects argument of type 'long long int', but argument 2 has type 'int'" "" { target *-*-* } .-1 } */
+  bar ((foo (x ? "%ld" : "%ld")), x);	/* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */
+  bar ((foo (x ? "%ld" : "%lld")), x);	/* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */
+					/* { dg-warning "format '%lld' expects argument of type 'long long int', but argument 2 has type 'int'" "" { target *-*-* } .-1 } */
+}
