+2015-05-21 Manuel López-Ibáñez <manu@gcc.gnu.org>
+
+ PR c/52952
+ * c-format.c (location_column_from_byte_offset): New.
+ (location_from_offset): New.
+ (struct format_wanted_type): Add offset_loc field.
+ (check_format_info): Move handling of location for extra arguments
+ closer to the point of warning.
+ (check_format_info_main): Pass the result of location_from_offset
+ to warning_at.
+ (format_type_warning): Pass the result of location_from_offset
+ to warning_at.
+
2015-05-20 Marek Polacek <polacek@redhat.com>
* c-omp.c (check_omp_for_incr_expr): Use BINARY_CLASS_P.
static const char *format_name (int format_num);
static int format_flags (int format_num);
+/* Given a string S of length LINE_WIDTH, find the visual column
+ corresponding to OFFSET bytes. */
+
+static unsigned int
+location_column_from_byte_offset (const char *s, int line_width,
+ unsigned int offset)
+{
+ const char * c = s;
+ if (*c != '"')
+ return 0;
+
+ c++, offset--;
+ while (offset > 0)
+ {
+ if (c - s >= line_width)
+ return 0;
+
+ switch (*c)
+ {
+ case '\\':
+ c++;
+ if (c - s >= line_width)
+ return 0;
+ switch (*c)
+ {
+ case '\\': case '\'': case '"': case '?':
+ case '(': case '{': case '[': case '%':
+ case 'a': case 'b': case 'f': case 'n':
+ case 'r': case 't': case 'v':
+ case 'e': case 'E':
+ c++, offset--;
+ break;
+
+ default:
+ return 0;
+ }
+ break;
+
+ case '"':
+ /* We found the end of the string too early. */
+ return 0;
+
+ default:
+ c++, offset--;
+ break;
+ }
+ }
+ return c - s;
+}
+
+/* Return a location that encodes the same location as LOC but shifted
+ by OFFSET bytes. */
+
+static location_t
+location_from_offset (location_t loc, int offset)
+{
+ gcc_checking_assert (offset >= 0);
+ if (linemap_location_from_macro_expansion_p (line_table, loc)
+ || offset < 0)
+ return loc;
+
+ expanded_location s = expand_location_to_spelling_point (loc);
+ int line_width;
+ const char *line = location_get_source_line (s, &line_width);
+ line += s.column - 1 ;
+ line_width -= s.column - 1;
+ unsigned int column =
+ location_column_from_byte_offset (line, line_width, (unsigned) offset);
+
+ return linemap_position_for_loc_and_offset (line_table, loc, column);
+}
+
/* Check that we have a pointer to a string suitable for use as a format.
The default is to check for a char type.
For objective-c dialects, this is extended to include references to string
tree param;
/* The argument number of that parameter. */
int arg_num;
+ /* The offset location of this argument with respect to the format
+ string location. */
+ unsigned int offset_loc;
/* The next type to check for this format conversion, or NULL if none. */
struct format_wanted_type *next;
} format_wanted_type;
format_tree, arg_num);
location_t loc = format_ctx.res->format_string_loc;
- if (res.extra_arg_loc == UNKNOWN_LOCATION)
- res.extra_arg_loc = loc;
if (res.number_non_literal > 0)
{
case of extra format arguments. */
if (res.number_extra_args > 0 && res.number_non_literal == 0
&& res.number_other == 0)
- warning_at (res.extra_arg_loc, OPT_Wformat_extra_args,
- "too many arguments for format");
+ {
+ if (res.extra_arg_loc == UNKNOWN_LOCATION)
+ res.extra_arg_loc = loc;
+ warning_at (res.extra_arg_loc, OPT_Wformat_extra_args,
+ "too many arguments for format");
+ }
if (res.number_dollar_extra_args > 0 && res.number_non_literal == 0
&& res.number_other == 0)
warning_at (loc, OPT_Wformat_extra_args, "unused arguments in $-style format");
continue;
if (*format_chars == 0)
{
- warning_at (format_string_loc, OPT_Wformat_,
+ warning_at (location_from_offset (format_string_loc,
+ format_chars - orig_format_chars),
+ OPT_Wformat_,
"spurious trailing %<%%%> in format");
continue;
}
*format_chars, NULL);
if (strchr (flag_chars, *format_chars) != 0)
{
- warning_at (format_string_loc, OPT_Wformat_,
+ warning_at (location_from_offset (format_string_loc,
+ format_chars + 1
+ - orig_format_chars),
+ OPT_Wformat_,
"repeated %s in format", _(s->name));
}
else
width_wanted_type.format_length = 1;
width_wanted_type.param = cur_param;
width_wanted_type.arg_num = arg_num;
+ width_wanted_type.offset_loc =
+ format_chars - orig_format_chars;
width_wanted_type.next = NULL;
if (last_wanted_type != 0)
last_wanted_type->next = &width_wanted_type;
flag_chars[i++] = fki->left_precision_char;
flag_chars[i] = 0;
if (!ISDIGIT (*format_chars))
- warning_at (format_string_loc, OPT_Wformat_,
+ warning_at (location_from_offset (format_string_loc,
+ format_chars - orig_format_chars),
+ OPT_Wformat_,
"empty left precision in %s format", fki->name);
while (ISDIGIT (*format_chars))
++format_chars;
precision_wanted_type.format_start = format_chars - 2;
precision_wanted_type.format_length = 2;
precision_wanted_type.arg_num = arg_num;
+ precision_wanted_type.offset_loc =
+ format_chars - orig_format_chars;
precision_wanted_type.next = NULL;
if (last_wanted_type != 0)
last_wanted_type->next = &precision_wanted_type;
{
if (!(fki->flags & (int) FMT_FLAG_EMPTY_PREC_OK)
&& !ISDIGIT (*format_chars))
- warning_at (format_string_loc, OPT_Wformat_,
+ warning_at (location_from_offset (format_string_loc,
+ format_chars - orig_format_chars),
+ OPT_Wformat_,
"empty precision in %s format", fki->name);
while (ISDIGIT (*format_chars))
++format_chars;
{
const format_flag_spec *s = get_flag_spec (flag_specs,
*format_chars, NULL);
- warning_at (format_string_loc, OPT_Wformat_,
+ warning_at (location_from_offset (format_string_loc,
+ format_chars
+ - orig_format_chars),
+ OPT_Wformat_,
"repeated %s in format", _(s->name));
}
else
|| (!(fki->flags & (int) FMT_FLAG_FANCY_PERCENT_OK)
&& format_char == '%'))
{
- warning_at (format_string_loc, OPT_Wformat_,
+ warning_at (location_from_offset (format_string_loc,
+ format_chars - orig_format_chars),
+ OPT_Wformat_,
"conversion lacks type at end of format");
continue;
}
if (fci->format_chars == 0)
{
if (ISGRAPH (format_char))
- warning_at (format_string_loc, OPT_Wformat_,
+ warning_at (location_from_offset (format_string_loc,
+ format_chars - orig_format_chars),
+ OPT_Wformat_,
"unknown conversion type character %qc in format",
format_char);
else
- warning_at (format_string_loc, OPT_Wformat_,
+ warning_at (location_from_offset (format_string_loc,
+ format_chars - orig_format_chars),
+ OPT_Wformat_,
"unknown conversion type character 0x%x in format",
format_char);
continue;
if (pedantic)
{
if (ADJ_STD (fci->std) > C_STD_VER)
- warning_at (format_string_loc, OPT_Wformat_,
+ warning_at (location_from_offset (format_string_loc,
+ format_chars - orig_format_chars),
+ OPT_Wformat_,
"%s does not support the %<%%%c%> %s format",
C_STD_NAME (fci->std), format_char, fki->name);
}
continue;
if (strchr (fci->flag_chars, flag_chars[i]) == 0)
{
- warning_at (format_string_loc,
- OPT_Wformat_, "%s used with %<%%%c%> %s format",
+ warning_at (location_from_offset (format_string_loc,
+ format_chars
+ - orig_format_chars),
+ OPT_Wformat_, "%s used with %<%%%c%> %s format",
_(s->name), format_char, fki->name);
d++;
continue;
++format_chars;
if (*format_chars != ']')
/* The end of the format string was reached. */
- warning_at (format_string_loc, OPT_Wformat_,
+ warning_at (location_from_offset (format_string_loc,
+ format_chars - orig_format_chars),
+ OPT_Wformat_,
"no closing %<]%> for %<%%[%> format");
}
wanted_type_std = fci->types[length_chars_val].std;
if (wanted_type == 0)
{
- warning_at (format_string_loc, OPT_Wformat_,
- "use of %qs length modifier with %qc type character",
+ warning_at (location_from_offset (format_string_loc,
+ format_chars - orig_format_chars),
+ OPT_Wformat_,
+ "use of %qs length modifier with %qc type character"
+ " has either no effect or undefined behavior",
length_chars, format_char);
/* Heuristic: skip one argument when an invalid length/type
combination is encountered. */
&& ADJ_STD (wanted_type_std) > ADJ_STD (fci->std))
{
if (ADJ_STD (wanted_type_std) > C_STD_VER)
- warning_at (format_string_loc, OPT_Wformat_,
+ warning_at (location_from_offset (format_string_loc,
+ format_chars - orig_format_chars),
+ OPT_Wformat_,
"%s does not support the %<%%%s%c%> %s format",
C_STD_NAME (wanted_type_std), length_chars,
format_char, fki->name);
wanted_type_ptr->arg_num = arg_num;
wanted_type_ptr->format_start = format_start;
wanted_type_ptr->format_length = format_chars - format_start;
+ wanted_type_ptr->offset_loc = format_chars - orig_format_chars;
wanted_type_ptr->next = NULL;
if (last_wanted_type != 0)
last_wanted_type->next = wanted_type_ptr;
}
if (format_chars - orig_format_chars != format_length)
- warning_at (format_string_loc, OPT_Wformat_contains_nul,
+ warning_at (location_from_offset (format_string_loc,
+ format_chars + 1 - orig_format_chars),
+ OPT_Wformat_contains_nul,
"embedded %<\\0%> in format");
if (info->first_arg_num != 0 && params != 0
&& has_operand_number <= 0)
int format_length = type->format_length;
int pointer_count = type->pointer_count;
int arg_num = type->arg_num;
+ unsigned int offset_loc = type->offset_loc;
char *p;
/* If ARG_TYPE is a typedef with a misleading name (for example,
p[pointer_count + 1] = 0;
}
+ loc = location_from_offset (loc, offset_loc);
+
if (wanted_type_name)
{
if (arg_type)
+2015-05-21 Manuel López-Ibáñez <manu@gcc.gnu.org>
+
+ PR c/52952
+ * gcc.dg/redecl-4.c: Update column numbers.
+ * gcc.dg/format/bitfld-1.c: Likewise.
+ * gcc.dg/format/attr-2.c: Likewise.
+ * gcc.dg/format/attr-6.c: Likewise.
+ * gcc.dg/format/attr-7.c (baz): Likewise.
+ * gcc.dg/format/asm_fprintf-1.c: Likewise.
+ * gcc.dg/format/attr-4.c: Likewise.
+ * gcc.dg/format/branch-1.c: Likewise.
+ * gcc.dg/format/c90-printf-1.c: Likewise. Add tests for column
+ locations within strings with embedded escape sequences.
+
2015-05-20 Alex Velenko <Alex.Velenko@arm.com>
* gcc.target/arm/thumb1-far-jump-2.c (r4): Added int in definition.
asm_fprintf ("%wd%wi%wo%wu%wx%wX", ll, ll, ull, ull, ull, ull);
/* Standard specifiers not accepted in asm_fprintf. */
- asm_fprintf ("%f\n", d); /* { dg-warning "16:format" "float" } */
- asm_fprintf ("%e\n", d); /* { dg-warning "16:format" "float" } */
- asm_fprintf ("%E\n", d); /* { dg-warning "16:format" "float" } */
- asm_fprintf ("%g\n", d); /* { dg-warning "16:format" "float" } */
- asm_fprintf ("%G\n", d); /* { dg-warning "16:format" "float" } */
- asm_fprintf ("%p\n", p); /* { dg-warning "16:format" "pointer" } */
- asm_fprintf ("%n\n", n); /* { dg-warning "16:format" "counter" } */
- asm_fprintf ("%hd\n", i); /* { dg-warning "16:format" "conversion" } */
+ asm_fprintf ("%f\n", d); /* { dg-warning "18:format" "float" } */
+ asm_fprintf ("%e\n", d); /* { dg-warning "18:format" "float" } */
+ asm_fprintf ("%E\n", d); /* { dg-warning "18:format" "float" } */
+ asm_fprintf ("%g\n", d); /* { dg-warning "18:format" "float" } */
+ asm_fprintf ("%G\n", d); /* { dg-warning "18:format" "float" } */
+ asm_fprintf ("%p\n", p); /* { dg-warning "18:format" "pointer" } */
+ asm_fprintf ("%n\n", n); /* { dg-warning "18:format" "counter" } */
+ asm_fprintf ("%hd\n", i); /* { dg-warning "18:format" "conversion" } */
/* Various tests of bad argument types. */
- asm_fprintf ("%d", l); /* { dg-warning "16:format" "bad argument types" } */
- asm_fprintf ("%wd", l); /* { dg-warning "16:format" "bad argument types" } */
- asm_fprintf ("%d", ll); /* { dg-warning "16:format" "bad argument types" } */
- asm_fprintf ("%*d\n", i1, i); /* { dg-warning "16:format" "bad * argument types" } */
- asm_fprintf ("%.*d\n", i2, i); /* { dg-warning "16:format" "bad * argument types" } */
- asm_fprintf ("%*.*ld\n", i1, i2, l); /* { dg-warning "16:format" "bad * argument types" } */
- asm_fprintf ("%ld", i); /* { dg-warning "16:format" "bad argument types" } */
- asm_fprintf ("%s", n); /* { dg-warning "16:format" "bad argument types" } */
+ asm_fprintf ("%d", l); /* { dg-warning "18:format" "bad argument types" } */
+ asm_fprintf ("%wd", l); /* { dg-warning "19:format" "bad argument types" } */
+ asm_fprintf ("%d", ll); /* { dg-warning "18:format" "bad argument types" } */
+ asm_fprintf ("%*d\n", i1, i); /* { dg-warning "18:format" "bad * argument types" } */
+ asm_fprintf ("%.*d\n", i2, i); /* { dg-warning "19:format" "bad * argument types" } */
+ asm_fprintf ("%*.*ld\n", i1, i2, l); /* { dg-warning "18:format" "bad * argument types" } */
+ asm_fprintf ("%ld", i); /* { dg-warning "19:format" "bad argument types" } */
+ asm_fprintf ("%s", n); /* { dg-warning "18:format" "bad argument types" } */
/* Wrong number of arguments. */
- asm_fprintf ("%d%d", i); /* { dg-warning "16:matching" "wrong number of args" } */
+ asm_fprintf ("%d%d", i); /* { dg-warning "20:matching" "wrong number of args" } */
asm_fprintf ("%d", i, i); /* { dg-warning "16:arguments" "wrong number of args" } */
/* Miscellaneous bogus constructions. */
asm_fprintf (""); /* { dg-warning "16:zero-length" "warning for empty format" } */
- asm_fprintf ("\0"); /* { dg-warning "16:embedded" "warning for embedded NUL" } */
- asm_fprintf ("%d\0", i); /* { dg-warning "16:embedded" "warning for embedded NUL" } */
- asm_fprintf ("%d\0%d", i, i); /* { dg-warning "16:embedded|too many" "warning for embedded NUL" } */
+ asm_fprintf ("\0"); /* { dg-warning "17:embedded" "warning for embedded NUL" } */
+ asm_fprintf ("%d\0", i); /* { dg-warning "19:embedded" "warning for embedded NUL" } */
+ asm_fprintf ("%d\0%d", i, i); /* { dg-warning "19:embedded|too many" "warning for embedded NUL" } */
asm_fprintf (NULL); /* { dg-warning "null" "null format string warning" } */
- asm_fprintf ("%"); /* { dg-warning "16:trailing" "trailing % warning" } */
- asm_fprintf ("%++d", i); /* { dg-warning "16:repeated" "repeated flag warning" } */
+ asm_fprintf ("%"); /* { dg-warning "17:trailing" "trailing % warning" } */
+ asm_fprintf ("%++d", i); /* { dg-warning "19:repeated" "repeated flag warning" } */
asm_fprintf ((const char *)L"foo"); /* { dg-warning "30:wide" "wide string" } */
asm_fprintf ("%s", (char *)0); /* { dg-warning "null" "%s with NULL" } */
/* Make sure we still get warnings for regular printf. */
- printf ("%d\n", ll); /* { dg-warning "11:format" "bad argument types" } */
+ printf ("%d\n", ll); /* { dg-warning "13:format" "bad argument types" } */
}
+/* { dg-warning "16:too many arguments for format" "too many arguments" { target *-*-* } 0 } */
foo (int i, int *ip, double d)
{
tformatprintf ("%d", i);
- tformatprintf ("%"); /* { dg-warning "18:format" "attribute format printf" } */
+ tformatprintf ("%"); /* { dg-warning "19:format" "attribute format printf" } */
tformat__printf__ ("%d", i);
tformat__printf__ ("%"); /* { dg-warning "format" "attribute format __printf__" } */
tformatscanf ("%d", ip);
tformatscanf ("%"); /* { dg-warning "format" "attribute format scanf" } */
tformat__scanf__ ("%d", ip);
- tformat__scanf__ ("%"); /* { dg-warning "format" "attribute format __scanf__" } */
+ tformat__scanf__ ("%"); /* { dg-warning "22:format" "attribute format __scanf__" } */
tformatstrftime ("%a");
tformatstrftime ("%"); /* { dg-warning "format" "attribute format strftime" } */
tformat__strftime__ ("%a");
baz (int i, int *ip, double d)
{
tformatprintf0 ("%d", i);
- tformatprintf0 ("%"); /* { dg-warning "19:format" "attribute format printf case 0" } */
+ tformatprintf0 ("%"); /* { dg-warning "20:format" "attribute format printf case 0" } */
tformatprintf1 ("%d", i);
tformatprintf1 ("%"); /* { dg-warning "format" "attribute format printf case 1" } */
tformatprintf2 ("%d", i);
void
foo (const char *s, int *p)
{
- scanf("%ld", p); /* { dg-warning "9:format" "implicit scanf" } */
+ scanf("%ld", p); /* { dg-warning "12:format" "implicit scanf" } */
/* { dg-warning "implicit" "implicit decl warning" { target *-*-* } 20 } */
}
{
(*tformatprintf0) ("%d", i);
(*tformatprintf0) ((*tformat_arg) ("%d"), i);
- (*tformatprintf0) ("%"); /* { dg-warning "22:format" "prefix" } */
+ (*tformatprintf0) ("%"); /* { dg-warning "23:format" "prefix" } */
(*tformatprintf0) ((*tformat_arg) ("%")); /* { dg-warning "format" "prefix" } */
(*tformatprintf1) ("%d", i);
(*tformatprintf1) ((*tformat_arg) ("%d"), i);
printf ("%ld%lu", x.u32, x.u32);
printf ("%ld%lu", x.s32, x.s32);
#endif
- printf ("%llu", x.u48); /* { dg-warning "11:has type '.*unsigned int:48'" } */
+ printf ("%llu", x.u48); /* { dg-warning "15:has type '.*unsigned int:48'" } */
printf ("%llu", (unsigned long long)x.u48);
}
foo (long l, int nfoo)
{
printf ((nfoo > 1) ? "%d foos" : "%d foo", nfoo);
- printf ((l > 1) ? "%d foos" /* { dg-warning "21:int" "wrong type in conditional expr" } */
- : "%d foo", l); /* { dg-warning "14:int" "wrong type in conditional expr" } */
- printf ((l > 1) ? "%ld foos" : "%d foo", l); /* { dg-warning "34:int" "wrong type in conditional expr" } */
- printf ((l > 1) ? "%d foos" : "%ld foo", l); /* { dg-warning "21:int" "wrong type in conditional expr" } */
+ printf ((l > 1) ? "%d foos" /* { dg-warning "23:int" "wrong type in conditional expr" } */
+ : "%d foo", l); /* { dg-warning "16:int" "wrong type in conditional expr" } */
+ printf ((l > 1) ? "%ld foos" : "%d foo", l); /* { dg-warning "36:int" "wrong type in conditional expr" } */
+ printf ((l > 1) ? "%d foos" : "%ld foo", l); /* { dg-warning "23:int" "wrong type in conditional expr" } */
/* Should allow one case to have extra arguments. */
printf ((nfoo > 1) ? "%d foos" : "1 foo", nfoo);
printf ((nfoo > 1) ? "many foos" : "1 foo", nfoo); /* { dg-warning "38:too many" "too many args in all branches" } */
printf ((nfoo > 1) ? "%d foos" : "", nfoo);
printf ((nfoo > 1) ? "%d foos" : ((nfoo > 0) ? "1 foo" : "no foos"), nfoo);
printf ((nfoo > 1) ? "%d foos" : ((nfoo > 0) ? "%d foo" : "%d foos"), nfoo);
- printf ((nfoo > 1) ? "%d foos" : ((nfoo > 0) ? "%d foo" : "%ld foos"), nfoo); /* { dg-warning "61:long int" "wrong type" } */
- printf ((nfoo > 1) ? "%ld foos" : ((nfoo > 0) ? "%d foo" : "%d foos"), nfoo); /* { dg-warning "24:long int" "wrong type" } */
- printf ((nfoo > 1) ? "%d foos" : ((nfoo > 0) ? "%ld foo" : "%d foos"), nfoo); /* { dg-warning "50:long int" "wrong type" } */
+ printf ((nfoo > 1) ? "%d foos" : ((nfoo > 0) ? "%d foo" : "%ld foos"), nfoo); /* { dg-warning "64:long int" "wrong type" } */
+ printf ((nfoo > 1) ? "%ld foos" : ((nfoo > 0) ? "%d foo" : "%d foos"), nfoo); /* { dg-warning "27:long int" "wrong type" } */
+ printf ((nfoo > 1) ? "%d foos" : ((nfoo > 0) ? "%ld foo" : "%d foos"), nfoo); /* { dg-warning "53:long int" "wrong type" } */
/* Extra arguments to NULL should be complained about. */
printf (0, "foo"); /* { dg-warning "14:too many" "NULL extra args" } */
/* { dg-warning "null" "null format arg" { target *-*-* } 26 } */
*/
printf ("%.e\n", d); /* { dg-bogus "precision" "bogus precision warning" } */
/* Bogus use of width. */
- printf ("%5n\n", n); /* { dg-warning "11:width" "width with %n" } */
+ printf ("%5n\n", n); /* { dg-warning "14:width" "width with %n" } */
/* Erroneous, ignored or pointless constructs with precision. */
/* Whether negative values for precision may be included in the format
string is not entirely clear; presume not, following Clive Feather's
proposed resolution to DR#220 against C99. In any case, such a
construct should be warned about.
*/
- printf ("%.-5d\n", i); /* { dg-warning "11:format|precision" "negative precision warning" } */
- printf ("%.-*d\n", i); /* { dg-warning "11:format" "broken %.-*d format" } */
- printf ("%.3c\n", i); /* { dg-warning "11:precision" "precision with %c" } */
- printf ("%.3p\n", p); /* { dg-warning "11:precision" "precision with %p" } */
- printf ("%.3n\n", n); /* { dg-warning "11:precision" "precision with %n" } */
+ printf ("%.-5d\n", i); /* { dg-warning "14:format|precision" "negative precision warning" } */
+ /* { dg-warning "too many arguments for format" "too many arguments" { target *-*-* } 44 } */
+ printf ("%.-*d\n", i); /* { dg-warning "14:format" "broken %.-*d format" } */
+ /* { dg-warning "too many arguments for format" "too many arguments" { target *-*-* } 46 } */
+ printf ("%.3c\n", i); /* { dg-warning "15:precision" "precision with %c" } */
+ printf ("%.3p\n", p); /* { dg-warning "15:precision" "precision with %p" } */
+ printf ("%.3n\n", n); /* { dg-warning "15:precision" "precision with %n" } */
/* Valid and invalid %% constructions. Some of the warning messages
are non-optimal, but they do detect the errorneous nature of the
format string.
*/
printf ("%%");
- printf ("%.3%"); /* { dg-warning "11:format" "bogus %%" } */
- printf ("%-%"); /* { dg-warning "11:format" "bogus %%" } */
- printf ("%-%\n"); /* { dg-warning "11:format" "bogus %%" } */
- printf ("%5%\n"); /* { dg-warning "11:format" "bogus %%" } */
- printf ("%h%\n"); /* { dg-warning "11:format" "bogus %%" } */
+ printf ("%.3%"); /* { dg-warning "14:type" "missing type" } */
+ /* { dg-warning "15:trailing" "bogus %%" { target *-*-* } 56 } */
+ printf ("%-%"); /* { dg-warning "13:type" "missing type" } */
+ /* { dg-warning "14:trailing" "bogus %%" { target *-*-* } 58 } */
+ printf ("%-%\n"); /* { dg-warning "13:format" "bogus %%" } */
+ /* { dg-warning "15:format" "bogus %%" { target *-*-* } 60 } */
+ printf ("%5%\n"); /* { dg-warning "13:format" "bogus %%" } */
+ /* { dg-warning "15:format" "bogus %%" { target *-*-* } 62 } */
+ printf ("%h%\n"); /* { dg-warning "13:format" "bogus %%" } */
+ /* { dg-warning "15:format" "bogus %%" { target *-*-* } 64 } */
/* Valid and invalid %h, %l, %L constructions. */
printf ("%hd", i);
printf ("%hi", i);
*/
printf ("%ho%hu%hx%hX", u, u, u, u);
printf ("%hn", hn);
- printf ("%hf", d); /* { dg-warning "11:length" "bad use of %h" } */
- printf ("%he", d); /* { dg-warning "11:length" "bad use of %h" } */
- printf ("%hE", d); /* { dg-warning "11:length" "bad use of %h" } */
- printf ("%hg", d); /* { dg-warning "11:length" "bad use of %h" } */
- printf ("%hG", d); /* { dg-warning "11:length" "bad use of %h" } */
- printf ("%hc", i); /* { dg-warning "11:length" "bad use of %h" } */
- printf ("%hs", s); /* { dg-warning "11:length" "bad use of %h" } */
- printf ("%hp", p); /* { dg-warning "11:length" "bad use of %h" } */
- printf ("%h"); /* { dg-warning "11:conversion lacks type" "bare %h" } */
- printf ("%h."); /* { dg-warning "11:conversion" "bogus %h." } */
- printf ("%ld%li%lo%lu%lx%lX", l, l, ul, ul, ul, ul);
- printf ("%ln", ln);
- printf ("%lf", d); /* { dg-warning "11:length|C" "bad use of %l" } */
- printf ("%le", d); /* { dg-warning "11:length|C" "bad use of %l" } */
- printf ("%lE", d); /* { dg-warning "11:length|C" "bad use of %l" } */
- printf ("%lg", d); /* { dg-warning "11:length|C" "bad use of %l" } */
- printf ("%lG", d); /* { dg-warning "11:length|C" "bad use of %l" } */
- printf ("%lp", p); /* { dg-warning "11:length|C" "bad use of %l" } */
+ printf (" %hf", d); /* { dg-warning "15:length" "bad use of %h" } */
+ printf (" %he", d); /* { dg-warning "15:length" "bad use of %h" } */
+ printf (" %hE", d); /* { dg-warning "15:length" "bad use of %h" } */
+ printf (" %hg", d); /* { dg-warning "15:length" "bad use of %h" } */
+ printf (" %hG", d); /* { dg-warning "15:length" "bad use of %h" } */
+ printf (" %hc", i); /* { dg-warning "15:length" "bad use of %h" } */
+ printf (" %hs", s); /* { dg-warning "15:length" "bad use of %h" } */
+ printf (" %hp", p); /* { dg-warning "15:length" "bad use of %h" } */
+ printf (" %h"); /* { dg-warning "14:conversion lacks type" "bare %h" } */
+ printf (" %h."); /* { dg-warning "15:conversion" "bogus %h." } */
+ printf (" %ld%li%lo%lu%lx%lX", l, l, ul, ul, ul, ul);
+ printf (" %ln", ln);
+ printf (" %lf", d); /* { dg-warning "15:length|C" "bad use of %l" } */
+ printf (" %le", d); /* { dg-warning "15:length|C" "bad use of %l" } */
+ printf (" %lE", d); /* { dg-warning "15:length|C" "bad use of %l" } */
+ printf (" %lg", d); /* { dg-warning "15:length|C" "bad use of %l" } */
+ printf (" %lG", d); /* { dg-warning "15:length|C" "bad use of %l" } */
+ printf (" %lp", p); /* { dg-warning "15:length|C" "bad use of %l" } */
/* These next two were added in C94, but should be objected to in C90.
For the first one, GCC has wanted wchar_t instead of the correct C94
and C99 wint_t.
*/
- printf ("%lc", lc); /* { dg-warning "11:length|C" "C90 bad use of %l" } */
- printf ("%ls", ls); /* { dg-warning "11:length|C" "C90 bad use of %l" } */
+ printf ("%lc", lc); /* { dg-warning "14:length|C" "C90 bad use of %l" } */
+ printf ("%ls", ls); /* { dg-warning "14:length|C" "C90 bad use of %l" } */
/* These uses of %L are legitimate, though GCC has wrongly warned for
them in the past.
*/
/* These next six are accepted by GCC as referring to long long,
but -pedantic correctly warns.
*/
- printf ("%Ld", ll); /* { dg-warning "11:does not support" "bad use of %L" } */
- printf ("%Li", ll); /* { dg-warning "11:does not support" "bad use of %L" } */
- printf ("%Lo", ull); /* { dg-warning "11:does not support" "bad use of %L" } */
- printf ("%Lu", ull); /* { dg-warning "11:does not support" "bad use of %L" } */
- printf ("%Lx", ull); /* { dg-warning "11:does not support" "bad use of %L" } */
- printf ("%LX", ull); /* { dg-warning "11:does not support" "bad use of %L" } */
- printf ("%Lc", i); /* { dg-warning "11:length" "bad use of %L" } */
- printf ("%Ls", s); /* { dg-warning "11:length" "bad use of %L" } */
- printf ("%Lp", p); /* { dg-warning "11:length" "bad use of %L" } */
- printf ("%Ln", n); /* { dg-warning "11:length" "bad use of %L" } */
+ printf ("%Ld", ll); /* { dg-warning "14:does not support" "bad use of %L" } */
+ printf ("%Li", ll); /* { dg-warning "14:does not support" "bad use of %L" } */
+ printf ("%Lo", ull); /* { dg-warning "14:does not support" "bad use of %L" } */
+ printf ("%Lu", ull); /* { dg-warning "14:does not support" "bad use of %L" } */
+ printf ("%Lx", ull); /* { dg-warning "14:does not support" "bad use of %L" } */
+ printf ("%LX", ull); /* { dg-warning "14:does not support" "bad use of %L" } */
+ printf ("%Lc", i); /* { dg-warning "14:length" "bad use of %L" } */
+ printf ("%Ls", s); /* { dg-warning "14:length" "bad use of %L" } */
+ printf ("%Lp", p); /* { dg-warning "14:length" "bad use of %L" } */
+ printf ("%Ln", n); /* { dg-warning "14:length" "bad use of %L" } */
/* Valid uses of each bare conversion. */
printf ("%d%i%o%u%x%X%f%e%E%g%G%c%s%p%n%%", i, i, u, u, u, u, d, d, d, d, d,
i, s, p, n);
/* Uses of the - flag (valid on all non-%, non-n conversions). */
printf ("%-d%-i%-o%-u%-x%-X%-f%-e%-E%-g%-G%-c%-s%-p", i, i, u, u, u, u,
d, d, d, d, d, i, s, p);
- printf ("%-n", n); /* { dg-warning "11:flag" "bad use of %-n" } */
+ printf ("%-n", n); /* { dg-warning "14:flag" "bad use of %-n" } */
/* Uses of the + flag (valid on signed conversions only). */
printf ("%+d%+i%+f%+e%+E%+g%+G\n", i, i, d, d, d, d, d);
- printf ("%+o", u); /* { dg-warning "11:flag" "bad use of + flag" } */
- printf ("%+u", u); /* { dg-warning "11:flag" "bad use of + flag" } */
- printf ("%+x", u); /* { dg-warning "11:flag" "bad use of + flag" } */
- printf ("%+X", u); /* { dg-warning "11:flag" "bad use of + flag" } */
- printf ("%+c", i); /* { dg-warning "11:flag" "bad use of + flag" } */
- printf ("%+s", s); /* { dg-warning "11:flag" "bad use of + flag" } */
- printf ("%+p", p); /* { dg-warning "11:flag" "bad use of + flag" } */
- printf ("%+n", n); /* { dg-warning "11:flag" "bad use of + flag" } */
+ printf ("%+o", u); /* { dg-warning "14:flag" "bad use of + flag" } */
+ printf ("%+u", u); /* { dg-warning "14:flag" "bad use of + flag" } */
+ printf ("%+x", u); /* { dg-warning "14:flag" "bad use of + flag" } */
+ printf ("%+X", u); /* { dg-warning "14:flag" "bad use of + flag" } */
+ printf ("%+c", i); /* { dg-warning "14:flag" "bad use of + flag" } */
+ printf ("%+s", s); /* { dg-warning "14:flag" "bad use of + flag" } */
+ printf ("%+p", p); /* { dg-warning "14:flag" "bad use of + flag" } */
+ printf ("%+n", n); /* { dg-warning "14:flag" "bad use of + flag" } */
/* Uses of the space flag (valid on signed conversions only, and ignored
with +).
*/
printf ("% +d", i); /* { dg-warning "11:use of both|ignored" "use of space and + flags" } */
printf ("%+ d", i); /* { dg-warning "11:use of both|ignored" "use of space and + flags" } */
printf ("% d% i% f% e% E% g% G\n", i, i, d, d, d, d, d);
- printf ("% o", u); /* { dg-warning "11:flag" "bad use of space flag" } */
- printf ("% u", u); /* { dg-warning "11:flag" "bad use of space flag" } */
- printf ("% x", u); /* { dg-warning "11:flag" "bad use of space flag" } */
- printf ("% X", u); /* { dg-warning "11:flag" "bad use of space flag" } */
- printf ("% c", i); /* { dg-warning "11:flag" "bad use of space flag" } */
- printf ("% s", s); /* { dg-warning "11:flag" "bad use of space flag" } */
- printf ("% p", p); /* { dg-warning "11:flag" "bad use of space flag" } */
- printf ("% n", n); /* { dg-warning "11:flag" "bad use of space flag" } */
+ printf ("% o", u); /* { dg-warning "14:flag" "bad use of space flag" } */
+ printf ("% u", u); /* { dg-warning "14:flag" "bad use of space flag" } */
+ printf ("% x", u); /* { dg-warning "14:flag" "bad use of space flag" } */
+ printf ("% X", u); /* { dg-warning "14:flag" "bad use of space flag" } */
+ printf ("% c", i); /* { dg-warning "14:flag" "bad use of space flag" } */
+ printf ("% s", s); /* { dg-warning "14:flag" "bad use of space flag" } */
+ printf ("% p", p); /* { dg-warning "14:flag" "bad use of space flag" } */
+ printf ("% n", n); /* { dg-warning "14:flag" "bad use of space flag" } */
/* Uses of the # flag. */
printf ("%#o%#x%#X%#e%#E%#f%#g%#G", u, u, u, d, d, d, d, d);
- printf ("%#d", i); /* { dg-warning "11:flag" "bad use of # flag" } */
- printf ("%#i", i); /* { dg-warning "11:flag" "bad use of # flag" } */
- printf ("%#u", u); /* { dg-warning "11:flag" "bad use of # flag" } */
- printf ("%#c", i); /* { dg-warning "11:flag" "bad use of # flag" } */
- printf ("%#s", s); /* { dg-warning "11:flag" "bad use of # flag" } */
- printf ("%#p", p); /* { dg-warning "11:flag" "bad use of # flag" } */
- printf ("%#n", n); /* { dg-warning "11:flag" "bad use of # flag" } */
+ printf ("%#d", i); /* { dg-warning "14:flag" "bad use of # flag" } */
+ printf ("%#i", i); /* { dg-warning "14:flag" "bad use of # flag" } */
+ printf ("%#u", u); /* { dg-warning "14:flag" "bad use of # flag" } */
+ printf ("%#c", i); /* { dg-warning "14:flag" "bad use of # flag" } */
+ printf ("%#s", s); /* { dg-warning "14:flag" "bad use of # flag" } */
+ printf ("%#p", p); /* { dg-warning "14:flag" "bad use of # flag" } */
+ printf ("%#n", n); /* { dg-warning "14:flag" "bad use of # flag" } */
/* Uses of the 0 flag. */
printf ("%08d%08i%08o%08u%08x%08X%08e%08E%08f%08g%08G", i, i, u, u, u, u,
d, d, d, d, d);
- printf ("%0c", i); /* { dg-warning "11:flag" "bad use of 0 flag" } */
- printf ("%0s", s); /* { dg-warning "11:flag" "bad use of 0 flag" } */
- printf ("%0p", p); /* { dg-warning "11:flag" "bad use of 0 flag" } */
- printf ("%0n", n); /* { dg-warning "11:flag" "bad use of 0 flag" } */
+ printf ("%0c", i); /* { dg-warning "14:flag" "bad use of 0 flag" } */
+ printf ("%0s", s); /* { dg-warning "14:flag" "bad use of 0 flag" } */
+ printf ("%0p", p); /* { dg-warning "14:flag" "bad use of 0 flag" } */
+ printf ("%0n", n); /* { dg-warning "14:flag" "bad use of 0 flag" } */
/* 0 flag ignored with precision for certain types, not others. */
printf ("%08.5d", i); /* { dg-warning "11:ignored" "0 flag ignored with precision" } */
printf ("%08.5i", i); /* { dg-warning "11:ignored" "0 flag ignored with precision" } */
printf ("%-08g", d); /* { dg-warning "11:flags|ignored" "0 flag ignored with - flag" } */
printf ("%-08G", d); /* { dg-warning "11:flags|ignored" "0 flag ignored with - flag" } */
/* Various tests of bad argument types. */
- printf ("%d", l); /* { dg-warning "11:format" "bad argument types" } */
- printf ("%*.*d", l, i2, i); /* { dg-warning "11:field" "bad * argument types" } */
- printf ("%*.*d", i1, l, i); /* { dg-warning "11:field" "bad * argument types" } */
- printf ("%ld", i); /* { dg-warning "11:format" "bad argument types" } */
- printf ("%s", n); /* { dg-warning "11:format" "bad argument types" } */
- printf ("%p", i); /* { dg-warning "11:format" "bad argument types" } */
- printf ("%n", p); /* { dg-warning "11:format" "bad argument types" } */
+ printf ("%d", l); /* { dg-warning "13:format" "bad argument types" } */
+ printf ("%*.*d", l, i2, i); /* { dg-warning "13:field" "bad * argument types" } */
+ printf ("%*.*d", i1, l, i); /* { dg-warning "15:field" "bad * argument types" } */
+ printf ("%ld", i); /* { dg-warning "14:format" "bad argument types" } */
+ printf ("%s", n); /* { dg-warning "13:format" "bad argument types" } */
+ printf ("%p", i); /* { dg-warning "13:format" "bad argument types" } */
+ printf ("%n", p); /* { dg-warning "13:format" "bad argument types" } */
/* With -pedantic, we want some further checks for pointer targets:
%p should allow only pointers to void (possibly qualified) and
to character types (possibly qualified), but not function pointers
char * or unsigned char * being passed to %hhn, even if strictly
legitimate by the standard.)
*/
- printf ("%p", foo); /* { dg-warning "11:format" "bad argument types" } */
- printf ("%n", un); /* { dg-warning "11:format" "bad argument types" } */
- printf ("%p", n); /* { dg-warning "11:format" "bad argument types" } */
+ printf ("%p", foo); /* { dg-warning "13:format" "bad argument types" } */
+ printf ("%n", un); /* { dg-warning "13:format" "bad argument types" } */
+ printf ("%p", n); /* { dg-warning "13:format" "bad argument types" } */
/* Allow character pointers with %p. */
printf ("%p%p%p%p", s, ss, us, css);
/* %s allows any character type. */
and seems useful to keep, even if some standard versions might be
read to permit it.
*/
- printf ("%s", p); /* { dg-warning "11:format" "bad argument types" } */
+ printf ("%s", p); /* { dg-warning "13:format" "bad argument types" } */
/* The historical behavior is to allow signed / unsigned types
interchangeably as arguments. For values representable in both types,
such usage may be correct. For now preserve the behavior of GCC
*/
printf ("%*.*d", u1, u2, i);
/* Wrong number of arguments. */
- printf ("%d%d", i); /* { dg-warning "11:matching" "wrong number of args" } */
+ printf ("%d%d", i); /* { dg-warning "15:matching" "wrong number of args" } */
printf ("%d", i, i); /* { dg-warning "11:arguments" "wrong number of args" } */
/* Miscellaneous bogus constructions. */
printf (""); /* { dg-warning "11:zero-length" "warning for empty format" } */
- printf ("\0"); /* { dg-warning "11:embedded" "warning for embedded NUL" } */
- printf ("%d\0", i); /* { dg-warning "11:embedded" "warning for embedded NUL" } */
- printf ("%d\0%d", i, i); /* { dg-warning "11:embedded|too many" "warning for embedded NUL" } */
+ printf ("\0"); /* { dg-warning "12:embedded" "warning for embedded NUL" } */
+ printf ("%d\0", i); /* { dg-warning "14:embedded" "warning for embedded NUL" } */
+ printf ("%d\0%d", i, i); /* { dg-warning "embedded|too many" "warning for embedded NUL" } */
printf (NULL); /* { dg-warning "3:null" "null format string warning" } */
- printf ("%"); /* { dg-warning "11:trailing" "trailing % warning" } */
- printf ("%++d", i); /* { dg-warning "11:repeated" "repeated flag warning" } */
+ printf ("%"); /* { dg-warning "12:trailing" "trailing % warning" } */
+ printf ("%++d", i); /* { dg-warning "14:repeated" "repeated flag warning" } */
printf ("%n", cn); /* { dg-warning "3:constant" "%n with const" } */
printf ((const char *)L"foo"); /* { dg-warning "25:wide" "wide string" } */
printf ("%n", (int *)0); /* { dg-warning "3:null" "%n with NULL" } */
printf ("%s", (char *)0); /* { dg-warning "3:null" "%s with NULL" } */
+ /* Test for correct column locations within strings with embedded
+ escape sequences. */
+ printf ("\\\a\n \"\t%5n\n", n); /* { dg-warning "25:width" "width with %n" } */
+ printf ("\\a\\n%5n\n", n); /* { dg-warning "20:width" "width with %n" } */
}
/* Should get format warnings even though the built-in declaration
isn't "visible". */
printf (
- "%s", 1); /* { dg-warning "6:format" } */
+ "%s", 1); /* { dg-warning "8:format" } */
/* The type of strcmp here should have no prototype. */
if (0)
strcmp (1);