diff mbox

Updated: [Patch, c* ,ObjC*] handle string objects in format checking.

Message ID 98C75414-88E8-4E25-8943-27E332689B3E@sandoe-acoustics.co.uk
State New
Headers show

Commit Message

Iain Sandoe Oct. 28, 2010, 7:43 p.m. UTC
On 28 Oct 2010, at 19:21, Joseph S. Myers wrote:

> On Thu, 28 Oct 2010, IainS wrote:
>
>> 	* doc/extend.tex (format): Document NSString extension.
>
> It's .texi not .tex.

Indeed, a typo, and I should also have put:

	PR target/44981

at the start of each segment.

>> +	  /* 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));
>
> What is "ref."?  Is it a term of art in the relevant specification?   
> Or
> does the relevant specification say "reference"?  If "reference" is  
> the
> standard form, use that in the diagnostic.

Darwin consistently uses "CFStringRef" rather than CFString * (the  
CFString type itself is not available in end-user headers).
However, NSString is consistently referenced by NSString * (since  
NSString is a class).

Since the diagnostics have no cognizance of this, I was trying to make  
a solution that might seem more familiar to the recipient.

Since there's no standard as such, I've changed them all to  
'reference' since that's correct en.

>> +	    error ("found a %qD but the format argument should be a  
>> string",
>> +		   TYPE_NAME (ref));
>
> Will TYPE_NAME always be non-NULL here?  Or should you use %qT?
changed to qT.

>   In general you
> should check the formatting of this patch carefully; there seem to be
> several whitespace peculiarities.
I've re-scanned it and caught one more missing space.

>> +static const char *
>> +format_name (int format_num)
>
> Missing a comment describing the semantics of this function, its  
> argument
> and return value.
done

>> +{
>> +  if (format_num >= 0 && format_num < n_format_types)
>> +    return format_types[format_num].name;
>> +  else
>> +    return "invalid format type";
>
> No, returning an English fragment not marked up for translation is  
> not OK.
> If there is any valid or invalid input for which this case may be
> returned, please try to return a special value the caller can use to  
> pass
> an alternative full sentence to a diagnostic function; otherwise use
> gcc_unreachable here.
changed to gcc_unreachable (also in format_flags ()).

>> +static int
>> +format_flags (int format_num)
>
> Likewise needs comment.
done

>> +      /* Else we can't handle it and retire quietly.  */
>> +      return ;
>
> Stray space before ;.
done

