aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2019-01-14 18:44:00 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2019-01-14 11:44:00 -0700
commit23db6ced33c245c38c147c31011bbafa392e4328 (patch)
treee0ee52741bfafa1d02673e8cf26b8d54139efe82
parent15f4e33db7e7b0c466db39eccfc693c910459368 (diff)
downloadgcc-23db6ced33c245c38c147c31011bbafa392e4328.zip
gcc-23db6ced33c245c38c147c31011bbafa392e4328.tar.gz
gcc-23db6ced33c245c38c147c31011bbafa392e4328.tar.bz2
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
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/c-family/ChangeLog11
-rw-r--r--gcc/c-family/c-attribs.c31
-rw-r--r--gcc/c-family/c-common.h3
-rw-r--r--gcc/c-family/c-format.c20
-rw-r--r--gcc/doc/extend.texi12
-rw-r--r--gcc/testsuite/ChangeLog9
-rw-r--r--gcc/testsuite/gcc.dg/darwin-cfstring-format-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/format/attr-3.c12
-rw-r--r--gcc/testsuite/gcc.dg/format/attr-8.c34
-rw-r--r--gcc/testsuite/obj-c++.dg/fsf-nsstring-format-1.mm4
-rw-r--r--gcc/testsuite/objc.dg/fsf-nsstring-format-1.m4
12 files changed, 117 insertions, 32 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index bf6e319..869ab24 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index d1b4d25..fe4c81f 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -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):
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index c893baa..2058459 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -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 "
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index db16ae9..9f790bc 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -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. */
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 327fa29..9b48ee3 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -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))
{
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index f013057..c81092d 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 093c362..8c6f9e4 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.dg/darwin-cfstring-format-1.c b/gcc/testsuite/gcc.dg/darwin-cfstring-format-1.c
index c1b44a3..a1513ee 100644
--- a/gcc/testsuite/gcc.dg/darwin-cfstring-format-1.c
+++ b/gcc/testsuite/gcc.dg/darwin-cfstring-format-1.c
@@ -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)
diff --git a/gcc/testsuite/gcc.dg/format/attr-3.c b/gcc/testsuite/gcc.dg/format/attr-3.c
index 31cc05ec..1b275c5 100644
--- a/gcc/testsuite/gcc.dg/format/attr-3.c
+++ b/gcc/testsuite/gcc.dg/format/attr-3.c
@@ -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" } */
diff --git a/gcc/testsuite/gcc.dg/format/attr-8.c b/gcc/testsuite/gcc.dg/format/attr-8.c
new file mode 100644
index 0000000..7fba35a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/format/attr-8.c
@@ -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 \\\*." } */
diff --git a/gcc/testsuite/obj-c++.dg/fsf-nsstring-format-1.mm b/gcc/testsuite/obj-c++.dg/fsf-nsstring-format-1.mm
index a5eaf34..18f5960 100644
--- a/gcc/testsuite/obj-c++.dg/fsf-nsstring-format-1.mm
+++ b/gcc/testsuite/obj-c++.dg/fsf-nsstring-format-1.mm
@@ -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 */
diff --git a/gcc/testsuite/objc.dg/fsf-nsstring-format-1.m b/gcc/testsuite/objc.dg/fsf-nsstring-format-1.m
index ecbad43..e29358c 100644
--- a/gcc/testsuite/objc.dg/fsf-nsstring-format-1.m
+++ b/gcc/testsuite/objc.dg/fsf-nsstring-format-1.m
@@ -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 */