aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-family/c-common.cc25
-rw-r--r--gcc/c-family/c-common.h3
-rw-r--r--gcc/c-family/c-format.cc2
-rw-r--r--gcc/testsuite/c-c++-common/Wformat-pr104148.c33
4 files changed, 51 insertions, 12 deletions
diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index f56f6df..bf0749b 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -5592,7 +5592,7 @@ check_function_nonnull (nonnull_arg_ctx &ctx, int nargs, tree *argarray)
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 &ctx, int nargs, tree *argarray)
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 &ctx, int nargs, tree *argarray)
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, const_tree fndecl, const_tree fntype,
/* 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 (*callback)
{
/* 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 (*callback)
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 (*callback)
/* 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;
}
}
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 28c73fe..a8d6f82 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -853,7 +853,8 @@ extern void check_function_arguments_recurse (void (*)
(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 *,
diff --git a/gcc/c-family/c-format.cc b/gcc/c-family/c-format.cc
index a2affda..98f28c0 100644
--- a/gcc/c-family/c-format.cc
+++ b/gcc/c-family/c-format.cc
@@ -1531,7 +1531,7 @@ check_format_info (function_format_info *info, tree params,
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;
diff --git a/gcc/testsuite/c-c++-common/Wformat-pr104148.c b/gcc/testsuite/c-c++-common/Wformat-pr104148.c
new file mode 100644
index 0000000..6786463
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wformat-pr104148.c
@@ -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 } */
+}