>> @@ -1430,7 +1590,6 @@ check_format_arg (void *ctx, tree format_tree,
>>   free_alloc_pool (fwt_pool);
>> }
>>
>> -
>> /* 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
>
> Bogus diff hunk changing whitespace in code not otherwise touched.
done

I also realized that the copyright years needed updating on several of  
the files and the amended attachment has that addition too.

re-tested on darwin with the test-case text amendments to reflect the  
use of 'reference'.

Iain

>
> -- 
> Joseph S. Myers
> joseph@codesourcery.com

Comments

Nicola Pero Oct. 31, 2010, 7:30 p.m. UTC | #1
Iain

I have been working on the "format" attributes for Objective-C methods today and the main missing attribute
for Objective-C is really __attribute__ ((format (NSString, 1, 2))).  That attribute would be so incredibly
useful (I have been wanting to have it since I started using Objective-C 10 years ago). ;-)

Your patch does much of it (thanks a lot for you work on that), but not all of it.  Are you planning 
to finish it so we can include it in 4.6.0 ? :-)

I know Joseph was asking what the new format is - well, all we need is:

 * a new format type (NSString), identical to 'printf', which the exception that:

   - it is only available in Objective-C / Objective-C++

   - it accepts the additional syntax %@, which should match an Objective-C object.  Arguments matching %@ 
     are good if (objc_is_object_ptr(argument)).

   - the format string is not a C string, but an Objective-C string.  If it is a constant Objective-C string 
     (ie, generated by the parser using objc_build_string_object()), we can peek in, extract the C string
     and the rest is identical to the other format types.  If it is not a constant Objective-C string, we 
     can only check that the format string is of the right type; you've already added an objc_string_ref_type_p()
     that does that (PS: we may want to polish that check, but it can be done as a bugfix)

Your patch does most of it, and with a bit of polishing and a few additions could do it all.  I know that
stage 1 is closing today, but this patch was in the making, and I'd say it would be worth finishing it for
inclusion (unless Mike or Joseph disagree of course). :-)

I would really be good to have __attribute__ ((format (NSString, 1, 2))) in GCC 4.6.0.

Thanks

[by the way, I can help with writing the code, but I don't think you need help with that ...] ;-)


-----Original Message-----
From: "IainS" <developer@sandoe-acoustics.co.uk>
Sent: Thursday, 28 October, 2010 21:43
To: "Joseph S. Myers" <joseph@codesourcery.com>
Cc: "GCC Patches" <gcc-patches@gcc.gnu.org>, "Mike Stump" <mrs@gcc.gnu.org>, "Mike Stump" <mikestump@comcast.net>
Subject: Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.


On 28 Oct 2010, at 19:21, Joseph S. Myers wrote:

> On Thu, 28 Oct 2010, IainS wrote:
>
>> 	* doc/extend.tex (format): Document NSString extension.
>
> It's .texi not .tex.

Indeed, a typo, and I should also have put:

	PR target/44981

at the start of each segment.

>> +	  /* 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));
>
> What is "ref."?  Is it a term of art in the relevant specification?   
> Or
> does the relevant specification say "reference"?  If "reference" is  
> the
> standard form, use that in the diagnostic.

Darwin consistently uses "CFStringRef" rather than CFString * (the  
CFString type itself is not available in end-user headers).
However, NSString is consistently referenced by NSString * (since  
NSString is a class).

Since the diagnostics have no cognizance of this, I was trying to make  
a solution that might seem more familiar to the recipient.

Since there's no standard as such, I've changed them all to  
'reference' since that's correct en.

>> +	    error ("found a %qD but the format argument should be a  
>> string",
>> +		   TYPE_NAME (ref));
>
> Will TYPE_NAME always be non-NULL here?  Or should you use %qT?
changed to qT.

>   In general you
> should check the formatting of this patch carefully; there seem to be
> several whitespace peculiarities.
I've re-scanned it and caught one more missing space.

>> +static const char *
>> +format_name (int format_num)
>
> Missing a comment describing the semantics of this function, its  
> argument
> and return value.
done

>> +{
>> +  if (format_num >= 0 && format_num < n_format_types)
>> +    return format_types[format_num].name;
>> +  else
>> +    return "invalid format type";
>
> No, returning an English fragment not marked up for translation is  
> not OK.
> If there is any valid or invalid input for which this case may be
> returned, please try to return a special value the caller can use to  
> pass
> an alternative full sentence to a diagnostic function; otherwise use
> gcc_unreachable here.
changed to gcc_unreachable (also in format_flags ()).

>> +static int
>> +format_flags (int format_num)
>
> Likewise needs comment.
done

>> +      /* Else we can't handle it and retire quietly.  */
>> +      return ;
>
> Stray space before ;.
done

>> @@ -1430,7 +1590,6 @@ check_format_arg (void *ctx, tree format_tree,
>>   free_alloc_pool (fwt_pool);
>> }
>>
>> -
>> /* 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
>
> Bogus diff hunk changing whitespace in code not otherwise touched.
done

I also realized that the copyright years needed updating on several of  
the files and the amended attachment has that addition too.

re-tested on darwin with the test-case text amendments to reflect the  
use of 'reference'.

Iain




>
> -- 
> Joseph S. Myers
> joseph@codesourcery.com
Iain Sandoe Oct. 31, 2010, 7:46 p.m. UTC | #2
On 31 Oct 2010, at 19:30, Nicola Pero wrote:
> I have been working on the "format" attributes for Objective-C  
> methods today and the main missing attribute
> for Objective-C is really __attribute__ ((format (NSString, 1,  
> 2))).  That attribute would be so incredibly
> useful (I have been wanting to have it since I started using  
> Objective-C 10 years ago). ;-)

I saw the  patches posted, great!  :-)
(been side-tracked with darwin the last few days, so not much ObjC).

> Your patch does much of it (thanks a lot for you work on that), but  
> not all of it.  Are you planning
> to finish it so we can include it in 4.6.0 ? :-)

It's awaiting, hopefully final or close to final, review of: http://gcc.gnu.org/ml/gcc-patches/2010-10/msg02432.html

I sincerely hope we can get it into 4.6 too - since, in addition to  
ObjC,  it also makes FSF gcc much more useful on Darwin 10.

----
FWIW:

The actual scanning of the format strings is now local to ObjC  
(there's a stub routine added by the patch) and additions to carry  
that out would fall under whatever rules Mike wishes to invoke.

I don't think we should delay implementing the framework to wait to  
fill in that particular aspect --- the current offering does allow  
syntax-checking to work and simply treats the format string in the  
same manner as a non-literal.

(I also believe we need to take care not to paint ourselves into a  
corner tho' - since the Apple version of ObjC does not define this  
operation yet).

.. perhaps, OTOH,  we could lead the way :-)

cheers
Iain
Nicola Pero Oct. 31, 2010, 7:59 p.m. UTC | #3
> The actual scanning of the format strings is now local to ObjC  
> (there's a stub routine added by the patch) and additions to carry  
> that out would fall under whatever rules Mike wishes to invoke.

Wouldn't we reuse the existing routines and simply add %@ ?


> (I also believe we need to take care not to paint ourselves into a  
> corner tho' - since the Apple version of ObjC does not define this  
> operation yet).

What do you mean ?  __attribute__((format (NSString, 1, 2))) works
on Apple (using LLVM I think, I don't have an Apple but I know it's
there) and it works as expected.  The standard example is NSLog 
(in much the same way as the standard example of the printf format 
is printf) and that is very well-defined.  GNUstep has NSLog and I can't
wait for the compiler to check that the arguments passed to NSLog
match the format string. ;-)

And since I implemented format attributes for methods, we should immediately
be able to have the compiler check [NSString -stringWithFormat:] as well ...

Thanks
Iain Sandoe Oct. 31, 2010, 8:18 p.m. UTC | #4
On 31 Oct 2010, at 19:59, Nicola Pero wrote:

>
>> The actual scanning of the format strings is now local to ObjC
>> (there's a stub routine added by the patch) and additions to carry
>> that out would fall under whatever rules Mike wishes to invoke.
>
> Wouldn't we reuse the existing routines and simply add %@ ?

Hm.
I think to double-check the doc.
IIRC there were some subtle differences from c. (on NeXT, at least)...

>> (I also believe we need to take care not to paint ourselves into a
>> corner tho' - since the Apple version of ObjC does not define this
>> operation yet).
>
> What do you mean ?  __attribute__((format (NSString, 1, 2))) works
> on Apple (using LLVM I think, I don't have an Apple but I know it's
> there) and it works as expected.  The standard example is NSLog
> (in much the same way as the standard example of the printf format
> is printf) and that is very well-defined.  GNUstep has NSLog and I  
> can't
> wait for the compiler to check that the arguments passed to NSLog
> match the format string. ;-)

Hm - maybe sth LLVM-specific.. I've not looked too hard at that code.

I've got the latest XCode on Darwin 9 & 10...

apple gcc-4.2.1 (darwin9 & darwin10) both accept .... format(__  
NSString__ ... and barf on ... format(NSString ...

AFAICT it does not check the string when __ NSString__ is used. [-Wall]

and, as Joseph prompted me to check, the ObjC doc. (at least the copy  
I d/loaded) does not specifically refer to this attribute.

If you can get it to work with the test-suite additions from the patch  
- or point me at somewhere that publishes an expectation
- pls. send me the relevant info offlist.

(I don't believe it makes any difference to our game-plan -- it's  
actually helpful if it is specified for NeXT).

cheers
Iain
Iain Sandoe Oct. 31, 2010, 8:41 p.m. UTC | #5
On 31 Oct 2010, at 20:18, IainS wrote:
>> What do you mean ?  __attribute__((format (NSString, 1, 2))) works
>> on Apple (using LLVM I think, I don't have an Apple but I know it's
>> there) and it works as expected.  The standard example is NSLog
>> (in much the same way as the standard example of the printf format
>> is printf) and that is very well-defined.  GNUstep has NSLog and I  
>> can't
>> wait for the compiler to check that the arguments passed to NSLog
>> match the format string. ;-)
>
> Hm - maybe sth LLVM-specific.. I've not looked too hard at that code.

it works with clang on darwin10 - OK that's handy, a reference platform.

Iain
Joseph Myers Nov. 5, 2010, 4:57 p.m. UTC | #6
On Thu, 28 Oct 2010, IainS wrote:

> +@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 will be parsed for correct syntax
> +and format argument types.  However, parsing of the format string itself is currently undefined
> +and will not be carried out by this version of the compiler.  
> +
> +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
> +available on Darwin (OSX) installations.   On such installations, the  XCode and system

Three spaces after ".", should be two; two before "XCode", should be one.

> +static int first_target_format_type;
> +static const char * format_name (int format_num);

No space after "*".

> +  if (format_types[info->format_type].flags 
> +		  & (int) FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL)

Bad indentation of the "&", should be in the column immediately after the 
"(" on the line above.

> +(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.\

C, C++, Objective-C.

> + A string object might, for example, embed encoding and length information.\
> + These objects are considered opaque to the compiler and handled as references.\
> + An ideal implementation makes the composition of the string object\
> + match that of the objective-c @code{NSString} (@code{NXString} for GNUStep),\

Objective-C.

> + allowing efficient interworking between c-only and objective-c code.\

C-only, Objective-C.

> + If a target implements string objects then this hook should return a\
> + reference to such an object constructed from the normal 'c' string\

`C' (in TeXinfo, ` is an opening quote and ' a closing one).

> + representation provided in @var{string}.\
> + At present, the hook is used by objective-c only, to obtain a\

Objective-C.

> +(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.",

@code{true}.

The C and documentation changes are OK with those fixes (and of course 
tm.texi regenerated).
diff mbox

Patch

Index: gcc/doc/extend.texi
===================================================================
--- 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}.
 
-The target may provide additional types of format checks.
+For Objective-C dialects, @code{NSString} (or @code{__NSString__}) is 
+recognized in the same context.  Declarations including these format attributes
+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 
+compiler.
+
+The target may also provide additional types of format checks.
 @xref{Target Format Checks,,Format Checks Specific to Particular
 Target Machines}.
 
@@ -2467,6 +2473,14 @@  requested by @option{-ansi} or an appropriate @opt
 is used.  @xref{C Dialect Options,,Options
 Controlling C Dialect}.
 
+For Objective-C dialects, the @code{format-arg} attribute may refer to an
+@code{NSString} reference for compatibility with the @code{format} attribute
+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, M32C and SH2A processors
 Use this attribute on the H8/300, H8/300H, and H8S to indicate that the specified
@@ -12408,6 +12422,7 @@  format attribute
 
 @menu
 * Solaris Format Checks::
+* Darwin Format Checks::
 @end menu
 
 @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 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 will be parsed for correct syntax
+and format argument types.  However, parsing of the format string itself is currently undefined
+and will not be carried out by this version of the compiler.  
+
+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
+available on Darwin (OSX) installations.   On such installations, the  XCode 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
===================================================================
--- 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
 
-@deftypefn {Target Hook} tree TARGET_OBJC_CONSTRUCT_STRING (tree @var{string})
-Construct a constant string representation for @var{string}
+@deftypefn {Target Hook} tree TARGET_OBJC_CONSTRUCT_STRING_OBJECT (tree @var{string})
+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 references. An ideal implementation makes the composition of the string object match that of the objective-c @code{NSString} (@code{NXString} for GNUStep), 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.
 @end deftypefn
 
+@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  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.
+@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
===================================================================
--- 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
 
-@hook TARGET_OBJC_CONSTRUCT_STRING
+@hook TARGET_OBJC_CONSTRUCT_STRING_OBJECT
 
+@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
===================================================================
--- 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"
 
 /* Set format warning options according to a -Wformat=n option.  */
 
@@ -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 = -1};
 
 typedef struct function_format_info
@@ -77,12 +79,38 @@  static int decode_format_type (const char *);
 
 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_name);
 static bool cmp_attribs (const char *tattr_name, const char *attr_name);
 
+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 string
+   objects validated by objc_string_ref_type_p ().  
+   Targets may also provide a string object type that can be used within c and 
+   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.
+   
+   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)
+{
+  return (strref != NULL
+	  && TREE_CODE (strref) == POINTER_TYPE
+	  && (TYPE_MAIN_VARIANT (TREE_TYPE (strref)) == 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 = 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;
     }
 
-  if (TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
-      || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
-	  != 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;
 }
 
-/* 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 suitable,
+   for the language dialect and target (in case the format attribute is in 
+   error).  When we know the specific reference type expected, this is also 
+   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;
 
   for (i = 1; i != format_num; i++)
     {
@@ -137,17 +170,78 @@  check_format_string (tree argument, unsigned HOST_
     }
 
   if (!argument
-      || TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE
-      || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument)))
-	  != char_type_node))
+      || !(ref = 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 = true;
       return false;
     }
 
-  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 = 
+    (TYPE_MAIN_VARIANT (TREE_TYPE (ref)) == char_type_node);
+
+  fmt_flags = format_flags (expected_format_type);
+  is_objc_sref = is_target_sref = false;
+  if (!is_char_ref)
+    is_objc_sref = 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%> reference but the format argument should"
+		   " be a string", format_name (gcc_objc_string_format_type));
+	  else
+	    error ("found a %qT but the format argument should be a string",
+		   ref);
+	  *no_add_attrs = true;
+	  return false;
+	}
+    }
+
+  /* We expect a string object type as the format arg.  */
+  if (is_char_ref)
+    {
+      error ("format argument should be a %<%s%> reference but"
+	     " a string was found", format_name (expected_format_type));
+      *no_add_attrs = true;
+      return false;
+    }
+  
+  /* We will assert that objective-c will support either its own string type
+     or the target-supplied variant.  */
+  if (!is_objc_sref)
+    is_target_sref = (*targetcm.string_object_ref_type_p) ((const_tree) ref);
+
+  if (expected_format_type == (int) gcc_objc_string_format_type 
+      && (is_objc_sref || is_target_sref))
+    return true;
+
+  /* We will allow a target string ref to match only itself.  */
+  if (first_target_format_type 
+      && expected_format_type >= first_target_format_type
+      && is_target_sref)
+    return true;
+  else
+    {
+      error ("format argument should be a %<%s%> reference", 
+	      format_name (expected_format_type));
+      *no_add_attrs = true;
+      return false;
+    }
+
+  gcc_unreachable ();
 }
 
 /* Verify EXPR is a constant, and store its value.
@@ -195,6 +289,16 @@  decode_format_attr (tree args, function_format_inf
       p = convert_format_name_to_system_name (p);
 
       info->format_type = decode_format_type (p);
+      
+      if (!c_dialect_objc ()
+	   && info->format_type == 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 = format_type_error;
+	  return false;
+	}
 
       if (info->format_type == 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_FLAG_ZERO_WIDTH_BAD|FMT_FLAG_DOLLAR_GAP_POINTER_OK,
@@ -812,6 +921,26 @@  typedef struct
   tree params;
 } format_check_context;
 
+/* Return the format name (as specified in the original table) for the format
+   type indicated by format_num.  */
+static const char *
+format_name (int format_num)
+{
+  if (format_num >= 0 && format_num < n_format_types)
+    return format_types[format_num].name;
+  gcc_unreachable ();
+}
+
+/* Return the format flags (as specified in the original table) for the format
+   type indicated by format_num.  */
+static int
+format_flags (int format_num)
+{
+  if (format_num >= 0 && format_num < n_format_types)
+    return format_types[format_num].flags;
+  gcc_unreachable ();
+}
+
 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 +1478,39 @@  check_format_arg (void *ctx, tree format_tree,
       return;
     }
   format_tree = TREE_OPERAND (format_tree, 0);
+  if (format_types[info->format_type].flags 
+		  & (int) FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL)
+    {
+      bool objc_str = (info->format_type == gcc_objc_string_format_type);
+      /* We cannot examine this string here - but we can check that it is
+         a valid type.  */
+      if (TREE_CODE (format_tree) != CONST_DECL
+	  || !((objc_str && objc_string_ref_type_p (TREE_TYPE (format_tree)))
+		|| (*targetcm.string_object_ref_type_p) 
+				     ((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 == 0)
+	    return;
+	  params = 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) == ARRAY_REF
       && host_integerp (TREE_OPERAND (format_tree, 1), 0)
       && (offset += tree_low_cst (TREE_OPERAND (format_tree, 1), 0)) >= 0)
@@ -2785,6 +2947,8 @@  handle_format_attribute (tree *node, tree ARG_UNUS
 	      TARGET_N_FORMAT_TYPES * sizeof (dynamic_format_types[0]));
 
       format_types = dynamic_format_types;
+      /* Provide a reference for the first potential external type.  */
+      first_target_format_type = n_format_types;
       n_format_types += TARGET_N_FORMAT_TYPES;
     }
 #endif
@@ -2799,7 +2963,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;
 
       if (info.first_arg_num != 0)
Index: gcc/c-family/c-common.h
===================================================================
--- 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);
 
 /* The following are provided by the C and C++ front-ends, and called by
    ObjC/ObjC++.  */
Index: gcc/c-family/c-format.h
===================================================================
--- gcc/c-family/c-format.h	(revision 166026)
+++ gcc/c-family/c-format.h	(working copy)
@@ -1,6 +1,6 @@ 
 /* Check calls to formatted I/O functions (-Wformat).
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2007, 2008 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2007, 2008, 2010 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -73,7 +73,10 @@  enum
   FMT_FLAG_EMPTY_PREC_OK = 64,
   /* Gaps are allowed in the arguments with $ operand numbers if all
      arguments are pointers (scanf).  */
-  FMT_FLAG_DOLLAR_GAP_POINTER_OK = 128
+  FMT_FLAG_DOLLAR_GAP_POINTER_OK = 128,
+  /* The format arg is an opaque object that will be parsed by an external
+     facility.  */
+  FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL = 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
===================================================================
--- gcc/c-family/stub-objc.c	(revision 166026)
+++ gcc/c-family/stub-objc.c	(working copy)
@@ -2,7 +2,7 @@ 
    that are called from within the C and C++ front-ends,
    respectively.
    Copyright (C) 1991, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-   2004, 2005, 2007, 2009 Free Software Foundation, Inc.
+   2004, 2005, 2007, 2009, 2010 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -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), 
+		       tree ARG_UNUSED (args_list))
+{
+}
Index: gcc/target.def
===================================================================
--- 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)
 
