Commit 23db6ced by Martin Sebor Committed by Martin Sebor

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
parent 15f4e33d
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
......
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
......
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" } */
/* 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 */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment