PR target/88638 - FAIL: fsf-nsstring-format-1.s on darwin
gcc/c-family/ChangeLog: PR target/88638 * c-attribs.c (positional_argument): Call valid_format_string_type_p and issue errors if it fails. * c-common.h (valid_format_string_type_p): Declare. * c-format.c (valid_stringptr_type_p): Rename... (valid_format_string_type_p): ...to this and make extern. (handle_format_arg_attribute): Adjust to new name. (check_format_string): Same. gcc/testsuite/ChangeLog: PR target/88638 * gcc.dg/format/attr-8.c: New test. * gcc.dg/darwin-cfstring-format-1.c: Adjust diagnostics. * gcc.dg/format/attr-3.c: Same. * obj-c++.dg/fsf-nsstring-format-1.mm: Same. * objc.dg/fsf-nsstring-format-1.m: Same. gcc/ChangeLog: PR target/88638 * doc/extend.texi (Darwin Format Checks): Clarify. From-SVN: r267922
This commit is contained in:
parent
15f4e33db7
commit
23db6ced33
12 changed files with 117 additions and 32 deletions
|
@ -1,3 +1,8 @@
|
|||
2019-01-14 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR target/88638
|
||||
* doc/extend.texi (Darwin Format Checks): Clarify.
|
||||
|
||||
2019-01-14 Richard Biener <rguenther@suse.de>
|
||||
|
||||
* genmatch.c (dt_simplify::gen_1): Change dumping dependent on
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
2019-01-14 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR target/88638
|
||||
* c-attribs.c (positional_argument): Call valid_format_string_type_p
|
||||
and issue errors if it fails.
|
||||
* c-common.h (valid_format_string_type_p): Declare.
|
||||
* c-format.c (valid_stringptr_type_p): Rename...
|
||||
(valid_format_string_type_p): ...to this and make extern.
|
||||
(handle_format_arg_attribute): Adjust to new name.
|
||||
(check_format_string): Same.
|
||||
|
||||
2019-01-13 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* c-warn.c (warn_for_address_or_pointer_of_packed_member):
|
||||
|
|
|
@ -631,17 +631,13 @@ positional_argument (const_tree fntype, const_tree atname, tree pos,
|
|||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Where the expected code is STRING_CST accept any pointer
|
||||
expected by attribute format (this includes possibly qualified
|
||||
char pointers and, for targets like Darwin, also pointers to
|
||||
struct CFString). */
|
||||
bool type_match;
|
||||
if (code == STRING_CST && POINTER_TYPE_P (argtype))
|
||||
{
|
||||
/* Where the expected code is STRING_CST accept any pointer
|
||||
to a narrow character type, qualified or otherwise. */
|
||||
tree type = TREE_TYPE (argtype);
|
||||
type = TYPE_MAIN_VARIANT (type);
|
||||
type_match = (type == char_type_node
|
||||
|| type == signed_char_type_node
|
||||
|| type == unsigned_char_type_node);
|
||||
}
|
||||
if (code == STRING_CST)
|
||||
type_match = valid_format_string_type_p (argtype);
|
||||
else if (code == INTEGER_TYPE)
|
||||
/* For integers, accept enums, wide characters and other types
|
||||
that match INTEGRAL_TYPE_P except for bool. */
|
||||
|
@ -652,6 +648,21 @@ positional_argument (const_tree fntype, const_tree atname, tree pos,
|
|||
|
||||
if (!type_match)
|
||||
{
|
||||
if (code == STRING_CST)
|
||||
{
|
||||
/* Reject invalid format strings with an error. */
|
||||
if (argno < 1)
|
||||
error ("%qE attribute argument value %qE refers to "
|
||||
"parameter type %qT",
|
||||
atname, pos, argtype);
|
||||
else
|
||||
error ("%qE attribute argument %i value %qE refers to "
|
||||
"parameter type %qT",
|
||||
atname, argno, pos, argtype);
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
if (argno < 1)
|
||||
warning (OPT_Wattributes,
|
||||
"%qE attribute argument value %qE refers to "
|
||||
|
|
|
@ -1336,6 +1336,9 @@ extern tree tm_mask_to_attr (int);
|
|||
extern tree find_tm_attribute (tree);
|
||||
extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[];
|
||||
|
||||
/* In c-format.c. */
|
||||
extern bool valid_format_string_type_p (tree);
|
||||
|
||||
/* A bitmap of flags to positional_argument. */
|
||||
enum posargflags {
|
||||
/* Consider positional attribute argument value zero valid. */
|
||||
|
|
|
@ -122,8 +122,8 @@ format_warning_at_char (location_t fmt_string_loc, tree format_string_cst,
|
|||
The function returns true if strref points to any string type valid for the
|
||||
language dialect and target. */
|
||||
|
||||
static bool
|
||||
valid_stringptr_type_p (tree strref)
|
||||
bool
|
||||
valid_format_string_type_p (tree strref)
|
||||
{
|
||||
return (strref != NULL
|
||||
&& TREE_CODE (strref) == POINTER_TYPE
|
||||
|
@ -160,7 +160,7 @@ handle_format_arg_attribute (tree *node, tree atname,
|
|||
return NULL_TREE;
|
||||
}
|
||||
|
||||
if (!valid_stringptr_type_p (TREE_TYPE (type)))
|
||||
if (!valid_format_string_type_p (TREE_TYPE (type)))
|
||||
{
|
||||
if (!(flags & (int) ATTR_FLAG_BUILT_IN))
|
||||
error ("function does not return string type");
|
||||
|
@ -194,7 +194,7 @@ check_format_string (const_tree fntype, unsigned HOST_WIDE_INT format_num,
|
|||
}
|
||||
|
||||
if (!ref
|
||||
|| !valid_stringptr_type_p (ref))
|
||||
|| !valid_format_string_type_p (ref))
|
||||
{
|
||||
if (!(flags & (int) ATTR_FLAG_BUILT_IN))
|
||||
error ("format string argument is not a string type");
|
||||
|
@ -267,13 +267,21 @@ check_format_string (const_tree fntype, unsigned HOST_WIDE_INT format_num,
|
|||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* Verify EXPR is a constant, and store its value.
|
||||
If validated_p is true there should be no errors.
|
||||
/* Under the control of FLAGS, verify EXPR is a valid constant that
|
||||
refers to a positional argument ARGNO having a string type (char*
|
||||
or, for targets like Darwin, a pointer to struct CFString) to
|
||||
a function type FNTYPE declared with attribute ATNAME.
|
||||
If valid, store the constant's integer value in *VALUE and return
|
||||
the value.
|
||||
If VALIDATED_P is true assert the validation is successful.
|
||||
Returns the converted constant value on success, null otherwise. */
|
||||
|
||||
static tree
|
||||
get_constant (const_tree fntype, const_tree atname, tree expr, int argno,
|
||||
unsigned HOST_WIDE_INT *value, int flags, bool validated_p)
|
||||
{
|
||||
/* Require the referenced argument to have a string type. For targets
|
||||
like Darwin, also accept pointers to struct CFString. */
|
||||
if (tree val = positional_argument (fntype, atname, expr, STRING_CST,
|
||||
argno, flags))
|
||||
{
|
||||
|
|
|
@ -22397,10 +22397,14 @@ bit-fields. See the Solaris man page for @code{cmn_err} for more information.
|
|||
@node Darwin Format Checks
|
||||
@subsection Darwin Format Checks
|
||||
|
||||
Darwin targets support the @code{CFString} (or @code{__CFString__}) in the format
|
||||
attribute context. Declarations made with such attribution are parsed for correct syntax
|
||||
and format argument types. However, parsing of the format string itself is currently undefined
|
||||
and is not carried out by this version of the compiler.
|
||||
In addition to the full set of format archetypes (attribute format style
|
||||
arguments such as @code{printf}, @code{scanf}, @code{strftime}, and
|
||||
@code{strfmon}), Darwin targets also support the @code{CFString} (or
|
||||
@code{__CFString__}) archetype in the @code{format} attribute.
|
||||
Declarations with this archetype are parsed for correct syntax
|
||||
and argument types. However, parsing of the format string itself and
|
||||
validating arguments against it in calls to such functions is currently
|
||||
not performed.
|
||||
|
||||
Additionally, @code{CFStringRefs} (defined by the @code{CoreFoundation} headers) may
|
||||
also be used as format arguments. Note that the relevant headers are only likely to be
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
2019-01-14 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR target/88638
|
||||
* gcc.dg/format/attr-8.c: New test.
|
||||
* gcc.dg/darwin-cfstring-format-1.c: Adjust diagnostics.
|
||||
* gcc.dg/format/attr-3.c: Same.
|
||||
* obj-c++.dg/fsf-nsstring-format-1.mm: Same.
|
||||
* objc.dg/fsf-nsstring-format-1.m: Same.
|
||||
|
||||
2019-01-14 Martin Liska <mliska@suse.cz>
|
||||
|
||||
PR gcov-profile/88263
|
||||
|
|
|
@ -15,7 +15,7 @@ typedef const struct __CFString * CFStringRef;
|
|||
int s1 (CFStringRef fmt, ...) __attribute__((format(CFString, 1, 2))) ; /* OK */
|
||||
int s2 (int a, CFStringRef fmt, ... ) __attribute__((format(__CFString__, 2, 3))) ; /* OK */
|
||||
|
||||
int s2a (int a, CFStringRef fmt, ... ) __attribute__((format(CFString, 2, 2))) ; /* { dg-error "format string argument follows the args to be formatted" } */
|
||||
int s2a (int a, CFStringRef fmt, ... ) __attribute__((format(CFString, 2, 2))) ; /* { dg-error ".format. attribute argument 3 value .2. does not refer to a variable argument list" } */
|
||||
|
||||
int s3 (const char *fmt, ... ) __attribute__((format(__CFString__, 1, 2))) ; /* { dg-error "format argument should be a .CFString. reference but a string was found" } */
|
||||
int s4 (CFStringRef fmt, ... ) __attribute__((format(printf, 1, 2))) ; /* { dg-error "found a .CFStringRef.* but the format argument should be a string" } */
|
||||
|
@ -23,7 +23,7 @@ int s4 (CFStringRef fmt, ... ) __attribute__((format(printf, 1, 2))) ; /* { dg-e
|
|||
char *s5 (char dum, char *fmt1, ... ) __attribute__((format_arg(2))) ; /* OK */
|
||||
CFStringRef s6 (CFStringRef dum, CFStringRef fmt1, ... ) __attribute__((format_arg(2))) ; /* OK */
|
||||
|
||||
char *s7 (int dum, void *fmt1, ... ) __attribute__((format_arg(2))) ; /* { dg-error "format string argument is not a string type" } */
|
||||
char *s7 (int dum, void *fmt1, ... ) __attribute__((format_arg(2))) ; /* { dg-error ".format_arg. attribute argument value .2. refers to parameter type .void \\\*." } */
|
||||
int s8 (CFStringRef dum, CFStringRef fmt1, ... ) __attribute__((format_arg(2))) ; /* { dg-error "function does not return string type" } */
|
||||
|
||||
void foo (void)
|
||||
|
|
|
@ -56,16 +56,16 @@ extern void fg3 () __attribute__((format(gnu_attr_printf, 2, 1))); /* { dg-error
|
|||
|
||||
/* The format string argument must be a string type, and the arguments to
|
||||
be formatted must be the "...". */
|
||||
extern void fh0 (int, ...) __attribute__((format(gnu_attr_printf, 1, 2))); /* { dg-warning ".format. attribute argument 2 value .1. refers to parameter type .int." "format int string" } */
|
||||
extern void fh1 (signed char *, ...) __attribute__((format(gnu_attr_printf, 1, 2))); /* { dg-error "not a string" "signed char string" } */
|
||||
extern void fh2 (unsigned char *, ...) __attribute__((format(gnu_attr_printf, 1, 2))); /* { dg-error "not a string" "unsigned char string" } */
|
||||
extern void fh0 (int, ...) __attribute__((format(gnu_attr_printf, 1, 2))); /* { dg-error ".format. attribute argument 2 value .1. refers to parameter type .int." "format int string" } */
|
||||
extern void fh1 (signed char *, ...) __attribute__((format(gnu_attr_printf, 1, 2))); /* { dg-error ".format. attribute argument 2 value .1. refers to parameter type .signed char \\\*." "signed char string" } */
|
||||
extern void fh2 (unsigned char *, ...) __attribute__((format(gnu_attr_printf, 1, 2))); /* { dg-error ".format. attribute argument 2 value .1. refers to parameter type .unsigned char \\\*." "unsigned char string" } */
|
||||
extern void fh3 (const char *, ...) __attribute__((format(gnu_attr_printf, 1, 3))); /* { dg-error "is not" "not ..." } */
|
||||
extern void fh4 (const char *, int, ...) __attribute__((format(gnu_attr_printf, 1, 2))); /* { dg-error ".format. attribute argument 3 value .2. does not refer to a variable argument list" "not ..." } */
|
||||
|
||||
/* format_arg formats must take and return a string. */
|
||||
extern char *fi0 (int) __attribute__((format_arg(1))); /* { dg-warning ".format_arg. attribute argument value .1. refers to parameter type .int." } */
|
||||
extern char *fi1 (signed char *) __attribute__((format_arg(1))); /* { dg-error "not a string" "format_arg signed char string" } */
|
||||
extern char *fi2 (unsigned char *) __attribute__((format_arg(1))); /* { dg-error "not a string" "format_arg unsigned char string" } */
|
||||
extern char *fi0 (int) __attribute__((format_arg(1))); /* { dg-error ".format_arg. attribute argument value .1. refers to parameter type .int." } */
|
||||
extern char *fi1 (signed char *) __attribute__((format_arg(1))); /* { dg-error ".format_arg. attribute argument value .1. refers to parameter type .signed char \\\*." "format_arg signed char string" } */
|
||||
extern char *fi2 (unsigned char *) __attribute__((format_arg(1))); /* { dg-error ".format_arg. attribute argument value .1. refers to parameter type .unsigned char \\\*." "format_arg unsigned char string" } */
|
||||
extern int fi3 (const char *) __attribute__((format_arg(1))); /* { dg-error "not return string" "format_arg ret int string" } */
|
||||
extern signed char *fi4 (const char *) __attribute__((format_arg(1))); /* { dg-error "not return string" "format_arg ret signed char string" } */
|
||||
extern unsigned char *fi5 (const char *) __attribute__((format_arg(1))); /* { dg-error "not return string" "format_arg ret unsigned char string" } */
|
||||
|
|
34
gcc/testsuite/gcc.dg/format/attr-8.c
Normal file
34
gcc/testsuite/gcc.dg/format/attr-8.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* Test to verify that parameters of qualified narrow char pointer type
|
||||
are accepted for attribute format printf, but others are rejected.
|
||||
{ dg-do compile }
|
||||
{ dg-options "-std=gnu99 -Wformat" } */
|
||||
|
||||
#define DONT_GNU_PROTOTYPE
|
||||
#include "format.h"
|
||||
|
||||
#define FORMAT(archetype, arg1, arg2) \
|
||||
__attribute__ ((format (archetype, arg1, arg2)))
|
||||
|
||||
FORMAT (gnu_attr_printf, 1, 2)
|
||||
void fpc_1_2 (char *, ...);
|
||||
|
||||
FORMAT (gnu_attr_printf, 1, 2)
|
||||
void fpcc_1_2 (const char *, ...);
|
||||
|
||||
FORMAT (gnu_attr_printf, 1, 2)
|
||||
void frpc_1_2 (char * restrict, ...);
|
||||
|
||||
FORMAT (gnu_attr_printf, 1, 2)
|
||||
void fpvc_1_2 (volatile char *, ...);
|
||||
|
||||
FORMAT (gnu_attr_printf, 1, 2)
|
||||
void fpcvc_1_2 (const volatile char *, ...);
|
||||
|
||||
FORMAT (gnu_attr_printf, 1, 2)
|
||||
void fpv_1_2 (void *, ...); /* { dg-error ".format. attribute argument 2 value .1. refers to parameter type .void \\\*." } */
|
||||
|
||||
FORMAT (gnu_attr_printf, 1, 2)
|
||||
void fppc_1_2 (char **, ...); /* { dg-error ".format. attribute argument 2 value .1. refers to parameter type .char \\\*\\\*." } */
|
||||
|
||||
FORMAT (gnu_attr_printf, 1, 2)
|
||||
void fpwc_1_2 (wchar_t *, ...); /* { dg-error ".format. attribute argument 2 value .1. refers to parameter type .wchar_t \\\*." } */
|
|
@ -28,7 +28,7 @@ int s1b (NSString *fmt, ...) __attribute__((format(CFString, 1, 2))) ; /* { dg-e
|
|||
|
||||
int s2 (int a, NSString *fmt, ... ) __attribute__((format(__NSString__, 2, 3))) ; /* OK */
|
||||
|
||||
int s2a (int a, NSString *fmt, ... ) __attribute__((format(NSString, 2, 2))) ; /* { dg-error "format string argument follows the args to be formatted" } */
|
||||
int s2a (int a, NSString *fmt, ... ) __attribute__((format(NSString, 2, 2))) ; /* { dg-error ".format. attribute argument 3 value .2. does not refer to a variable argument list" } */
|
||||
|
||||
int s3 (const char *fmt, ... ) __attribute__((format(__NSString__, 1, 2))) ; /* { dg-error "format argument should be a .NSString. reference but a string was found" } */
|
||||
int s4 (NSString *fmt, ... ) __attribute__((format(printf, 1, 2))) ; /* { dg-error "found a .NSString. reference but the format argument should be a string" } */
|
||||
|
@ -36,7 +36,7 @@ int s4 (NSString *fmt, ... ) __attribute__((format(printf, 1, 2))) ; /* { dg-err
|
|||
char *s5 (char dum, char *fmt1, ... ) __attribute__((format_arg(2))) ; /* OK */
|
||||
NSString *s6 (NSString *dum, NSString *fmt1, ... ) __attribute__((format_arg(2))) ; /* OK */
|
||||
|
||||
char *s7 (int dum, void *fmt1, ... ) __attribute__((format_arg(2))) ; /* { dg-error "format string argument is not a string type" } */
|
||||
char *s7 (int dum, void *fmt1, ... ) __attribute__((format_arg(2))) ; /* { dg-error ".format_arg. attribute argument value .2. refers to parameter type .void\\\*." } */
|
||||
int s8 (NSString *dum, NSString *fmt1, ... ) __attribute__((format_arg(2))) ; /* { dg-error "function does not return string type" } */
|
||||
|
||||
char *s9 (int dum, char *fmt1, ... ) __attribute__((format_arg(2))) ; /* OK */
|
||||
|
|
|
@ -21,7 +21,7 @@ int s1b (NSString *fmt, ...) __attribute__((format(CFString, 1, 2))) ; /* { dg-e
|
|||
|
||||
int s2 (int a, NSString *fmt, ... ) __attribute__((format(__NSString__, 2, 3))) ; /* OK */
|
||||
|
||||
int s2a (int a, NSString *fmt, ... ) __attribute__((format(NSString, 2, 2))) ; /* { dg-error "format string argument follows the args to be formatted" } */
|
||||
int s2a (int a, NSString *fmt, ... ) __attribute__((format(NSString, 2, 2))) ; /* { dg-error ".format. attribute argument 3 value .2. does not refer to a variable argument list" } */
|
||||
|
||||
int s3 (const char *fmt, ... ) __attribute__((format(__NSString__, 1, 2))) ; /* { dg-error "format argument should be a .NSString. reference but a string was found" } */
|
||||
int s4 (NSString *fmt, ... ) __attribute__((format(printf, 1, 2))) ; /* { dg-error "found a .NSString. reference but the format argument should be a string" } */
|
||||
|
@ -29,7 +29,7 @@ int s4 (NSString *fmt, ... ) __attribute__((format(printf, 1, 2))) ; /* { dg-err
|
|||
char *s5 (char dum, char *fmt1, ... ) __attribute__((format_arg(2))) ; /* OK */
|
||||
NSString *s6 (NSString *dum, NSString *fmt1, ... ) __attribute__((format_arg(2))) ; /* OK */
|
||||
|
||||
char *s7 (int dum, void *fmt1, ... ) __attribute__((format_arg(2))) ; /* { dg-error "format string argument is not a string type" } */
|
||||
char *s7 (int dum, void *fmt1, ... ) __attribute__((format_arg(2))) ; /* { dg-error ".format_arg. attribute argument value .2. refers to parameter type .void \\\*." } */
|
||||
int s8 (NSString *dum, NSString *fmt1, ... ) __attribute__((format_arg(2))) ; /* { dg-error "function does not return string type" } */
|
||||
|
||||
char *s9 (int dum, char *fmt1, ... ) __attribute__((format_arg(2))) ; /* OK */
|
||||
|
|
Loading…
Add table
Reference in a new issue