+/* 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 references.\
+ An ideal implementation makes the composition of the string object\
+ match that of the objective-c @code{NSString} (@code{NXString} for GNUStep),\
+ 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)
+ 
+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)
 
+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)
+ 
 HOOK_VECTOR_END (C90_EMPTY_HACK)
Index: gcc/objc/objc-act.c
===================================================================
--- 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
 
 #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 
      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 = (*targetcm.objc_construct_string) (string);
+      tree constructor = (*targetcm.objc_construct_string_object) (string);
       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  */
 }
 
+/* Return true if we have an NxString object pointer.  */
+
+bool
+objc_string_ref_type_p (tree strp)
+{
+  tree tmv;
+  if (!strp || TREE_CODE (strp) != POINTER_TYPE)
+    return false;
+
+  tmv = TYPE_MAIN_VARIANT (TREE_TYPE (strp));
+  tmv = OBJC_TYPE_NAME (tmv);
+  return (tmv
+  	  && TREE_CODE (tmv) == 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), 
+		       tree ARG_UNUSED (args_list))
+{
+}
+
 #include "gt-objc-objc-act.h"
Index: gcc/testsuite/gcc.dg/darwin-cfstring-format-1.c
===================================================================
--- 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 formatted" } */
+
+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" } */
+
+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" } */
+int s8 (CFStringRef dum, CFStringRef fmt1, ... ) __attribute__((format_arg(2))) ; /* { dg-error "function does not return string type" } */
+
+void foo (void)
+{
+  CFStringRef notchk = 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 .int." } */
+}
\ No newline at end of file
Index: gcc/testsuite/gcc.dg/warn-nsstring.c
===================================================================
--- 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
===================================================================
--- 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 = 0 in the NeXT headers, also suppress deprecation warnings.  */
 /* { dg-options "-framework Foundation -fobjc-exceptions -mmacosx-version-min=10.4 -Wno-deprecated-declarations" } */
