From patchwork Wed May 20 08:15:35 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?TWFudWVsIEzDs3Blei1JYsOhw7Fleg==?= X-Patchwork-Id: 474208 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 6F7FB1400B7 for ; Wed, 20 May 2015 18:16:35 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=D4L2syM0; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=BocYztJVD8u3N/rmvKaFy31gnmkVrAxRagsgdX/tXunbhj s/enHvMa+jKC9kmz8sELZroKw0GHF5YlvbKLtjUU6Zp7QKwz90X7dgg698aR6S7l P+9wmDUSB5NvXALAntcWeTWlnliwp98AcDt8Y9JnpILgEIUkio6un7KcRBJog= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=wWSUTAXMerxS93B7D1VENp/XaAE=; b=D4L2syM0UlYwxF+DWkFk 4VQCOYHm9dU2ItvnsPJqHn9ogFnH3u3FuJEb8Ak2UALfF0l1xtq59oc6eot0Fios 1uTIVePyCtpEixyR1BwQZJiaKjLZ+XxR4QDe58CM88ovuuL5D0GUDZf9nx1hJm9Y /RGEvhiZBoWQfykVWXUvKq4= Received: (qmail 73589 invoked by alias); 20 May 2015 08:16:26 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 73573 invoked by uid 89); 20 May 2015 08:16:25 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.1 required=5.0 tests=AWL, BAYES_50, FREEMAIL_FROM, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=no version=3.3.2 X-HELO: mail-wg0-f45.google.com Received: from mail-wg0-f45.google.com (HELO mail-wg0-f45.google.com) (74.125.82.45) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Wed, 20 May 2015 08:16:19 +0000 Received: by wgjc11 with SMTP id c11so44211388wgj.0 for ; Wed, 20 May 2015 01:16:16 -0700 (PDT) X-Received: by 10.180.219.42 with SMTP id pl10mr39606822wic.70.1432109776319; Wed, 20 May 2015 01:16:16 -0700 (PDT) MIME-Version: 1.0 Received: by 10.28.103.6 with HTTP; Wed, 20 May 2015 01:15:35 -0700 (PDT) From: =?UTF-8?B?TWFudWVsIEzDs3Blei1JYsOhw7Fleg==?= Date: Wed, 20 May 2015 10:15:35 +0200 Message-ID: Subject: [PR c/52952] More precise locations within format strings To: Gcc Patch List , "Joseph S. Myers" This is a new version of the patch submitted here: https://gcc.gnu.org/ml/gcc-patches/2014-11/msg00663.html but handling (some) escape sequences. I could not figure out a way to re-use the code from libcpp for this, thus I implemented a simple function that given a string and offset in bytes, it computes the visual column corresponding to that offset. The function is very conservative: As soon as something unknown or inconsistent is detected, it returns zero, thus preserving the current behavior. This also preserves the current behavior for non-concatenated tokens. Bootstrapped and regression tested on x86_64-linux-gnu. OK? gcc/testsuite/ChangeLog: 2015-05-20 Manuel López-Ibáñez 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. gcc/c-family/ChangeLog: 2015-05-20 Manuel López-Ibáñez 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_arg): Set offset_is_invalid. (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. Index: gcc/c-family/c-format.c =================================================================== --- gcc/c-family/c-format.c (revision 223371) +++ gcc/c-family/c-format.c (working copy) @@ -76,10 +76,90 @@ static bool cmp_attribs (const char *tat static int first_target_format_type; static const char *format_name (int format_num); static int format_flags (int format_num); +/* FIXME: This indicates that loc is not the location of the format + string, thus computing an offset is useless. This happens, for + example, when the format string is a constant array. + Unfortunately, GCC does not keep track of the location of the + initializer of the array yet. */ +static bool offset_is_invalid; + +/* 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 (offset_is_invalid + || 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 objects validated by objc_string_ref_type_p (). Targets may also provide a string object type that can be used within c and @@ -388,10 +468,13 @@ typedef struct format_wanted_type int format_length; /* The actual parameter to check against the wanted type. */ 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; /* Convenience macro for format_length_info meaning unused. */ @@ -1356,12 +1439,10 @@ check_format_info (function_format_info check_function_arguments_recurse (check_format_arg, &format_ctx, 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) { /* Functions taking a va_list normally pass a non-literal format string. These functions typically are declared with @@ -1403,12 +1484,16 @@ check_format_info (function_format_info arguments, but was otherwise OK (either non-literal or checked OK). If the format is an empty string, this should be counted similarly to the 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"); if (res.number_empty > 0 && res.number_non_literal == 0 && res.number_other == 0) @@ -1502,10 +1587,11 @@ check_format_arg (void *ctx, tree format { res->number_non_literal++; return; } res->format_string_loc = EXPR_LOC_OR_LOC (format_tree, input_location); + offset_is_invalid = false; format_tree = TREE_OPERAND (format_tree, 0); if (format_types[info->format_type].flags & (int) FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL) { bool objc_str = (info->format_type == gcc_objc_string_format_type); @@ -1555,10 +1641,11 @@ check_format_arg (void *ctx, tree format /* Extract the string constant initializer. Note that this may include a trailing NUL character that is not in the array (e.g. const char a[3] = "foo";). */ array_size = DECL_SIZE_UNIT (format_tree); format_tree = array_init; + offset_is_invalid = true; } if (TREE_CODE (format_tree) != STRING_CST) { res->number_non_literal++; return; @@ -1680,11 +1767,13 @@ check_format_info_main (format_check_res if (*format_chars++ != '%') 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; } if (*format_chars == '%') { @@ -1725,11 +1814,14 @@ check_format_info_main (format_check_res { const format_flag_spec *s = get_flag_spec (flag_specs, *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 { i = strlen (flag_chars); @@ -1805,10 +1897,12 @@ check_format_info_main (format_check_res width_wanted_type.kind = CF_KIND_FIELD_WIDTH; width_wanted_type.format_start = format_chars - 1; 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; if (first_wanted_type == 0) first_wanted_type = &width_wanted_type; @@ -1847,11 +1941,13 @@ check_format_info_main (format_check_res ++format_chars; i = strlen (flag_chars); 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; } @@ -1912,10 +2008,12 @@ check_format_info_main (format_check_res precision_wanted_type.kind = CF_KIND_FIELD_PRECISION; precision_wanted_type.param = cur_param; 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 (first_wanted_type == 0) first_wanted_type = &precision_wanted_type; @@ -1924,11 +2022,13 @@ check_format_info_main (format_check_res } else { 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; } } @@ -2010,11 +2110,14 @@ check_format_info_main (format_check_res { if (strchr (flag_chars, *format_chars) != 0) { 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 { i = strlen (flag_chars); @@ -2028,11 +2131,13 @@ check_format_info_main (format_check_res format_char = *format_chars; if (format_char == 0 || (!(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; } format_chars++; fci = fki->conversion_specs; @@ -2040,23 +2145,29 @@ check_format_info_main (format_check_res && strchr (fci->format_chars, format_char) == 0) ++fci; 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); } /* Validate the individual flags used, removing any that are invalid. */ @@ -2069,12 +2180,14 @@ check_format_info_main (format_check_res flag_chars[i - d] = flag_chars[i]; if (flag_chars[i] == fki->length_code_char) 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; } if (pedantic) @@ -2184,11 +2297,13 @@ check_format_info_main (format_check_res ++format_chars; while (*format_chars && *format_chars != ']') ++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 = 0; wanted_type_name = 0; @@ -2198,12 +2313,15 @@ check_format_info_main (format_check_res ? *fci->types[length_chars_val].type : 0); wanted_type_name = fci->types[length_chars_val].name; 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. */ arg_num++; if (params != 0) @@ -2216,11 +2334,13 @@ check_format_info_main (format_check_res have been warned for. */ && ADJ_STD (wanted_type_std) > ADJ_STD (length_chars_std) && 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); } } @@ -2301,10 +2421,11 @@ check_format_info_main (format_check_res wanted_type_ptr->kind = CF_KIND_FORMAT; wanted_type_ptr->param = cur_param; 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 (first_wanted_type == 0) first_wanted_type = wanted_type_ptr; @@ -2325,11 +2446,13 @@ check_format_info_main (format_check_res if (first_wanted_type != 0) check_format_types (format_string_loc, first_wanted_type); } 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) { res->number_other--; @@ -2533,10 +2656,11 @@ format_type_warning (location_t loc, for const char *wanted_type_name = type->wanted_type_name; const char *format_start = type->format_start; 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, size_t but not the standard size_t expected by printf %zu), avoid printing the typedef name. */ @@ -2566,10 +2690,12 @@ format_type_warning (location_t loc, for p[0] = ' '; memset (p + 1, '*', pointer_count); p[pointer_count + 1] = 0; } + loc = location_from_offset (loc, offset_loc); + if (wanted_type_name) { if (arg_type) warning_at (loc, OPT_Wformat_, "%s %<%s%.*s%> expects argument of type %<%s%s%>, " Index: gcc/testsuite/gcc.dg/redecl-4.c =================================================================== --- gcc/testsuite/gcc.dg/redecl-4.c (revision 223371) +++ gcc/testsuite/gcc.dg/redecl-4.c (working copy) @@ -13,11 +13,11 @@ f (void) int printf (const char *, ...); int strcmp (); /* 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); /* Likewise, implicitly declared memcmp. */ if (0) Index: gcc/testsuite/gcc.dg/format/bitfld-1.c =================================================================== --- gcc/testsuite/gcc.dg/format/bitfld-1.c (revision 223371) +++ gcc/testsuite/gcc.dg/format/bitfld-1.c (working copy) @@ -44,8 +44,8 @@ foo (void) printf ("%d%u", x.s32, x.s32); #else 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); } Index: gcc/testsuite/gcc.dg/format/attr-2.c =================================================================== --- gcc/testsuite/gcc.dg/format/attr-2.c (revision 223371) +++ gcc/testsuite/gcc.dg/format/attr-2.c (working copy) @@ -28,17 +28,17 @@ extern char *t__format_arg__ (const char void 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"); tformat__strftime__ ("%"); /* { dg-warning "format" "attribute format __strftime__" } */ tformatstrfmon ("%n", d); Index: gcc/testsuite/gcc.dg/format/attr-6.c =================================================================== --- gcc/testsuite/gcc.dg/format/attr-6.c (revision 223371) +++ gcc/testsuite/gcc.dg/format/attr-6.c (working copy) @@ -15,8 +15,8 @@ of it as a built-in function. */ 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 } */ } Index: gcc/testsuite/gcc.dg/format/attr-7.c =================================================================== --- gcc/testsuite/gcc.dg/format/attr-7.c (revision 223371) +++ gcc/testsuite/gcc.dg/format/attr-7.c (working copy) @@ -16,11 +16,11 @@ char * (__attribute__((format_arg(1))) * void baz (int i) { (*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); (*tformatprintf1) ("%"); /* { dg-warning "format" "postfix" } */ (*tformatprintf1) ((*tformat_arg) ("%")); /* { dg-warning "format" "postfix" } */ Index: gcc/testsuite/gcc.dg/format/asm_fprintf-1.c =================================================================== --- gcc/testsuite/gcc.dg/format/asm_fprintf-1.c (revision 223371) +++ gcc/testsuite/gcc.dg/format/asm_fprintf-1.c (working copy) @@ -40,41 +40,42 @@ foo (int i, int i1, int i2, unsigned int asm_fprintf ("%O%R%I%L%U%@"); asm_fprintf ("%r", i); 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 } */ Index: gcc/testsuite/gcc.dg/format/attr-4.c =================================================================== --- gcc/testsuite/gcc.dg/format/attr-4.c (revision 223371) +++ gcc/testsuite/gcc.dg/format/attr-4.c (working copy) @@ -14,11 +14,11 @@ extern __attribute__((noreturn)) void ba void 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); tformatprintf2 ("%"); /* { dg-warning "format" "attribute format printf case 2" } */ tformatprintf3 ("%d", i); Index: gcc/testsuite/gcc.dg/format/branch-1.c =================================================================== --- gcc/testsuite/gcc.dg/format/branch-1.c (revision 223371) +++ gcc/testsuite/gcc.dg/format/branch-1.c (working copy) @@ -7,22 +7,22 @@ void 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 } */ } Index: gcc/testsuite/gcc.dg/format/c90-printf-1.c =================================================================== --- gcc/testsuite/gcc.dg/format/c90-printf-1.c (revision 223371) +++ gcc/testsuite/gcc.dg/format/c90-printf-1.c (working copy) @@ -32,32 +32,39 @@ foo (int i, int i1, int i2, unsigned int /* GCC has objected to the next one in the past, but it is a valid way of specifying zero precision. */ 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); /* Strictly, these parameters should be int or unsigned int according to what unsigned short promotes to. However, GCC ignores sign @@ -65,98 +72,98 @@ foo (int i, int i1, int i2, unsigned int correct checking without print_char_table needing to know whether int and short are the same size. */ 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. */ printf ("%Le%LE%Lf%Lg%LG", ld, ld, ld, ld, ld); /* 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 ("%08.5o", u); /* { dg-warning "11:ignored" "0 flag ignored with precision" } */ printf ("%08.5u", u); /* { dg-warning "11:ignored" "0 flag ignored with precision" } */ @@ -174,17 +181,17 @@ foo (int i, int i1, int i2, unsigned int printf ("%-08E", d); /* { dg-warning "11:flags|ignored" "0 flag ignored with - flag" } */ printf ("%-08f", d); /* { dg-warning "11:flags|ignored" "0 flag ignored with - flag" } */ 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 or pointers to other types. (Whether, in fact, character types are allowed here is unclear; see thread on comp.std.c, July 2000 for @@ -194,22 +201,22 @@ foo (int i, int i1, int i2, unsigned int pointer targets differ in signedness, except in some circumstances for character pointers. (In C99 we should consider warning for 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. */ printf ("%s%s%s%s", s, ss, us, css); /* Warning for void * arguments for %s is GCC's historical behavior, 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 in such cases. */ @@ -218,20 +225,24 @@ foo (int i, int i1, int i2, unsigned int GCC has been inconsistent and allowed unsigned for width but not precision. */ 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" } */ }