From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15311 invoked by alias); 28 Oct 2010 13:38:22 -0000 Received: (qmail 15294 invoked by uid 22791); 28 Oct 2010 13:38:16 -0000 X-SWARE-Spam-Status: No, hits=1.5 required=5.0 tests=AWL,BAYES_05,KAM_STOCKTIP,RCVD_IN_DNSWL_NONE,TW_BJ X-Spam-Check-By: sourceware.org Received: from c2bthomr13.btconnect.com (HELO mail.btconnect.com) (213.123.20.131) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 28 Oct 2010 13:38:05 +0000 Received: from host81-138-1-83.in-addr.btopenworld.com (EHLO thor.office) ([81.138.1.83]) by c2bthomr13.btconnect.com with ESMTP id ALD86193; Thu, 28 Oct 2010 14:38:01 +0100 (BST) Cc: GCC Patches , Mike Stump , Mike Stump Message-Id: <7E8FB7AA-C33B-4A87-A176-081C3E7787AC@sandoe-acoustics.co.uk> From: IainS To: "Joseph S. Myers" In-Reply-To: Content-Type: multipart/mixed; boundary=Apple-Mail-221-728228882 Mime-Version: 1.0 (Apple Message framework v936) Subject: Updated: [Patch, c* ,ObjC*] handle string objects in format checking. Date: Thu, 28 Oct 2010 18:05:00 -0000 References: <3F894B1C-C5CE-45FD-B73F-843A2C7ED940@sandoe-acoustics.co.uk> <0F66301E-FC8C-46C1-AFAF-CDF2ACDA2EEA@sandoe-acoustics.co.uk> X-Mirapoint-IP-Reputation: reputation=Fair-1, source=Queried, refid=tid=0001.0A0B0301.4CC97CB2.02E6, actions=tag X-Junkmail-Signature-Raw: score=unknown, refid=str=0001.0A0B0203.4CC97CBA.001E,ss=1,fgs=0, ip=0.0.0.0, so=2010-07-22 22:03:31, dmn=2009-09-10 00:05:08, mode=single engine X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2010-10/txt/msg02418.txt.bz2 --Apple-Mail-221-728228882 Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit Content-length: 4049 Hello Joseph, On 25 Oct 2010, at 01:40, Mike Stump wrote: > On Oct 24, 2010, at 9:20 AM, IainS wrote: >> I'll wait for any further comments, and for Mike's input and then >> update the patch. > > Usually we just update as we go... Once the issues Joseph pointed > out are fixed, I'm fine with this. Firstly, I apologize that the intent of the patch was not stated explicitly. The objective is solely to extend the syntax checking of the format and format_arg attributes to include the types that may be used to convey format strings in objective-c* (and between objective-c* and 'c*' when the target understands string objects). Since the behavior of checking such strings is currently undefined, the format arg parse is a no-op for this version of the compiler. --- I have: o Added documentation to describe what is allowed, and what its limitations are. o Added an explicit flag to the formats that indicates that parsing of the format arg string is the responsibility of an external agent. o Added a stub implementation (i.e. the 'no-op' is moved from c- family/ to objc and darwin for NSString and target strings respectively). o Expanded the diagnostics. o Added explicit test-cases (additional to the existing darwin header checks). o Expanded the hook documentation and source comments somewhat. o moved the darwin part of the code to darwin-c as you suggested. bootstrapped & checked on darwin9/10, x86_64-linux. (& done make pdf). OK for trunk? Iain --- gcc: * doc/extend.tex (format): Document NSString extension. (format_arg): Likewise. (Darwin Format Checks): New section. * doc/tm.texi: Document string object hooks (generated). * doc/tm.texi.in (TARGET_OBJC_CONSTRUCT_STRING_OBJECT) Rename. (TARGET_STRING_OBJECT_REF_TYPE_P): New. (TARGET_CHECK_STRING_OBJECT_FORMAT_ARG): New. * target.def (objc_construct_string_object): Rename, amend documentation. (string_object_ref_type_p): New hook. (check_string_object_format_arg): New hook. * c-parser.c (c_parser_attributes): Allow objective-c class names as attribute identifiers. * config/darwin-c.c (darwin_cfstring_ref_p): New. (darwin_check_cfstring_format_arg): New. (darwin_additional_format_types): New. * config/darwin-protos.h (darwin_cfstring_ref_p) New. (darwin_check_cfstring_format_arg): New. * config/darwin.h (TARGET_OBJC_CONSTRUCT_STRING_OBJECT) Renamed. (TARGET_STRING_OBJECT_REF_TYPE_P): New. (TARGET_N_FORMAT_TYPES): New. (TARGET_CHECK_STRING_OBJECT_FORMAT_ARG): New. gcc/c-family: * c-format.c (format_type): New type gcc_objc_string_format_type. (valid_stringptr_type_p): New. (handle_format_arg_attribute): Use valid_stringptr_type_p (). (check_format_string): Pass expected type, use valid_stringptr_type_p (), check that the format string types are consistent with the format specification. (decode_format_attr): Warn if NSString is used outside objective-c. (format_types_orig): Add NSString. (format_name): New. (format_flags): New. (check_format_arg): Handle format strings requiring an external parser. first_target_format_type: New variable. (handle_format_attribute): Set up first_target_format_type, pass the expected format arg string type to check_format_string(). * c-common.h (FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL): New flag. * stub-objc.c (objc_string_ref_type_p): New. (objc_check_format_arg): New. gcc/objc: * objc-act.c (objc_build_string_object): Amend for renamed hook. (objc_string_ref_type_p): New. (objc_check_format_arg): New. gcc/testsuite: * gcc.dg/darwin-cfstring-format-1.c: New. * gcc.dg/warn-nsstring.c: New. * objc.dg/fsf-nsstring-format-1.m: New. * obj-c++.dg/fsf-nsstring-format-1.mm: New. * objc.dg/property/property-3.m: Update for darwin10 linker warning. * objc.dg/property/property-2.m: Likewise. * objc.dg/torture/strings/const-cfstring-1.m: Likewise. * obj-c++.dg/property/property-2.mm: Likewise. * obj-c++.dg/property/property-3.mm: Likewise. * obj-c++.dg/torture/strings/const-cfstring-1.mm: Likewise. --Apple-Mail-221-728228882 Content-Disposition: attachment; filename=166026-format-attr-extensions.txt Content-Type: text/plain; x-unix-mode=0644; x-mac-type=54455854; name="166026-format-attr-extensions.txt" Content-Transfer-Encoding: quoted-printable Content-length: 43865 Index: gcc/doc/extend.texi =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/doc/extend.texi (revision 166026) +++ gcc/doc/extend.texi (working copy) @@ -2418,7 +2418,13 @@ standard modes, the X/Open function @code{strfmon} are @code{printf_unlocked} and @code{fprintf_unlocked}. @xref{C Dialect Options,,Options Controlling C Dialect}. =20 -The target may provide additional types of format checks. +For Objective-C dialects, @code{NSString} (or @code{__NSString__}) is=20 +recognized in the same context. Declarations including these format attri= butes +will be parsed for correct syntax, however the result of checking of such = format +strings is not yet defined, and will not be carried out by this version of= the=20 +compiler. + +The target may also provide additional types of format checks. @xref{Target Format Checks,,Format Checks Specific to Particular Target Machines}. =20 @@ -2467,6 +2473,14 @@ requested by @option{-ansi} or an appropriate @opt is used. @xref{C Dialect Options,,Options Controlling C Dialect}. =20 +For Objective-C dialects, the @code{format-arg} attribute may refer to an +@code{NSString} reference for compatibility with the @code{format} attribu= te +above. + +The target may also allow additional types in @code{format-arg} attributes. +@xref{Target Format Checks,,Format Checks Specific to Particular +Target Machines}. + @item function_vector @cindex calling functions through the function vector on H8/300, M16C, M32= C and SH2A processors Use this attribute on the H8/300, H8/300H, and H8S to indicate that the sp= ecified @@ -12408,6 +12422,7 @@ format attribute =20 @menu * Solaris Format Checks:: +* Darwin Format Checks:: @end menu =20 @node Solaris Format Checks @@ -12418,6 +12433,20 @@ check. @code{cmn_err} accepts a subset of the sta conversions, and the two-argument @code{%b} conversion for displaying bit-fields. See the Solaris man page for @code{cmn_err} for more informat= ion. =20 +@node Darwin Format Checks +@subsection Darwin Format Checks + +Darwin targets support the @code{CFString} (or @code{__CFString__}) in the= format=20 +attribute context. Declarations made with such attribution will be parsed= for correct syntax +and format argument types. However, parsing of the format string itself i= s currently undefined +and will not be carried out by this version of the compiler.=20=20 + +Additionally, @code{CFStringRefs} (defined by the @code{CoreFoundation} he= aders) may +also be used as format arguments. Note that the relevant headers are only= likely to be +available on Darwin (OSX) installations. On such installations, the XCo= de and system +documentation provide descriptions of @code{CFString}, @code{CFStringRefs}= and +associated functions. + @node Pragmas @section Pragmas Accepted by GCC @cindex pragmas Index: gcc/doc/tm.texi =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/doc/tm.texi (revision 166026) +++ gcc/doc/tm.texi (working copy) @@ -742,10 +742,18 @@ only available in the C (and related language) fro should use @code{TARGET_HANDLE_C_OPTION} instead. @end deftypefn =20 -@deftypefn {Target Hook} tree TARGET_OBJC_CONSTRUCT_STRING (tree @var{stri= ng}) -Construct a constant string representation for @var{string} +@deftypefn {Target Hook} tree TARGET_OBJC_CONSTRUCT_STRING_OBJECT (tree @v= ar{string}) +Targets may provide a string object type that can be used within and betwe= en c, c++ and their respective objective-c dialects. A string object might,= for example, embed encoding and length information. These objects are cons= idered opaque to the compiler and handled as references. An ideal implement= ation makes the composition of the string object match that of the objectiv= e-c @code{NSString} (@code{NXString} for GNUStep), allowing efficient inter= working between c-only and objective-c code. If a target implements string = objects then this hook should return a reference to such an object construc= ted from the normal 'c' string representation provided in @var{string}. At = present, the hook is used by objective-c only, to obtain a common-format st= ring object when the target provides one. @end deftypefn =20 +@deftypefn {Target Hook} bool TARGET_STRING_OBJECT_REF_TYPE_P (const_tree = @var{stringref}) +If a target implements string objects then this hook should return 'true' = if @var{stringref} is a valid reference to such an object. +@end deftypefn + +@deftypefn {Target Hook} void TARGET_CHECK_STRING_OBJECT_FORMAT_ARG (tree = @var{format_arg}, tree @var{args_list}) +If a target implements string objects then this hook should should provid= e a facility to check the function arguments in @var{args_list} against th= e format specifiers in @var{format_arg} where the type of @var{format_arg}= is one recognized as a valid string reference type. +@end deftypefn + @defmac TARGET_VERSION This macro is a C statement to print on @code{stderr} a string describing the particular machine description choice. Every machine Index: gcc/doc/tm.texi.in =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/doc/tm.texi.in (revision 166026) +++ gcc/doc/tm.texi.in (working copy) @@ -742,8 +742,12 @@ only available in the C (and related language) fro should use @code{TARGET_HANDLE_C_OPTION} instead. @end deftypefn =20 -@hook TARGET_OBJC_CONSTRUCT_STRING +@hook TARGET_OBJC_CONSTRUCT_STRING_OBJECT =20 +@hook TARGET_STRING_OBJECT_REF_TYPE_P + +@hook TARGET_CHECK_STRING_OBJECT_FORMAT_ARG + @defmac TARGET_VERSION This macro is a C statement to print on @code{stderr} a string describing the particular machine description choice. Every machine Index: gcc/c-family/c-format.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/c-family/c-format.c (revision 166026) +++ gcc/c-family/c-format.c (working copy) @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "c-format.h" #include "alloc-pool.h" +#include "target.h" =0C /* Set format warning options according to a -Wformat=3Dn option. */ =20 @@ -63,6 +64,7 @@ enum format_type { printf_format_type, asm_fprintf gcc_diag_format_type, gcc_tdiag_format_type, gcc_cdiag_format_type, gcc_cxxdiag_format_type, gcc_gfc_format_type, + gcc_objc_string_format_type, format_type_error =3D -1}; =20 typedef struct function_format_info @@ -77,12 +79,38 @@ static int decode_format_type (const char *); =20 static bool check_format_string (tree argument, unsigned HOST_WIDE_INT format_num, - int flags, bool *no_add_attrs); + int flags, bool *no_add_attrs, + int expected_format_type); static bool get_constant (tree expr, unsigned HOST_WIDE_INT *value, int validated_p); static const char *convert_format_name_to_system_name (const char *attr_na= me); static bool cmp_attribs (const char *tattr_name, const char *attr_name); =20 +static int first_target_format_type; +static const char * format_name (int format_num); +static int format_flags (int format_num); + +/* 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 str= ing + objects validated by objc_string_ref_type_p ().=20=20 + Targets may also provide a string object type that can be used within c= and=20 + c++ and shared with their respective objective-c dialects. In this case= the + reference to a format string is checked for validity via a hook. +=20=20=20 + The function returns true if strref points to any string type valid for= the=20 + language dialect and target. */ + +static bool +valid_stringptr_type_p (tree strref) +{ + return (strref !=3D NULL + && TREE_CODE (strref) =3D=3D POINTER_TYPE + && (TYPE_MAIN_VARIANT (TREE_TYPE (strref)) =3D=3D char_type_node + || objc_string_ref_type_p (strref) + || (*targetcm.string_object_ref_type_p) ((const_tree)strref))); +} + /* Handle a "format_arg" attribute; arguments as in struct attribute_spec.handler. */ tree @@ -104,13 +132,13 @@ handle_format_arg_attribute (tree *node, tree ARG_ argument =3D TYPE_ARG_TYPES (type); if (argument) { - if (!check_format_string (argument, format_num, flags, no_add_attrs)) + /* The format arg can be any string reference valid for the language= and + target. We cannot be more specific in this case. */ + if (!check_format_string (argument, format_num, flags, no_add_attrs,= -1)) return NULL_TREE; } =20 - if (TREE_CODE (TREE_TYPE (type)) !=3D POINTER_TYPE - || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) - !=3D char_type_node)) + if (!valid_stringptr_type_p (TREE_TYPE (type))) { if (!(flags & (int) ATTR_FLAG_BUILT_IN)) error ("function does not return string type"); @@ -121,13 +149,18 @@ handle_format_arg_attribute (tree *node, tree ARG_ return NULL_TREE; } =20 -/* Verify that the format_num argument is actually a string, in case - the format attribute is in error. */ +/* Verify that the format_num argument is actually a string reference suit= able, + for the language dialect and target (in case the format attribute is in= =20 + error). When we know the specific reference type expected, this is als= o=20 + checked. */ static bool check_format_string (tree argument, unsigned HOST_WIDE_INT format_num, - int flags, bool *no_add_attrs) + int flags, bool *no_add_attrs, int expected_format_type) { unsigned HOST_WIDE_INT i; + bool is_objc_sref, is_target_sref, is_char_ref; + tree ref; + int fmt_flags; =20 for (i =3D 1; i !=3D format_num; i++) { @@ -137,17 +170,78 @@ check_format_string (tree argument, unsigned HOST_ } =20 if (!argument - || TREE_CODE (TREE_VALUE (argument)) !=3D POINTER_TYPE - || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument))) - !=3D char_type_node)) + || !(ref =3D TREE_VALUE (argument)) + || !valid_stringptr_type_p (ref)) { if (!(flags & (int) ATTR_FLAG_BUILT_IN)) - error ("format string argument not a string type"); + error ("format string argument is not a string type"); *no_add_attrs =3D true; return false; } =20 - return true; + /* We only know that we want a suitable string reference. */ + if (expected_format_type < 0) + return true; + + /* Now check that the arg matches the expected type. */ + is_char_ref =3D=20 + (TYPE_MAIN_VARIANT (TREE_TYPE (ref)) =3D=3D char_type_node); + + fmt_flags =3D format_flags (expected_format_type); + is_objc_sref =3D is_target_sref =3D false; + if (!is_char_ref) + is_objc_sref =3D objc_string_ref_type_p (ref); + + if (!(fmt_flags & FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL)) + { + if (is_char_ref) + return true; /* OK, we expected a char and found one. */ + else + { + /* We expected a char but found an extended string type. */ + if (is_objc_sref) + error ("found a %<%s%> ref. but the format argument should be" + " a string", format_name (gcc_objc_string_format_type)); + else + error ("found a %qD but the format argument should be a string", + TYPE_NAME (ref)); + *no_add_attrs =3D true; + return false; + } + } + + /* We expect a string object type as the format arg. */ + if (is_char_ref) + { + error ("format argument should be a %<%s%> ref. but" + " a string was found",format_name (expected_format_type)); + *no_add_attrs =3D true; + return false; + } +=20=20 + /* We will assert that objective-c will support either its own string ty= pe + or the target-supplied variant. */ + if (!is_objc_sref) + is_target_sref =3D (*targetcm.string_object_ref_type_p) ((const_tree) = ref); + + if (expected_format_type =3D=3D (int) gcc_objc_string_format_type=20 + && (is_objc_sref || is_target_sref)) + return true; + + /* We will allow a target string ref to match only itself. */ + if (first_target_format_type=20 + && expected_format_type >=3D first_target_format_type + && is_target_sref) + return true; + else + { + error ("format argument should be a %<%s%> ref.",=20 + format_name (expected_format_type)); + *no_add_attrs =3D true; + return false; + } + + gcc_unreachable (); } =20 /* Verify EXPR is a constant, and store its value. @@ -195,6 +289,16 @@ decode_format_attr (tree args, function_format_inf p =3D convert_format_name_to_system_name (p); =20 info->format_type =3D decode_format_type (p); +=20=20=20=20=20=20 + if (!c_dialect_objc () + && info->format_type =3D=3D gcc_objc_string_format_type) + { + gcc_assert (!validated_p); + warning (OPT_Wformat, "%qE is only allowed in Objective-C dialects", + format_type_id); + info->format_type =3D format_type_error; + return false; + } =20 if (info->format_type =3D=3D format_type_error) { @@ -750,6 +854,11 @@ static const format_kind_info format_types_orig[] 0, 0, 0, 0, 0, 0, NULL, NULL }, + { "NSString", NULL, NULL, NULL, NULL, + NULL, NULL, + FMT_FLAG_ARG_CONVERT|FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL, 0, 0, 0, 0, = 0, 0, + NULL, NULL + }, { "gnu_scanf", scanf_length_specs, scan_char_table, "*'I", NULL, scanf_flag_specs, scanf_flag_pairs, FMT_FLAG_ARG_CONVERT|FMT_FLAG_SCANF_A_KLUDGE|FMT_FLAG_USE_DOLLAR|FMT_F= LAG_ZERO_WIDTH_BAD|FMT_FLAG_DOLLAR_GAP_POINTER_OK, @@ -812,6 +921,24 @@ typedef struct tree params; } format_check_context; =20 +static const char * +format_name (int format_num) +{ + if (format_num >=3D 0 && format_num < n_format_types) + return format_types[format_num].name; + else + return "invalid format type"; +} + +static int +format_flags (int format_num) +{ + if (format_num >=3D 0 && format_num < n_format_types) + return format_types[format_num].flags; + else + return 0; +} + static void check_format_info (function_format_info *, tree); static void check_format_arg (void *, tree, unsigned HOST_WIDE_INT); static void check_format_info_main (format_check_results *, @@ -1349,6 +1476,39 @@ check_format_arg (void *ctx, tree format_tree, return; } format_tree =3D TREE_OPERAND (format_tree, 0); + if (format_types[info->format_type].flags=20 + & (int) FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL) + { + bool objc_str =3D (info->format_type =3D=3D gcc_objc_string_format_t= ype); + /* We cannot examine this string here - but we can check that it is + a valid type. */ + if (TREE_CODE (format_tree) !=3D CONST_DECL + || !((objc_str && objc_string_ref_type_p (TREE_TYPE (format_tree))) + || (*targetcm.string_object_ref_type_p)=20 + ((const_tree) TREE_TYPE (format_tree)))) + { + res->number_non_literal++; + return; + } + /* Skip to first argument to check. */ + while (arg_num + 1 < info->first_arg_num) + { + if (params =3D=3D 0) + return; + params =3D TREE_CHAIN (params); + ++arg_num; + } + /* So, we have a valid literal string object and one or more params. + We need to use an external helper to parse the string into format + info. For Objective-C variants we provide the resource within the + objc tree, for target variants, via a hook. */ + if (objc_str) + objc_check_format_arg (format_tree, params); + else if (targetcm.check_string_object_format_arg) + (*targetcm.check_string_object_format_arg) (format_tree, params); + /* Else we can't handle it and retire quietly. */ + return ; + } if (TREE_CODE (format_tree) =3D=3D ARRAY_REF && host_integerp (TREE_OPERAND (format_tree, 1), 0) && (offset +=3D tree_low_cst (TREE_OPERAND (format_tree, 1), 0)) >= =3D 0) @@ -1430,7 +1590,6 @@ check_format_arg (void *ctx, tree format_tree, free_alloc_pool (fwt_pool); } =20 - /* Do the main part of checking a call to a format function. FORMAT_CHARS is the NUL-terminated format string (which at this point may contain internal NUL characters); FORMAT_LENGTH is its length (excluding the @@ -2785,6 +2944,8 @@ handle_format_attribute (tree *node, tree ARG_UNUS TARGET_N_FORMAT_TYPES * sizeof (dynamic_format_types[0])); =20 format_types =3D dynamic_format_types; + /* Provide a reference for the first potential external type. */ + first_target_format_type =3D n_format_types; n_format_types +=3D TARGET_N_FORMAT_TYPES; } #endif @@ -2799,7 +2960,7 @@ handle_format_attribute (tree *node, tree ARG_UNUS if (argument) { if (!check_format_string (argument, info.format_num, flags, - no_add_attrs)) + no_add_attrs, info.format_type)) return NULL_TREE; =20 if (info.first_arg_num !=3D 0) Index: gcc/c-family/c-common.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/c-family/c-common.h (revision 166026) +++ gcc/c-family/c-common.h (working copy) @@ -1045,6 +1045,8 @@ extern tree objc_build_setter_call (tree, tree); extern void objc_add_synthesize_declaration (location_t, tree); extern void objc_add_dynamic_declaration (location_t, tree); extern const char * objc_maybe_printable_name (tree, int); +extern bool objc_string_ref_type_p (tree); +extern void objc_check_format_arg (tree, tree); =20 /* The following are provided by the C and C++ front-ends, and called by ObjC/ObjC++. */ Index: gcc/c-family/c-format.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/c-family/c-format.h (revision 166026) +++ gcc/c-family/c-format.h (working copy) @@ -73,7 +73,10 @@ enum FMT_FLAG_EMPTY_PREC_OK =3D 64, /* Gaps are allowed in the arguments with $ operand numbers if all arguments are pointers (scanf). */ - FMT_FLAG_DOLLAR_GAP_POINTER_OK =3D 128 + FMT_FLAG_DOLLAR_GAP_POINTER_OK =3D 128, + /* The format arg is an opaque object that will be parsed by an external + facility. */ + FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL =3D 256 /* Not included here: details of whether width or precision may occur (controlled by width_char and precision_char); details of whether '*' can be used for these (width_type and precision_type); details Index: gcc/c-family/stub-objc.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/c-family/stub-objc.c (revision 166026) +++ gcc/c-family/stub-objc.c (working copy) @@ -430,3 +430,15 @@ void objc_write_global_declarations (void) { } + +bool +objc_string_ref_type_p (tree ARG_UNUSED (strp)) +{ + return false; +} + +void +objc_check_format_arg (tree ARG_UNUSED (format_arg),=20 + tree ARG_UNUSED (args_list)) +{ +} Index: gcc/target.def =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/target.def (revision 166026) +++ gcc/target.def (working copy) @@ -2554,10 +2554,40 @@ DEFHOOK bool, (size_t code, const char *arg, int value), default_handle_c_option) =20 +/* Targets may provide a string object type that can be used within + and between c, c++, and objective-c dialects. */ + DEFHOOK -(objc_construct_string, - "Construct a constant string representation for @var{string}", +(objc_construct_string_object, + "Targets may provide a string object type that can be used within\ + and between c, c++ and their respective objective-c dialects.\ + A string object might, for example, embed encoding and length information= .\ + These objects are considered opaque to the compiler and handled as refere= nces.\ + An ideal implementation makes the composition of the string object\ + match that of the objective-c @code{NSString} (@code{NXString} for GNUSte= p),\ + allowing efficient interworking between c-only and objective-c code.\ + If a target implements string objects then this hook should return a\ + reference to such an object constructed from the normal 'c' string\ + representation provided in @var{string}.\ + At present, the hook is used by objective-c only, to obtain a\ + common-format string object when the target provides one.", tree, (tree string), NULL) +=20 +DEFHOOK +(string_object_ref_type_p, + "If a target implements string objects then this hook should return\ + 'true' if @var{stringref} is a valid reference to such an object.", + bool, (const_tree stringref), + hook_bool_const_tree_false) =20 +DEFHOOK +(check_string_object_format_arg, + "If a target implements string objects then this hook should should\ + provide a facility to check the function arguments in @var{args_list}\ + against the format specifiers in @var{format_arg} where the type of\ + @var{format_arg} is one recognized as a valid string reference type.", + void, (tree format_arg, tree args_list), + NULL) +=20 HOOK_VECTOR_END (C90_EMPTY_HACK) Index: gcc/objc/objc-act.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/objc/objc-act.c (revision 166026) +++ gcc/objc/objc-act.c (working copy) @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see =20 #include "c-family/c-common.h" #include "c-family/c-pragma.h" +#include "c-family/c-format.h" #include "flags.h" #include "langhooks.h" #include "objc-act.h" @@ -2631,9 +2632,9 @@ objc_build_string_object (tree string) literal. On Darwin (Mac OS X), for example, we may wish to obtain a= =20 constant CFString reference instead. At present, this is only supported for the NeXT runtime. */ - if (flag_next_runtime && targetcm.objc_construct_string) + if (flag_next_runtime && targetcm.objc_construct_string_object) { - tree constructor =3D (*targetcm.objc_construct_string) (string); + tree constructor =3D (*targetcm.objc_construct_string_object) (strin= g); if (constructor) return build1 (NOP_EXPR, objc_object_type, constructor); } @@ -11843,4 +11844,28 @@ objc_finish_foreach_loop (location_t location, tre /* Done by c-parser.c */ } =20 +/* Return true if we have an NxString object pointer. */ + +bool +objc_string_ref_type_p (tree strp) +{ + tree tmv; + if (!strp || TREE_CODE (strp) !=3D POINTER_TYPE) + return false; + + tmv =3D TYPE_MAIN_VARIANT (TREE_TYPE (strp)); + tmv =3D OBJC_TYPE_NAME (tmv); + return (tmv + && TREE_CODE (tmv) =3D=3D IDENTIFIER_NODE + && IDENTIFIER_POINTER (tmv) + && !strncmp (IDENTIFIER_POINTER (tmv), "NSString", 8)); +} + +/* At present the behavior of this is undefined and it does nothing. */ +void +objc_check_format_arg (tree ARG_UNUSED (format_arg),=20 + tree ARG_UNUSED (args_list)) +{ +} + #include "gt-objc-objc-act.h" Index: gcc/testsuite/gcc.dg/darwin-cfstring-format-1.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/testsuite/gcc.dg/darwin-cfstring-format-1.c (revision 0) +++ gcc/testsuite/gcc.dg/darwin-cfstring-format-1.c (revision 0) @@ -0,0 +1,36 @@ +/* Check CFString format extensions. */ +/* { dg-do compile { target *-*-darwin* } } */ +/* { dg-options "-Wall" } */ + +extern int printf (const char *fmt, ...); + +typedef const struct __CFString * CFStringRef; + +#ifdef __CONSTANT_CFSTRINGS__ +#define CFSTR(cStr) ((CFStringRef) __builtin___CFStringMakeConstantString= ("" cStr "")) +#else +#error requires CFString +#endif + +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 formatt= ed" } */ + +int s3 (const char *fmt, ... ) __attribute__((format(__CFString__, 1, 2)))= ; /* { dg-error "format argument should be a .CFString. ref. 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 strin= g" } */ + +char *s5 (char dum, char *fmt1, ... ) __attribute__((format_arg(2))) ; /* = OK */ +CFStringRef s6 (CFStringRef dum, CFStringRef fmt1, ... ) __attribute__((fo= rmat_arg(2))) ; /* OK */ + +char *s7 (int dum, void *fmt1, ... ) __attribute__((format_arg(2))) ; /* {= dg-error "format string argument is not a string type" } */ +int s8 (CFStringRef dum, CFStringRef fmt1, ... ) __attribute__((format_arg= (2))) ; /* { dg-error "function does not return string type" } */ + +void foo (void) +{ + CFStringRef notchk =3D CFSTR ("here is an unchecked %d %s string"); + s1 (notchk, 5, 6, 7); + printf("this one is checked %d %s", 3, 4, 5); /* { dg-warning "format .%= s. expects type .char .., but argument 3 has type .int." } */ + /* { dg-warning "too many arguments for format" "" { target *-*-* } 33 = } */ + printf(s5 (1, "and so is this %d %d %s", 3, 4, "hey", 6), 5, 6, 12);/* {= dg-warning "format .%s. expects type .char .., but argument 4 has type .in= t." } */ +} \ No newline at end of file Index: gcc/testsuite/gcc.dg/warn-nsstring.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/testsuite/gcc.dg/warn-nsstring.c (revision 0) +++ gcc/testsuite/gcc.dg/warn-nsstring.c (revision 0) @@ -0,0 +1,7 @@ +/* Check that the NSString format extension is rejected in c. */ +/* { dg-do compile } */ + +extern void NSLog (void *fmt, ...) __attribute__((format(__NSString__, 1, = 2))); /* { dg-warning "is only allowed in Objective-C dialects" } */ +extern void NSLog1 (void *fmt, ...) __attribute__((format(NSString, 1, 2))= ); /* { dg-warning "is only allowed in Objective-C dialects" } */ + + Index: gcc/testsuite/objc.dg/property/property-3.m =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/testsuite/objc.dg/property/property-3.m (revision 166026) +++ gcc/testsuite/objc.dg/property/property-3.m (working copy) @@ -6,6 +6,9 @@ /* { dg-require-effective-target ilp32 } */ /* Force ABI =3D 0 in the NeXT headers, also suppress deprecation warnings= . */ /* { dg-options "-framework Foundation -fobjc-exceptions -mmacosx-version-= min=3D10.4 -Wno-deprecated-declarations" } */ +/* Darwin10's linker emits a warning that the constant strings are incompa= tible with writable ones. + well, we don't implement writeable ones at this juncture. */ +/* { dg-options "-framework Foundation -fobjc-exceptions -mmacosx-version-= min=3D10.4 -Wno-deprecated-declarations -Wl,-w" { target *-*-darwin[123]* }= } */ =20 #include #include Index: gcc/testsuite/objc.dg/property/property-2.m =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/testsuite/objc.dg/property/property-2.m (revision 166026) +++ gcc/testsuite/objc.dg/property/property-2.m (working copy) @@ -6,6 +6,9 @@ /* { dg-require-effective-target ilp32 } */ /* Force ABI =3D 0 in the NeXT headers, also suppress deprecation warnings= . */ /* { dg-options "-framework Foundation -fobjc-exceptions -mmacosx-version-= min=3D10.4 -Wno-deprecated-declarations" } */ +/* Darwin10's linker emits a warning that the constant strings are incompa= tible with writable ones. + well, we don't implement writeable ones at this juncture. */ +/* { dg-options "-framework Foundation -fobjc-exceptions -mmacosx-version-= min=3D10.4 -Wno-deprecated-declarations -Wl,-w" { target *-*-darwin[123]* }= } */ =20 #include #include Index: gcc/testsuite/objc.dg/torture/strings/const-cfstring-1.m =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/testsuite/objc.dg/torture/strings/const-cfstring-1.m (revision 1660= 26) +++ gcc/testsuite/objc.dg/torture/strings/const-cfstring-1.m (working copy) @@ -9,6 +9,9 @@ /* { dg-skip-if "NeXT only" { *-*-* } { "-fgnu-runtime" } { "" } } */ /* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc= 2 } } } { "-fnext-runtime" } { "" } } */ /* { dg-options "-mconstant-cfstrings -framework Cocoa" } */ +/* Darwin10's linker emits a warning that the constant strings are incompa= tible with writable ones. + well, we don't implement writable ones at this juncture. */ +/* { dg-options "-mconstant-cfstrings -framework Cocoa -Wl,-w" { target *-= *-darwin[123]* } } */ =20 #import #import Index: gcc/testsuite/objc.dg/fsf-nsstring-format-1.m =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/testsuite/objc.dg/fsf-nsstring-format-1.m (revision 0) +++ gcc/testsuite/objc.dg/fsf-nsstring-format-1.m (revision 0) @@ -0,0 +1,44 @@ +/* Check NSString format extensions. */ +/* { dg-do compile { target *-*-darwin* } } */ +/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */ +/* { dg-options "-Wall" } */ + +extern int printf (const char *fmt, ...); + +#ifndef __CONSTANT_CFSTRINGS__ +#error requires CFString +#endif + +typedef const struct __CFString * CFStringRef; +@class NSString; + +int s1 (NSString *fmt, ...) __attribute__((format(NSString, 1, 2))) ; /* O= K */ +/* A CFString can represent an NSString. */ +int s1a (CFStringRef fmt, ...) __attribute__((format(NSString, 1, 2))) ; /= * OK */ +/* But... it is possible that a CFString format might imply functionality = that + is not present in objective-c. */ +int s1b (NSString *fmt, ...) __attribute__((format(CFString, 1, 2))) ; /* = { dg-error "format argument should be a .CFString. ref" } */ + +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 s3 (const char *fmt, ... ) __attribute__((format(__NSString__, 1, 2)))= ; /* { dg-error "format argument should be a .NSString. ref. but a string = was found" } */ +int s4 (NSString *fmt, ... ) __attribute__((format(printf, 1, 2))) ; /* { = dg-error "found a .NSString. ref. but the format argument should be a strin= g" } */ + +char *s5 (char dum, char *fmt1, ... ) __attribute__((format_arg(2))) ; /* = OK */ +NSString *s6 (NSString *dum, NSString *fmt1, ... ) __attribute__((format_a= rg(2))) ; /* OK */ + +char *s7 (int dum, void *fmt1, ... ) __attribute__((format_arg(2))) ; /* {= dg-error "format string argument is not a string type" } */ +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))) ; /* O= K */ +NSString *s10 (int dum, NSString *fmt1, ... ) __attribute__((format_arg(2)= )) ; /* OK */ + +void foo (void) +{ + s1 (@"format not checked %d %s", 3, 4); + printf("this one is checked %d %s", 3, 4, 5); /* { dg-warning "format .%= s. expects type .char .., but argument 3 has type .int." } */ + /* { dg-warning "too many arguments for format" "" { target *-*-* } 41 = } */ + printf(s9 (1, "and so is this %d %d %s", 3, 4), 5, 6, 12); /* { dg-warni= ng "format .%s. expects type .char .., but argument 4 has type .int." } */ +} Index: gcc/testsuite/obj-c++.dg/property/property-2.mm =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/testsuite/obj-c++.dg/property/property-2.mm (revision 166026) +++ gcc/testsuite/obj-c++.dg/property/property-2.mm (working copy) @@ -5,6 +5,9 @@ /* { dg-require-effective-target ilp32 } */ /* Force ABI =3D 0 in the NeXT headers, also suppress deprecation warnings= . */ /* { dg-options "-framework Foundation -fobjc-exceptions -mmacosx-version-= min=3D10.4 -Wno-deprecated-declarations" } */ +/* Darwin10's linker emits a warning that the constant strings are incompa= tible with writable ones. + well, we don't implement writeable ones at this juncture. */ +/* { dg-options "-framework Foundation -fobjc-exceptions -mmacosx-version-= min=3D10.4 -Wno-deprecated-declarations -Wl,-w" { target *-*-darwin[123]* }= } */ =20 #include #include Index: gcc/testsuite/obj-c++.dg/property/property-3.mm =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/testsuite/obj-c++.dg/property/property-3.mm (revision 166026) +++ gcc/testsuite/obj-c++.dg/property/property-3.mm (working copy) @@ -6,6 +6,9 @@ /* { dg-require-effective-target ilp32 } */ /* Force ABI =3D 0 in the NeXT headers, also suppress deprecation warnings= . */ /* { dg-options "-framework Foundation -fobjc-exceptions -mmacosx-version-= min=3D10.4 -Wno-deprecated-declarations" } */ +/* Darwin10's linker emits a warning that the constant strings are incompa= tible with writable ones. + well, we don't implement writeable ones at this juncture. */ +/* { dg-options "-framework Foundation -fobjc-exceptions -mmacosx-version-= min=3D10.4 -Wno-deprecated-declarations -Wl,-w" { target *-*-darwin[123]* }= } */ =20 #include #include Index: gcc/testsuite/obj-c++.dg/torture/strings/const-cfstring-1.mm =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/testsuite/obj-c++.dg/torture/strings/const-cfstring-1.mm (revision = 166026) +++ gcc/testsuite/obj-c++.dg/torture/strings/const-cfstring-1.mm (working c= opy) @@ -9,6 +9,9 @@ /* { dg-skip-if "NeXT only" { *-*-* } { "-fgnu-runtime" } { "" } } */ /* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc= 2 } } } { "-fnext-runtime" } { "" } } */ /* { dg-options "-mconstant-cfstrings -framework Cocoa" } */ +/* Darwin10's linker emits a warning that the constant strings are incompa= tible with writable ones. + well, we don't implement writable ones at this juncture. */ +/* { dg-options "-mconstant-cfstrings -framework Cocoa -Wl,-w" { target *-= *-darwin[123]* } } */ =20 #import #import Index: gcc/testsuite/obj-c++.dg/fsf-nsstring-format-1.mm =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/testsuite/obj-c++.dg/fsf-nsstring-format-1.mm (revision 0) +++ gcc/testsuite/obj-c++.dg/fsf-nsstring-format-1.mm (revision 0) @@ -0,0 +1,51 @@ +/* Check NSString format extensions. */ +/* { dg-do compile { target *-*-darwin* } } */ +/* { dg-skip-if "" { *-*-* } { "-fgnu-runtime" } { "" } } */ +/* { dg-options "-Wall" } */ + +#ifndef __CONSTANT_CFSTRINGS__ +#error requires CFString +#endif + +#ifdef __cplusplus +extern "C" { +#endif +extern int printf (const char *fmt, ...); +typedef const struct __CFString * CFStringRef; + +#ifdef __cplusplus +} +#endif + +@class NSString; + +int s1 (NSString *fmt, ...) __attribute__((format(NSString, 1, 2))) ; /* O= K */ +/* A CFString can represent an NSString. */ +int s1a (CFStringRef fmt, ...) __attribute__((format(NSString, 1, 2))) ; /= * OK */ +/* But... it is possible that a CFString format might imply functionality = that + is not present in objective-c. */ +int s1b (NSString *fmt, ...) __attribute__((format(CFString, 1, 2))) ; /* = { dg-error "format argument should be a .CFString. ref" } */ + +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 s3 (const char *fmt, ... ) __attribute__((format(__NSString__, 1, 2)))= ; /* { dg-error "format argument should be a .NSString. ref. but a string = was found" } */ +int s4 (NSString *fmt, ... ) __attribute__((format(printf, 1, 2))) ; /* { = dg-error "found a .NSString. ref. but the format argument should be a strin= g" } */ + +char *s5 (char dum, char *fmt1, ... ) __attribute__((format_arg(2))) ; /* = OK */ +NSString *s6 (NSString *dum, NSString *fmt1, ... ) __attribute__((format_a= rg(2))) ; /* OK */ + +char *s7 (int dum, void *fmt1, ... ) __attribute__((format_arg(2))) ; /* {= dg-error "format string argument is not a string type" } */ +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))) ; /* O= K */ +NSString *s10 (int dum, NSString *fmt1, ... ) __attribute__((format_arg(2)= )) ; /* OK */ + +void foo (void) +{ + s1 (@"this format not checked %d %s", 3, 4); + printf("this one is checked %d %s", 3, 4, 5); /* { dg-warning "format .%= s. expects type .char.., but argument 3 has type 'int'" } */ + /* { dg-warning "too many arguments for format" "" { target *-*-* } 48 = } */ + printf(s9 (1, (char *)"and so is this %d %d %s" , 3, 4, "hm"), 5, 6, 12)= ; /* { dg-warning "format .%s. expects type .char.., but argument 4 has typ= e .int." } */ +} Index: gcc/c-parser.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/c-parser.c (revision 166026) +++ gcc/c-parser.c (working copy) @@ -3257,9 +3257,12 @@ c_parser_attributes (c_parser *parser) /* Parse the attribute contents. If they start with an identifier which is followed by a comma or close parenthesis, then the arguments start with that - identifier; otherwise they are an expression list. */ + identifier; otherwise they are an expression list.=20=20 + In objective-c the identifier may be a classname. */ if (c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_token (parser)->id_kind =3D=3D C_ID_ID + && (c_parser_peek_token (parser)->id_kind =3D=3D C_ID_ID + || (c_dialect_objc ()=20 + && c_parser_peek_token (parser)->id_kind =3D=3D C_ID_CLASSNAME)) && ((c_parser_peek_2nd_token (parser)->type =3D=3D CPP_COMMA) || (c_parser_peek_2nd_token (parser)->type =3D=3D CPP_CLOSE_PAREN))) Index: gcc/config/darwin-c.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/config/darwin-c.c (revision 166026) +++ gcc/config/darwin-c.c (working copy) @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see #include "incpath.h" #include "c-family/c-common.h" #include "c-family/c-pragma.h" +#include "c-family/c-format.h" #include "diagnostic-core.h" #include "toplev.h" #include "flags.h" @@ -678,3 +679,37 @@ darwin_objc_construct_string (tree str) =20 return darwin_build_constant_cfstring (str); } + +/* The string ref type is created as CFStringRef by therefore, = we + must match for it explicitly, since it's outside the gcc code. */ + +bool +darwin_cfstring_ref_p (const_tree strp) +{ + tree tn; + if (!strp || TREE_CODE (strp) !=3D POINTER_TYPE) + return false; + + tn =3D TYPE_NAME (strp); + if (tn)=20 + tn =3D DECL_NAME (tn); + return (tn=20 + && IDENTIFIER_POINTER (tn) + && !strncmp (IDENTIFIER_POINTER (tn), "CFStringRef", 8)); +} + +/* At present the behavior of this is undefined and it does nothing. */ +void +darwin_check_cfstring_format_arg (tree ARG_UNUSED (format_arg),=20 + tree ARG_UNUSED (args_list)) +{ +} + +/* The extra format types we recognize. */ +const format_kind_info darwin_additional_format_types[] =3D { + { "CFString", NULL, NULL, NULL, NULL,=20 + NULL, NULL,=20 + FMT_FLAG_ARG_CONVERT|FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL, 0, 0, 0, 0, = 0, 0, + NULL, NULL + } +}; Index: gcc/config/darwin-protos.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/config/darwin-protos.h (revision 166026) +++ gcc/config/darwin-protos.h (working copy) @@ -96,7 +96,9 @@ extern void darwin_init_cfstring_builtins (unsigne extern tree darwin_fold_builtin (tree, int, tree *, bool); extern tree darwin_objc_construct_string (tree); extern bool darwin_cfstring_p (tree); -extern tree darwin_build_constant_cfstring (tree str); +extern bool darwin_cfstring_ref_p (const_tree); +extern void darwin_check_cfstring_format_arg (tree, tree); +extern tree darwin_build_constant_cfstring (tree); extern void darwin_enter_string_into_cfstring_table (tree); =20 extern void darwin_asm_output_anchor (rtx symbol); Index: gcc/config/darwin.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- gcc/config/darwin.h (revision 166026) +++ gcc/config/darwin.h (working copy) @@ -1057,9 +1057,18 @@ __enable_execute_stack (void *addr) /* We have target-specific builtins. */ #define TARGET_FOLD_BUILTIN darwin_fold_builtin =20 -#define TARGET_OBJC_CONSTRUCT_STRING \ +#define TARGET_OBJC_CONSTRUCT_STRING_OBJECT \ darwin_objc_construct_string =20 +#define TARGET_STRING_OBJECT_REF_TYPE_P \ + darwin_cfstring_ref_p + +#define TARGET_N_FORMAT_TYPES 1 +#define TARGET_FORMAT_TYPES darwin_additional_format_types + +#define TARGET_CHECK_STRING_OBJECT_FORMAT_ARG \ + darwin_check_cfstring_format_arg + #define TARGET_HAS_TARGETCM 1 =20 #ifndef CROSS_DIRECTORY_STRUCTURE --Apple-Mail-221-728228882 Content-Type: text/plain; charset=US-ASCII; format=flowed Content-Transfer-Encoding: 7bit Content-length: 3 --Apple-Mail-221-728228882--