+/* Darwin10's linker emits a warning that the constant strings are incompatible with writable ones.
+   well, we don't implement writeable ones at this juncture.  */
+/* { dg-options "-framework Foundation -fobjc-exceptions -mmacosx-version-min=10.4 -Wno-deprecated-declarations -Wl,-w" { target *-*-darwin[123]* } } */
 
 #include <objc/objc-api.h>
 #include <Foundation/Foundation.h>
Index: gcc/testsuite/objc.dg/property/property-2.m
===================================================================
--- 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 = 0 in the NeXT headers, also suppress deprecation warnings.  */
 /* { dg-options "-framework Foundation -fobjc-exceptions -mmacosx-version-min=10.4 -Wno-deprecated-declarations" } */
+/* Darwin10's linker emits a warning that the constant strings are incompatible with writable ones.
+   well, we don't implement writeable ones at this juncture.  */
+/* { dg-options "-framework Foundation -fobjc-exceptions -mmacosx-version-min=10.4 -Wno-deprecated-declarations -Wl,-w" { target *-*-darwin[123]* } } */
 
 #include <objc/objc-api.h>
 #include <Foundation/Foundation.h>
Index: gcc/testsuite/objc.dg/torture/strings/const-cfstring-1.m
===================================================================
--- gcc/testsuite/objc.dg/torture/strings/const-cfstring-1.m	(revision 166026)
+++ 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 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
 /* { dg-options "-mconstant-cfstrings -framework Cocoa" } */
+/* Darwin10's linker emits a warning that the constant strings are incompatible with writable ones.
+   well, we don't implement writable ones at this juncture.  */
+/* { dg-options "-mconstant-cfstrings -framework Cocoa -Wl,-w" { target *-*-darwin[123]* } } */
 
 #import <Foundation/NSString.h>
 #import <CoreFoundation/CFString.h>
Index: gcc/testsuite/objc.dg/fsf-nsstring-format-1.m
===================================================================
--- 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))) ; /* OK */
+/* 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. reference" } */
+
+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. 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" } */
+
+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" } */
+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 */
+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-warning "format .%s. expects type .char .., but argument 4 has type .int." } */
+}
Index: gcc/testsuite/obj-c++.dg/property/property-2.mm
===================================================================
--- 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 = 0 in the NeXT headers, also suppress deprecation warnings.  */
 /* { dg-options "-framework Foundation -fobjc-exceptions -mmacosx-version-min=10.4 -Wno-deprecated-declarations" } */
+/* Darwin10's linker emits a warning that the constant strings are incompatible with writable ones.
+   well, we don't implement writeable ones at this juncture.  */
+/* { dg-options "-framework Foundation -fobjc-exceptions -mmacosx-version-min=10.4 -Wno-deprecated-declarations -Wl,-w" { target *-*-darwin[123]* } } */
 
 #include <objc/objc-api.h>
 #include <Foundation/Foundation.h>
Index: gcc/testsuite/obj-c++.dg/property/property-3.mm
===================================================================
--- 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 = 0 in the NeXT headers, also suppress deprecation warnings.  */
 /* { dg-options "-framework Foundation -fobjc-exceptions -mmacosx-version-min=10.4 -Wno-deprecated-declarations" } */
+/* Darwin10's linker emits a warning that the constant strings are incompatible with writable ones.
+   well, we don't implement writeable ones at this juncture.  */
+/* { dg-options "-framework Foundation -fobjc-exceptions -mmacosx-version-min=10.4 -Wno-deprecated-declarations -Wl,-w" { target *-*-darwin[123]* } } */
 
 #include <objc/objc-api.h>
 #include <Foundation/Foundation.h>
Index: gcc/testsuite/obj-c++.dg/torture/strings/const-cfstring-1.mm
===================================================================
--- 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 copy)
@@ -9,6 +9,9 @@ 
 /* { dg-skip-if "NeXT only" { *-*-* } { "-fgnu-runtime" } { "" } } */
 /* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */
 /* { dg-options "-mconstant-cfstrings -framework Cocoa" } */
+/* Darwin10's linker emits a warning that the constant strings are incompatible with writable ones.
+   well, we don't implement writable ones at this juncture.  */
+/* { dg-options "-mconstant-cfstrings -framework Cocoa -Wl,-w" { target *-*-darwin[123]* } } */
 
 #import <Foundation/NSString.h>
 #import <CoreFoundation/CFString.h>
Index: gcc/testsuite/obj-c++.dg/fsf-nsstring-format-1.mm
===================================================================
--- 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))) ; /* OK */
+/* 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. reference" } */
+
+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. 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" } */
+
+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" } */
+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 */
+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 type .int." } */
+}
Index: gcc/c-parser.c
===================================================================
--- 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.  
+	     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 == C_ID_ID
+	      && (c_parser_peek_token (parser)->id_kind == C_ID_ID
+		  || (c_dialect_objc () 
+		      && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
 	      && ((c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
 		  || (c_parser_peek_2nd_token (parser)->type
 		      == CPP_CLOSE_PAREN)))
Index: gcc/config/darwin-c.c
===================================================================
--- gcc/config/darwin-c.c	(revision 166026)
+++ gcc/config/darwin-c.c	(working copy)
@@ -1,5 +1,5 @@ 
 /* Darwin support needed only by C/C++ frontends.
-   Copyright (C) 2001, 2003, 2004, 2005, 2007, 2008
+   Copyright (C) 2001, 2003, 2004, 2005, 2007, 2008, 2010
    Free Software Foundation, Inc.
    Contributed by Apple Computer Inc.
 
@@ -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)
 
   return darwin_build_constant_cfstring (str);
 }
+
+/* The string ref type is created as CFStringRef by <CFBase.h> 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) != POINTER_TYPE)
+    return false;
+
+  tn = TYPE_NAME (strp);
+  if (tn) 
+    tn = DECL_NAME (tn);
+  return (tn 
+	  && 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), 
+				  tree ARG_UNUSED (args_list))
+{
+}
+
+/* The extra format types we recognize.  */
+const format_kind_info darwin_additional_format_types[] = {
+  { "CFString",   NULL,  NULL, NULL, NULL, 
+    NULL, NULL, 
+    FMT_FLAG_ARG_CONVERT|FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL, 0, 0, 0, 0, 0, 0,
+    NULL, NULL
+  }
+};
Index: gcc/config/darwin-protos.h
===================================================================
--- gcc/config/darwin-protos.h	(revision 166026)
+++ gcc/config/darwin-protos.h	(working copy)
@@ -1,5 +1,5 @@ 
 /* Prototypes.
-   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2010
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -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);
 
 extern void darwin_asm_output_anchor (rtx symbol);
Index: gcc/config/darwin.h
===================================================================
--- 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
 
-#define TARGET_OBJC_CONSTRUCT_STRING \
+#define TARGET_OBJC_CONSTRUCT_STRING_OBJECT \
   darwin_objc_construct_string
 
+#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
 
 #ifndef CROSS_DIRECTORY_STRUCTURE