public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [Patch, c* ,ObjC*] handle string objects in format checking.
@ 2010-10-24 15:09 IainS
  2010-10-24 17:13 ` Joseph S. Myers
  0 siblings, 1 reply; 29+ messages in thread
From: IainS @ 2010-10-24 15:09 UTC (permalink / raw)
  To: GCC Patches; +Cc: Mike Stump, Joseph S. Myers

[-- Attachment #1: Type: text/plain, Size: 2436 bytes --]

Hello,

ObjC* (currently for NeXT, but potentially also with GNU runtime) can  
use string object references in format args.
Darwin [and potentially other platforms, if the GNUstep people wish to  
implement] can also use CFStrings from c* in the same context (as  
these are essentially the same beast internally) and thus share with  
ObjC*.

Since Dawin10 was released some important system headers make use of  
CFStringRefs, which is a bit of show-stopper for [c, c++ and ObjC*]   
CoreFoundation on Darwin10 -- this is PR44981.

We have now implemented CFString on FSF gcc and this patch adds use of  
those in formatters.

ObjC strings are implemented in the normal way, with function calls  
and a stub in stub-objc.
CFString is handled with a c-family target hook.

Clearly, the main part of this is darwin and ObjC*-specific...

**  however we do need review and approval for the gcc/c-family changes.

boostrapped & checked on darwin9 & 10 (clears the remaining header  
parse errors there) and on x86_64-unk-linux (to ensure no changes to  
objc results).

OK for trunk?
Iain


gcc:

	PR target/44981

	* doc/tm.texi: Document TARGET_STRING_OBJECT_REF_TYPE_P hook.
	* doc/tm.texi.in: TARGET_STRING_OBJECT_REF_TYPE_P: New.
	* c-family/c-format.c (format_type): Add gcc_objc_string_format_type.
	(valid_stringptr_type_p): New.
	(handle_format_arg_attribute): Use valid_stringptr_type_p().
	(check_format_string): Likewise.
	(format_types_orig): Add NSString.
	* c-family/c-common.h (objc_string_ref_type_p): New prototype.
	* c-family/stub-objc.c: New stub.
	* config/darwin-c.c (darwin_cfstring_ref_p): New.
	* config/darwin-protos.h: Correct arg list for  
darwin_build_constant_cfstring()
	(darwin_cfstring_ref_p): New prototype.
	* config/darwin.c: Add c-format.h.
	(darwin_additional_format_types): New.
	* config/darwin.h: (TARGET_STRING_OBJECT_REF_TYPE_P) New.
	(TARGET_N_FORMAT_TYPES): New.
	(TARGET_FORMAT_TYPES): New.
	* target.def (string_object_ref_type_p): New hook.
	

gcc/objc:

	PR target/44981

	* objc/objc-act.c (objc_string_ref_type_p): New.


gcc/testsuite:

	PR target/44981

	* obj-c++.dg/property/property-2.m: Adjust for darwin10 linker warning.
	* obj-c++.dg/property/property-3.mm: Likewise.
	* obj-c++.dg/torture/strings/const-cfstring-1.mm: Likewise.
	* objc.dg/property/property-3.m: Likewise.
	* objc.dg/property/property-2.m: Likewise.
	* objc.dg/torture/strings/const-cfstring-1.m: Likewise.


[-- Attachment #2: 165889-string-object-formats.txt --]
[-- Type: text/plain, Size: 14681 bytes --]

Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(revision 165889)
+++ gcc/doc/tm.texi	(working copy)
@@ -746,6 +746,10 @@ should use @code{TARGET_HANDLE_C_OPTION} instead.
 Construct a constant string representation for @var{string}
 @end deftypefn
 
+@deftypefn {Target Hook} bool TARGET_STRING_OBJECT_REF_TYPE_P (const_tree @var{stringref})
+Check for a valid string object reference type in @var{stringref}
+@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 165889)
+++ gcc/doc/tm.texi.in	(working copy)
@@ -744,6 +744,8 @@ should use @code{TARGET_HANDLE_C_OPTION} instead.
 
 @hook TARGET_OBJC_CONSTRUCT_STRING
 
+@hook TARGET_STRING_OBJECT_REF_TYPE_P
+
 @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 165889)
+++ 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"
 \f
 /* 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
@@ -83,6 +85,19 @@ static bool get_constant (tree expr, unsigned HOST
 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);
 
+/* Check that we have a pointer to a string, or string object for objc and
+   targets that support them in c*.  */
+
+static bool
+valid_stringptr_type_p (tree strp)
+{
+  return (strp != NULL
+	  && TREE_CODE (strp) == POINTER_TYPE
+	  && (TYPE_MAIN_VARIANT (TREE_TYPE (strp)) == char_type_node
+	      || objc_string_ref_type_p (strp)
+	      || (*targetcm.string_object_ref_type_p) ((const_tree)strp)));
+}
+
 /* Handle a "format_arg" attribute; arguments as in
    struct attribute_spec.handler.  */
 tree
@@ -108,9 +123,7 @@ handle_format_arg_attribute (tree *node, tree ARG_
 	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");
@@ -136,10 +149,8 @@ check_format_string (tree argument, unsigned HOST_
       argument = TREE_CHAIN (argument);
     }
 
-  if (!argument
-      || TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE
-      || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument)))
-	  != char_type_node))
+  if (! argument
+        || !valid_stringptr_type_p (TREE_VALUE (argument)))
     {
       if (!(flags & (int) ATTR_FLAG_BUILT_IN))
 	error ("format string argument not a string type");
@@ -750,6 +761,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, 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,
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 165889)
+++ gcc/c-family/c-common.h	(working copy)
@@ -1049,6 +1049,7 @@ 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);
 
 /* The following are provided by the C and C++ front-ends, and called by
    ObjC/ObjC++.  */
Index: gcc/c-family/stub-objc.c
===================================================================
--- gcc/c-family/stub-objc.c	(revision 165889)
+++ gcc/c-family/stub-objc.c	(working copy)
@@ -426,3 +426,9 @@ void
 objc_write_global_declarations (void)
 {
 }
+
+bool
+objc_string_ref_type_p (tree ARG_UNUSED (strp))
+{
+   return false;
+}
Index: gcc/config/darwin-c.c
===================================================================
--- gcc/config/darwin-c.c	(revision 165889)
+++ gcc/config/darwin-c.c	(working copy)
@@ -678,3 +678,21 @@ 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));
+}
Index: gcc/config/darwin-protos.h
===================================================================
--- gcc/config/darwin-protos.h	(revision 165889)
+++ gcc/config/darwin-protos.h	(working copy)
@@ -96,7 +96,8 @@ 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 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.c
===================================================================
--- gcc/config/darwin.c	(revision 165889)
+++ gcc/config/darwin.c	(working copy)
@@ -50,6 +50,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "debug.h"
 #include "obstack.h"
 #include "lto-streamer.h"
+#include "c-family/c-format.h"
 
 /* Darwin supports a feature called fix-and-continue, which is used
    for rapid turn around debugging.  When code is compiled with the
@@ -2269,4 +2270,13 @@ darwin_enter_string_into_cfstring_table (tree str)
     }
 }
 
+/* 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, 0, 0, 0, 0, 0, 0,
+    NULL, NULL
+  }
+};
+  
 #include "gt-darwin.h"
Index: gcc/config/darwin.h
===================================================================
--- gcc/config/darwin.h	(revision 165889)
+++ gcc/config/darwin.h	(working copy)
@@ -1060,6 +1060,12 @@ __enable_execute_stack (void *addr)
 #define TARGET_OBJC_CONSTRUCT_STRING \
   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_HAS_TARGETCM 1
 
 #ifndef CROSS_DIRECTORY_STRUCTURE
Index: gcc/objc/objc-act.c
===================================================================
--- gcc/objc/objc-act.c	(revision 165889)
+++ gcc/objc/objc-act.c	(working copy)
@@ -11801,4 +11801,21 @@ objc_finish_foreach_loop (location_t location, tre
   /* Done by c-parser.c  */
 }
 
+/* Return true if we have an NxString object pointer.
+   Implemented only for NSString Objects so far.  */
+
+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 
+	  && IDENTIFIER_POINTER (tmv)
+	  && !strncmp (IDENTIFIER_POINTER (tmv), "NSString", 8));
+}
+
 #include "gt-objc-objc-act.h"
Index: gcc/target.def
===================================================================
--- gcc/target.def	(revision 165889)
+++ gcc/target.def	(working copy)
@@ -2539,5 +2539,11 @@ DEFHOOK
  "Construct a constant string representation for @var{string}",
  tree, (tree string),
  NULL)
-
+ 
+DEFHOOK
+(string_object_ref_type_p,
+ "Check for a valid string object reference type in @var{stringref}",
+ bool, (const_tree stringref),
+ hook_bool_const_tree_false)
+ 
 HOOK_VECTOR_END (C90_EMPTY_HACK)
Index: gcc/testsuite/obj-c++.dg/property/property-2.mm
===================================================================
--- gcc/testsuite/obj-c++.dg/property/property-2.mm	(revision 165889)
+++ 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 165889)
+++ 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 165889)
+++ 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/objc.dg/property/property-3.m
===================================================================
--- gcc/testsuite/objc.dg/property/property-3.m	(revision 165889)
+++ 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 165889)
+++ 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 165889)
+++ 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>

[-- Attachment #3: Type: text/plain, Size: 3 bytes --]





^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-10-24 15:09 [Patch, c* ,ObjC*] handle string objects in format checking IainS
@ 2010-10-24 17:13 ` Joseph S. Myers
  2010-10-24 19:08   ` IainS
  0 siblings, 1 reply; 29+ messages in thread
From: Joseph S. Myers @ 2010-10-24 17:13 UTC (permalink / raw)
  To: IainS; +Cc: GCC Patches, Mike Stump

On Sun, 24 Oct 2010, IainS wrote:

> 	* c-family/c-format.c (format_type): Add gcc_objc_string_format_type.
> 	(valid_stringptr_type_p): New.
> 	(handle_format_arg_attribute): Use valid_stringptr_type_p().
> 	(check_format_string): Likewise.
> 	(format_types_orig): Add NSString.
> 	* c-family/c-common.h (objc_string_ref_type_p): New prototype.

(c-family/ has its own ChangeLog.)

Is there something missing here that will be in a followup patch?

You're adding a new format style, "NSString".  There's no documentation 
for what it means, no testcases for this format style checking, and the 
table entry appears to be a dummy table entry.  What happens when the 
compiler tries to check a call to a function declared to use that type of 
format?  Are all the NULL table entries safe or will it try to dereference 
them?  Do these strings appear as STRING_CST?  If not, where is the code 
that knows how to extract the characters from them for checking?

> +/* Check that we have a pointer to a string, or string object for objc and
> +   targets that support them in c*.  */

What does "targets that support them in c*" mean?  You should explicitly 
state what the return value means, and what STRP is.

> +	      || (*targetcm.string_object_ref_type_p) ((const_tree)strp)));

Missing space in cast.

> +  if (! valid_stringptr_type_p (TREE_TYPE (type)))

Excess space in unary !.

> +  if (! argument

Likewise.

> Index: gcc/config/darwin.c
> ===================================================================
> --- gcc/config/darwin.c	(revision 165889)
> +++ gcc/config/darwin.c	(working copy)
> @@ -50,6 +50,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "debug.h"
>  #include "obstack.h"
>  #include "lto-streamer.h"
> +#include "c-family/c-format.h"

There are a few legacy c-* includes in target .c files that aren't 
c-family-specific, but you shouldn't add to them in new patches; why can't 
this go in darwin-c.c?

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-10-24 17:13 ` Joseph S. Myers
@ 2010-10-24 19:08   ` IainS
  2010-10-24 19:25     ` Joseph S. Myers
  0 siblings, 1 reply; 29+ messages in thread
From: IainS @ 2010-10-24 19:08 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: GCC Patches, Mike Stump

Hello Joseph,
Thanks for the quick review,

On 24 Oct 2010, at 15:26, Joseph S. Myers wrote:

> On Sun, 24 Oct 2010, IainS wrote:
>
>> 	* c-family/c-format.c (format_type): Add  
>> gcc_objc_string_format_type.
>> 	(valid_stringptr_type_p): New.
>> 	(handle_format_arg_attribute): Use valid_stringptr_type_p().
>> 	(check_format_string): Likewise.
>> 	(format_types_orig): Add NSString.
>> 	* c-family/c-common.h (objc_string_ref_type_p): New prototype.
>
> (c-family/ has its own ChangeLog.)
sorry, brainstorm... too late at night when I wrote the changelog.

> Is there something missing here that will be in a followup patch?

I don't believe so.

> You're adding a new format style, "NSString".  There's no  
> documentation
> for what it means,

NSString is documented in the relevant Objective C documentation.
- should I add a cross-reference here ?
or simply state what it is?

(it matches the enum  format_type  gcc_objc_string_format_type)

> no testcases for this format style checking,

the tests are already present (in test-cases that currently fail for  
NeXT ObjC).

I can also make additional stand-alone ones as a follow-up if that is  
deemed worthwhile.

> and the
> table entry appears to be a dummy table entry.  What happens when the
> compiler tries to check a call to a function declared to use that  
> type of
> format?  Are all the NULL table entries safe

I believe so - the purpose is simply to check consistency of  
definition - there is no attempt to look within the entities themselves.

> or will it try to dereference them?

IFAIU, it should not.

> Do these strings appear as STRING_CST?

no - the references are to an opaque type (which is what is being  
checked for in the code called from valid_stringptr_type_p()).

>  If not, where is the code
> that knows how to extract the characters from them for checking?

ObjC* code that would use such an NSString reference (or the c* code  
that would use a CFString reference) must know how to deal with the  
relevant class reference - there is no code to parse such a string  
within c-family/

(for example, it is _not_ intended that printf should be able to  
handle a NSString - and to try to do so would result in a parse error).

>> +/* Check that we have a pointer to a string, or string object for  
>> objc and
>> +   targets that support them in c*.  */
>
> What does "targets that support them in c*" mean?  You should  
> explicitly
> state what the return value means, and what STRP is.
>
>> +	      || (*targetcm.string_object_ref_type_p) ((const_tree)strp)));
>
> Missing space in cast.
>
>> +  if (! valid_stringptr_type_p (TREE_TYPE (type)))
>
> Excess space in unary !.
>
>> +  if (! argument
>
> Likewise.

all noted, thanks.

>
>> Index: gcc/config/darwin.c
>> ===================================================================
>> --- gcc/config/darwin.c	(revision 165889)
>> +++ gcc/config/darwin.c	(working copy)
>> @@ -50,6 +50,7 @@ along with GCC; see the file COPYING3.  If not see
>> #include "debug.h"
>> #include "obstack.h"
>> #include "lto-streamer.h"
>> +#include "c-family/c-format.h"
>
> There are a few legacy c-* includes in target .c files that aren't
> c-family-specific, but you shouldn't add to them in new patches; why  
> can't
> this go in darwin-c.c?

OK, indeed that makes more sense, will do,

Iain

>

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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-10-24 19:08   ` IainS
@ 2010-10-24 19:25     ` Joseph S. Myers
  2010-10-24 19:47       ` IainS
  0 siblings, 1 reply; 29+ messages in thread
From: Joseph S. Myers @ 2010-10-24 19:25 UTC (permalink / raw)
  To: IainS; +Cc: GCC Patches, Mike Stump

On Sun, 24 Oct 2010, IainS wrote:

> > You're adding a new format style, "NSString".  There's no documentation
> > for what it means,
> 
> NSString is documented in the relevant Objective C documentation.
> - should I add a cross-reference here ?
> or simply state what it is?

The Objective C documentation describes 
__attribute__((__format__(NSString,1,2))) or similar?

> > no testcases for this format style checking,
> 
> the tests are already present (in test-cases that currently fail for NeXT
> ObjC).

What testcases?  Please give specific file names of tests in the GCC 
testsuite that FAIL before this patch, PASS afterwards, and use the sort 
of format attribute construct I mention above.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-10-24 19:25     ` Joseph S. Myers
@ 2010-10-24 19:47       ` IainS
  2010-10-25  2:07         ` Jack Howarth
  2010-10-25 10:36         ` Mike Stump
  0 siblings, 2 replies; 29+ messages in thread
From: IainS @ 2010-10-24 19:47 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: GCC Patches, Mike Stump

Hello Joseph,

On 24 Oct 2010, at 16:27, Joseph S. Myers wrote:

> On Sun, 24 Oct 2010, IainS wrote:
>
>>> You're adding a new format style, "NSString".  There's no  
>>> documentation
>>> for what it means,
>>
>> NSString is documented in the relevant Objective C documentation.
>> - should I add a cross-reference here ?
>> or simply state what it is?
>
> The Objective C documentation describes
> __attribute__((__format__(NSString,1,2))) or similar?

no, whilst it does discuss attribute markup, it does not give such a  
format example.
I'll add something to the gcc doc.

>>> no testcases for this format style checking,
>>
>> the tests are already present (in test-cases that currently fail  
>> for NeXT
>> ObjC).
>
> What testcases?  Please give specific file names of tests in the GCC
> testsuite that FAIL before this patch, PASS afterwards, and use the  
> sort
> of format attribute construct I mention above.

on Darwin10, any test-case that includes <Foundation/Foundation.h>
or anything that includes (indirectly usually) CFString.h

for example;
gcc/testsuite/objc.dg/no-extra-load.m:#import <Foundation/Foundation.h>
gcc/testsuite/objc.dg/objc-foreach-4.m:#include <Foundation/ 
Foundation.h>
gcc/testsuite/objc.dg/objc-foreach-5.m:#import <Foundation/Foundation.h>

but, of course, I am happy to improve test coverage - I have one or  
two stand-alone tests in my local test directory that could be used.

At present, this is all darwin-specific, although Nicola might wish to  
extend to GNUstep, the consensus was probably not during 4.6.

I'll wait for any further comments,
and for  Mike's input and then update the patch.

thanks.
Iain

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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-10-24 19:47       ` IainS
@ 2010-10-25  2:07         ` Jack Howarth
  2010-10-25  2:32           ` Nicola Pero
  2010-10-25 10:36         ` Mike Stump
  1 sibling, 1 reply; 29+ messages in thread
From: Jack Howarth @ 2010-10-25  2:07 UTC (permalink / raw)
  To: IainS; +Cc: Joseph S. Myers, GCC Patches, Mike Stump

On Sun, Oct 24, 2010 at 05:20:19PM +0100, IainS wrote:
>
> on Darwin10, any test-case that includes <Foundation/Foundation.h>
> or anything that includes (indirectly usually) CFString.h
>
> for example;
> gcc/testsuite/objc.dg/no-extra-load.m:#import <Foundation/Foundation.h>
> gcc/testsuite/objc.dg/objc-foreach-4.m:#include <Foundation/ 
> Foundation.h>
> gcc/testsuite/objc.dg/objc-foreach-5.m:#import <Foundation/Foundation.h>
>

Iain,
   I am finding on x86_64-apple-darwin10 that your patch eliminates the following
testsuite failures...

unix/-m32
FAIL: objc.dg/no-extra-load.m -fnext-runtime (test for excess errors)
ERROR: objc.dg/no-extra-load.m: error executing dg-final: couldn't open "no-extra-load.s": no such file or directory
UNRESOLVED: objc.dg/no-extra-load.m: error executing dg-final: couldn't open "no-extra-load.s": no such file or directory
FAIL: objc.dg/objc-foreach-4.m -fnext-runtime (test for excess errors)
FAIL: objc.dg/objc-foreach-5.m -fnext-runtime (test for excess errors)
ERROR: objc.dg/objc-foreach-5.m: error executing dg-final: couldn't open "objc-foreach-5.s": no such file or directory
UNRESOLVED: objc.dg/objc-foreach-5.m: error executing dg-final: couldn't open "objc-foreach-5.s": no such file or directory
FAIL: objc.dg/property/property-2.m -fnext-runtime (test for excess errors)
WARNING: objc.dg/property/property-2.m -fnext-runtime compilation failed to produce executable
FAIL: objc.dg/property/property-3.m -fnext-runtime (test for excess errors)
WARNING: objc.dg/property/property-3.m -fnext-runtime compilation failed to produce executable
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O0  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O1  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O2  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O3 -fomit-frame-pointer  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O3 -g  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -Os  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O2 -flto  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O2 -fwhopr  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/property/property-2.mm -fnext-runtime (test for excess errors)
WARNING: obj-c++.dg/property/property-2.mm -fnext-runtime compilation failed to produce executable
FAIL: obj-c++.dg/property/property-3.mm -fnext-runtime (test for excess errors)
WARNING: obj-c++.dg/property/property-3.mm -fnext-runtime compilation failed to produce executable
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O0  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O1  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O2  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O3 -fomit-frame-pointer  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O3 -g  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -Os  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O2 -flto  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O2 -fwhopr  -fnext-runtime (test for excess errors)

unix/-m64
FAIL: objc.dg/no-extra-load.m -fnext-runtime (test for excess errors)
ERROR: objc.dg/no-extra-load.m: error executing dg-final: couldn't open "no-extra-load.s": no such file or directory
UNRESOLVED: objc.dg/no-extra-load.m: error executing dg-final: couldn't open "no-extra-load.s": no such file or directory
FAIL: objc.dg/objc-foreach-4.m -fnext-runtime (test for excess errors)
FAIL: objc.dg/objc-foreach-5.m -fnext-runtime (test for excess errors)
ERROR: objc.dg/objc-foreach-5.m: error executing dg-final: couldn't open "objc-foreach-5.s": no such file or directory
UNRESOLVED: objc.dg/objc-foreach-5.m: error executing dg-final: couldn't open "objc-foreach-5.s": no such file or directory
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O0  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O1  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O2  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O3 -fomit-frame-pointer  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O3 -g  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -Os  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O2 -flto  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O2 -fwhopr  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O0  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O1  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O2  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O3 -fomit-frame-pointer  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O3 -g  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -Os  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O2 -flto  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O2 -fwhopr  -fnext-runtime (test for excess errors)




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-10-25  2:07         ` Jack Howarth
@ 2010-10-25  2:32           ` Nicola Pero
  2010-10-25  9:48             ` IainS
  0 siblings, 1 reply; 29+ messages in thread
From: Nicola Pero @ 2010-10-25  2:32 UTC (permalink / raw)
  To: Jack Howarth; +Cc: IainS, Joseph S. Myers, GCC Patches, Mike Stump

Yes :-(

whenever possible, ObjC/ObjC++ testcases shouldn't #import <Foundation/Foundation.h> ...

 * it destroys the whole point of having testcases test a single, specific part or feature of the compiler

 * whether testcases pass or not depend on the version of the FoundationKit being used

 * it is hard to run any such tests with the GNU runtime

(Btw, ObjC/ObjC++ testcases that #import <Foundation/Foundation.h> usually come from Apple - we 
should really try to clean them to avoid Foundation/Foundation.h if possible) ;-)

Thanks

-----Original Message-----
From: "Jack Howarth" <howarth@bromo.med.uc.edu>
Sent: Sunday, 24 October, 2010 22:05
To: "IainS" <developer@sandoe-acoustics.co.uk>
Cc: "Joseph S. Myers" <joseph@codesourcery.com>, "GCC Patches" <gcc-patches@gcc.gnu.org>, "Mike Stump" <mrs@gcc.gnu.org>
Subject: Re: [Patch, c* ,ObjC*] handle string objects in format checking.

On Sun, Oct 24, 2010 at 05:20:19PM +0100, IainS wrote:
>
> on Darwin10, any test-case that includes <Foundation/Foundation.h>
> or anything that includes (indirectly usually) CFString.h
>
> for example;
> gcc/testsuite/objc.dg/no-extra-load.m:#import <Foundation/Foundation.h>
> gcc/testsuite/objc.dg/objc-foreach-4.m:#include <Foundation/ 
> Foundation.h>
> gcc/testsuite/objc.dg/objc-foreach-5.m:#import <Foundation/Foundation.h>
>

Iain,
   I am finding on x86_64-apple-darwin10 that your patch eliminates the following
testsuite failures...

unix/-m32
FAIL: objc.dg/no-extra-load.m -fnext-runtime (test for excess errors)
ERROR: objc.dg/no-extra-load.m: error executing dg-final: couldn't open "no-extra-load.s": no such file or directory
UNRESOLVED: objc.dg/no-extra-load.m: error executing dg-final: couldn't open "no-extra-load.s": no such file or directory
FAIL: objc.dg/objc-foreach-4.m -fnext-runtime (test for excess errors)
FAIL: objc.dg/objc-foreach-5.m -fnext-runtime (test for excess errors)
ERROR: objc.dg/objc-foreach-5.m: error executing dg-final: couldn't open "objc-foreach-5.s": no such file or directory
UNRESOLVED: objc.dg/objc-foreach-5.m: error executing dg-final: couldn't open "objc-foreach-5.s": no such file or directory
FAIL: objc.dg/property/property-2.m -fnext-runtime (test for excess errors)
WARNING: objc.dg/property/property-2.m -fnext-runtime compilation failed to produce executable
FAIL: objc.dg/property/property-3.m -fnext-runtime (test for excess errors)
WARNING: objc.dg/property/property-3.m -fnext-runtime compilation failed to produce executable
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O0  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O1  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O2  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O3 -fomit-frame-pointer  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O3 -g  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -Os  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O2 -flto  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O2 -fwhopr  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/property/property-2.mm -fnext-runtime (test for excess errors)
WARNING: obj-c++.dg/property/property-2.mm -fnext-runtime compilation failed to produce executable
FAIL: obj-c++.dg/property/property-3.mm -fnext-runtime (test for excess errors)
WARNING: obj-c++.dg/property/property-3.mm -fnext-runtime compilation failed to produce executable
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O0  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O1  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O2  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O3 -fomit-frame-pointer  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O3 -g  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -Os  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O2 -flto  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O2 -fwhopr  -fnext-runtime (test for excess errors)

unix/-m64
FAIL: objc.dg/no-extra-load.m -fnext-runtime (test for excess errors)
ERROR: objc.dg/no-extra-load.m: error executing dg-final: couldn't open "no-extra-load.s": no such file or directory
UNRESOLVED: objc.dg/no-extra-load.m: error executing dg-final: couldn't open "no-extra-load.s": no such file or directory
FAIL: objc.dg/objc-foreach-4.m -fnext-runtime (test for excess errors)
FAIL: objc.dg/objc-foreach-5.m -fnext-runtime (test for excess errors)
ERROR: objc.dg/objc-foreach-5.m: error executing dg-final: couldn't open "objc-foreach-5.s": no such file or directory
UNRESOLVED: objc.dg/objc-foreach-5.m: error executing dg-final: couldn't open "objc-foreach-5.s": no such file or directory
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O0  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O1  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O2  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O3 -fomit-frame-pointer  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O3 -g  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -Os  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O2 -flto  -fnext-runtime (test for excess errors)
FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O2 -fwhopr  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O0  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O1  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O2  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O3 -fomit-frame-pointer  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O3 -g  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -Os  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O2 -flto  -fnext-runtime (test for excess errors)
FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O2 -fwhopr  -fnext-runtime (test for excess errors)






^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-10-25  2:32           ` Nicola Pero
@ 2010-10-25  9:48             ` IainS
  0 siblings, 0 replies; 29+ messages in thread
From: IainS @ 2010-10-25  9:48 UTC (permalink / raw)
  To: Nicola Pero; +Cc: Jack Howarth, Joseph S. Myers, GCC Patches, Mike Stump

Hi Nicola,

I agree in general terms, as much as possible should be independent -  
and I've been "gnu-ifying" the NeXT cases and "next-ifying" the gnu  
ones as much as possible.

However,  we need to test stuff that performs the required functions  
with the NeXT runtime (which might include functionality outside what  
we have implemented for gnu).

-- being able to compile the Foundation (ObjC*) and CoreFoundation (c*  
and ObjC*)  headers is pretty (possibly vitally) important for use of  
FSF gcc on Darwin.

I'm working on making this particular change a little less obtuse.
cheers,
Iain


On 24 Oct 2010, at 21:50, Nicola Pero wrote:

> Yes :-(
>
> whenever possible, ObjC/ObjC++ testcases shouldn't #import  
> <Foundation/Foundation.h> ...
>
> * it destroys the whole point of having testcases test a single,  
> specific part or feature of the compiler
>
> * whether testcases pass or not depend on the version of the  
> FoundationKit being used
>
> * it is hard to run any such tests with the GNU runtime
>
> (Btw, ObjC/ObjC++ testcases that #import <Foundation/Foundation.h>  
> usually come from Apple - we
> should really try to clean them to avoid Foundation/Foundation.h if  
> possible) ;-)
>
> Thanks
>
> -----Original Message-----
> From: "Jack Howarth" <howarth@bromo.med.uc.edu>
> Sent: Sunday, 24 October, 2010 22:05
> To: "IainS" <developer@sandoe-acoustics.co.uk>
> Cc: "Joseph S. Myers" <joseph@codesourcery.com>, "GCC Patches" <gcc-patches@gcc.gnu.org 
> >, "Mike Stump" <mrs@gcc.gnu.org>
> Subject: Re: [Patch, c* ,ObjC*] handle string objects in format  
> checking.
>
> On Sun, Oct 24, 2010 at 05:20:19PM +0100, IainS wrote:
>>
>> on Darwin10, any test-case that includes <Foundation/Foundation.h>
>> or anything that includes (indirectly usually) CFString.h
>>
>> for example;
>> gcc/testsuite/objc.dg/no-extra-load.m:#import <Foundation/ 
>> Foundation.h>
>> gcc/testsuite/objc.dg/objc-foreach-4.m:#include <Foundation/
>> Foundation.h>
>> gcc/testsuite/objc.dg/objc-foreach-5.m:#import <Foundation/ 
>> Foundation.h>
>>
>
> Iain,
>   I am finding on x86_64-apple-darwin10 that your patch eliminates  
> the following
> testsuite failures...
>
> unix/-m32
> FAIL: objc.dg/no-extra-load.m -fnext-runtime (test for excess errors)
> ERROR: objc.dg/no-extra-load.m: error executing dg-final: couldn't  
> open "no-extra-load.s": no such file or directory
> UNRESOLVED: objc.dg/no-extra-load.m: error executing dg-final:  
> couldn't open "no-extra-load.s": no such file or directory
> FAIL: objc.dg/objc-foreach-4.m -fnext-runtime (test for excess errors)
> FAIL: objc.dg/objc-foreach-5.m -fnext-runtime (test for excess errors)
> ERROR: objc.dg/objc-foreach-5.m: error executing dg-final: couldn't  
> open "objc-foreach-5.s": no such file or directory
> UNRESOLVED: objc.dg/objc-foreach-5.m: error executing dg-final:  
> couldn't open "objc-foreach-5.s": no such file or directory
> FAIL: objc.dg/property/property-2.m -fnext-runtime (test for excess  
> errors)
> WARNING: objc.dg/property/property-2.m -fnext-runtime compilation  
> failed to produce executable
> FAIL: objc.dg/property/property-3.m -fnext-runtime (test for excess  
> errors)
> WARNING: objc.dg/property/property-3.m -fnext-runtime compilation  
> failed to produce executable
> FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O0  -fnext- 
> runtime (test for excess errors)
> FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O1  -fnext- 
> runtime (test for excess errors)
> FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O2  -fnext- 
> runtime (test for excess errors)
> FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O3 -fomit-frame- 
> pointer  -fnext-runtime (test for excess errors)
> FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O3 -g  -fnext- 
> runtime (test for excess errors)
> FAIL: objc.dg/torture/strings/const-cfstring-1.m  -Os  -fnext- 
> runtime (test for excess errors)
> FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O2 -flto  -fnext- 
> runtime (test for excess errors)
> FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O2 -fwhopr  - 
> fnext-runtime (test for excess errors)
> FAIL: obj-c++.dg/property/property-2.mm -fnext-runtime (test for  
> excess errors)
> WARNING: obj-c++.dg/property/property-2.mm -fnext-runtime  
> compilation failed to produce executable
> FAIL: obj-c++.dg/property/property-3.mm -fnext-runtime (test for  
> excess errors)
> WARNING: obj-c++.dg/property/property-3.mm -fnext-runtime  
> compilation failed to produce executable
> FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O0  -fnext- 
> runtime (test for excess errors)
> FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O1  -fnext- 
> runtime (test for excess errors)
> FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O2  -fnext- 
> runtime (test for excess errors)
> FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O3 -fomit- 
> frame-pointer  -fnext-runtime (test for excess errors)
> FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O3 -g  -fnext- 
> runtime (test for excess errors)
> FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -Os  -fnext- 
> runtime (test for excess errors)
> FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O2 -flto  - 
> fnext-runtime (test for excess errors)
> FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O2 -fwhopr  - 
> fnext-runtime (test for excess errors)
>
> unix/-m64
> FAIL: objc.dg/no-extra-load.m -fnext-runtime (test for excess errors)
> ERROR: objc.dg/no-extra-load.m: error executing dg-final: couldn't  
> open "no-extra-load.s": no such file or directory
> UNRESOLVED: objc.dg/no-extra-load.m: error executing dg-final:  
> couldn't open "no-extra-load.s": no such file or directory
> FAIL: objc.dg/objc-foreach-4.m -fnext-runtime (test for excess errors)
> FAIL: objc.dg/objc-foreach-5.m -fnext-runtime (test for excess errors)
> ERROR: objc.dg/objc-foreach-5.m: error executing dg-final: couldn't  
> open "objc-foreach-5.s": no such file or directory
> UNRESOLVED: objc.dg/objc-foreach-5.m: error executing dg-final:  
> couldn't open "objc-foreach-5.s": no such file or directory
> FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O0  -fnext- 
> runtime (test for excess errors)
> FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O1  -fnext- 
> runtime (test for excess errors)
> FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O2  -fnext- 
> runtime (test for excess errors)
> FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O3 -fomit-frame- 
> pointer  -fnext-runtime (test for excess errors)
> FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O3 -g  -fnext- 
> runtime (test for excess errors)
> FAIL: objc.dg/torture/strings/const-cfstring-1.m  -Os  -fnext- 
> runtime (test for excess errors)
> FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O2 -flto  -fnext- 
> runtime (test for excess errors)
> FAIL: objc.dg/torture/strings/const-cfstring-1.m  -O2 -fwhopr  - 
> fnext-runtime (test for excess errors)
> FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O0  -fnext- 
> runtime (test for excess errors)
> FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O1  -fnext- 
> runtime (test for excess errors)
> FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O2  -fnext- 
> runtime (test for excess errors)
> FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O3 -fomit- 
> frame-pointer  -fnext-runtime (test for excess errors)
> FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O3 -g  -fnext- 
> runtime (test for excess errors)
> FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -Os  -fnext- 
> runtime (test for excess errors)
> FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O2 -flto  - 
> fnext-runtime (test for excess errors)
> FAIL: obj-c++.dg/torture/strings/const-cfstring-1.mm  -O2 -fwhopr  - 
> fnext-runtime (test for excess errors)
>
>
>
>
>
>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-10-24 19:47       ` IainS
  2010-10-25  2:07         ` Jack Howarth
@ 2010-10-25 10:36         ` Mike Stump
  2010-10-28 18:05           ` Updated: " IainS
  1 sibling, 1 reply; 29+ messages in thread
From: Mike Stump @ 2010-10-25 10:36 UTC (permalink / raw)
  To: IainS; +Cc: Joseph S. Myers, GCC Patches, Mike Stump

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.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-10-25 10:36         ` Mike Stump
@ 2010-10-28 18:05           ` IainS
  2010-10-28 19:43             ` Joseph S. Myers
  0 siblings, 1 reply; 29+ messages in thread
From: IainS @ 2010-10-28 18:05 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: GCC Patches, Mike Stump, Mike Stump

[-- Attachment #1: Type: text/plain, Size: 4049 bytes --]

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.


[-- Attachment #2: 166026-format-attr-extensions.txt --]
[-- Type: text/plain, Size: 40959 bytes --]

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"
 \f
 /* 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%> 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 = 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 = 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%> ref.", 
+	      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,24 @@ typedef struct
   tree params;
 } format_check_context;
 
+static const char *
+format_name (int format_num)
+{
+  if (format_num >= 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 >= 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 = 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)
@@ -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
@@ -2785,6 +2944,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 +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;
 
       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)
@@ -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)
@@ -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. 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 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. 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 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. 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 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)
@@ -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)
@@ -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

[-- Attachment #3: Type: text/plain, Size: 3 bytes --]



	

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-10-28 18:05           ` Updated: " IainS
@ 2010-10-28 19:43             ` Joseph S. Myers
  2010-10-28 22:59               ` IainS
  0 siblings, 1 reply; 29+ messages in thread
From: Joseph S. Myers @ 2010-10-28 19:43 UTC (permalink / raw)
  To: IainS; +Cc: GCC Patches, Mike Stump, Mike Stump

On Thu, 28 Oct 2010, IainS wrote:

> 	* doc/extend.tex (format): Document NSString extension.

It's .texi not .tex.

> +	  /* 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.

> +	    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?

> +      error ("format argument should be a %<%s%> ref. but"
> +	     " a string was found",format_name (expected_format_type));

Same point about "ref.".  Missing space after comma.  In general you 
should check the formatting of this patch carefully; there seem to be 
several whitespace peculiarities.

> +      error ("format argument should be a %<%s%> ref.", 

Likewise.

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

Missing a comment describing the semantics of this function, its argument 
and return value.

> +{
> +  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.

> +static int
> +format_flags (int format_num)

Likewise needs comment.

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

Stray space before ;.

> @@ -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.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-10-28 19:43             ` Joseph S. Myers
@ 2010-10-28 22:59               ` IainS
  2010-10-31 21:39                 ` Nicola Pero
  2010-11-05 17:05                 ` Joseph S. Myers
  0 siblings, 2 replies; 29+ messages in thread
From: IainS @ 2010-10-28 22:59 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: GCC Patches, Mike Stump, Mike Stump

[-- Attachment #1: Type: text/plain, Size: 3100 bytes --]


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


[-- Attachment #2: 166026-format-attr-extensions-a.txt --]
[-- Type: text/plain, Size: 42023 bytes --]

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"
 \f
 /* 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

[-- Attachment #3: Type: text/plain, Size: 56 bytes --]




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


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-10-28 22:59               ` IainS
@ 2010-10-31 21:39                 ` Nicola Pero
  2010-10-31 22:03                   ` IainS
  2010-11-05 17:05                 ` Joseph S. Myers
  1 sibling, 1 reply; 29+ messages in thread
From: Nicola Pero @ 2010-10-31 21:39 UTC (permalink / raw)
  To: IainS; +Cc: Joseph S. Myers, GCC Patches, Mike Stump, Mike Stump

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



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-10-31 21:39                 ` Nicola Pero
@ 2010-10-31 22:03                   ` IainS
  2010-10-31 23:24                     ` Nicola Pero
  0 siblings, 1 reply; 29+ messages in thread
From: IainS @ 2010-10-31 22:03 UTC (permalink / raw)
  To: Nicola Pero; +Cc: Joseph S. Myers, GCC Patches, Mike Stump, Mike Stump


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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-10-31 22:03                   ` IainS
@ 2010-10-31 23:24                     ` Nicola Pero
  2010-10-31 23:38                       ` IainS
  0 siblings, 1 reply; 29+ messages in thread
From: Nicola Pero @ 2010-10-31 23:24 UTC (permalink / raw)
  To: IainS; +Cc: Joseph S. Myers, GCC Patches, Mike Stump, Mike Stump


> 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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-10-31 23:24                     ` Nicola Pero
@ 2010-10-31 23:38                       ` IainS
  0 siblings, 0 replies; 29+ messages in thread
From: IainS @ 2010-10-31 23:38 UTC (permalink / raw)
  To: Nicola Pero; +Cc: Joseph S. Myers, GCC Patches, Mike Stump, Mike Stump


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

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-10-28 22:59               ` IainS
  2010-10-31 21:39                 ` Nicola Pero
@ 2010-11-05 17:05                 ` Joseph S. Myers
  2010-11-06 11:25                   ` IainS
  1 sibling, 1 reply; 29+ messages in thread
From: Joseph S. Myers @ 2010-11-05 17:05 UTC (permalink / raw)
  To: IainS; +Cc: GCC Patches, Mike Stump, Mike Stump

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).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-11-05 17:05                 ` Joseph S. Myers
@ 2010-11-06 11:25                   ` IainS
  0 siblings, 0 replies; 29+ messages in thread
From: IainS @ 2010-11-06 11:25 UTC (permalink / raw)
  To: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 356 bytes --]


On 5 Nov 2010, at 16:57, Joseph S. Myers wrote:

corrections made, version committed attached.

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


re-bootstrapped, make pdf (and checked output) and checked objc*

thanks,
ci r166398/166399 (166399 reverts an accidental commit of an unrelated  
hunk.)
Iain


[-- Attachment #2: 166397-cf-ns-format-syntax.txt --]
[-- Type: text/plain, Size: 41061 bytes --]

Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 166397)
+++ 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
@@ -12426,6 +12440,7 @@ format attribute
 
 @menu
 * Solaris Format Checks::
+* Darwin Format Checks::
 @end menu
 
 @node Solaris Format Checks
@@ -12436,6 +12451,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 166397)
+++ gcc/doc/tm.texi	(working copy)
@@ -715,10 +715,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 @code{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 166397)
+++ gcc/doc/tm.texi.in	(working copy)
@@ -715,8 +715,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/ChangeLog
===================================================================
--- gcc/c-family/ChangeLog	(revision 166397)
+++ gcc/c-family/ChangeLog	(working copy)
@@ -1,3 +1,24 @@
+2010-11-06  Iain Sandoe  <iains@gcc.gnu.org>
+
+	PR target/44981
+	* 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.
+
 2010-11-04  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	Fixed using the Objective-C 2.0 dot-syntax with class names.	
Index: gcc/c-family/c-format.c
===================================================================
--- gcc/c-family/c-format.c	(revision 166397)
+++ 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"
 \f
 /* 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-format.h
===================================================================
--- gcc/c-family/c-format.h	(revision 166397)
+++ 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/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 166397)
+++ gcc/c-family/c-common.h	(working copy)
@@ -1043,6 +1043,8 @@ extern void objc_add_synthesize_declaration (locat
 extern void objc_add_dynamic_declaration (location_t, tree);
 extern const char * objc_maybe_printable_name (tree, int);
 extern bool objc_is_property_ref (tree);
+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/stub-objc.c
===================================================================
--- gcc/c-family/stub-objc.c	(revision 166397)
+++ 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.
 
@@ -440,3 +440,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 166397)
+++ gcc/target.def	(working copy)
@@ -2648,10 +2648,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\
+ @code{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 166397)
+++ 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"
@@ -2755,9 +2756,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);
     }
@@ -12673,4 +12674,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/objc/ChangeLog
===================================================================
--- gcc/objc/ChangeLog	(revision 166397)
+++ gcc/objc/ChangeLog	(working copy)
@@ -1,3 +1,10 @@
+2010-11-06  Iain Sandoe  <iains@gcc.gnu.org>
+
+	PR target/44981
+	* objc-act.c (objc_build_string_object): Amend for renamed hook.
+	(objc_string_ref_type_p): New.
+	(objc_check_format_arg): New.
+
 2010-11-04  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	Fixed using the Objective-C 2.0 dot-syntax with class names.	
Index: gcc/ChangeLog
===================================================================
--- gcc/ChangeLog	(revision 166397)
+++ gcc/ChangeLog	(working copy)
@@ -1,3 +1,29 @@
+2010-11-06  Iain Sandoe  <iains@gcc.gnu.org>
+
+	PR target/44981
+	* 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.
+
 2010-11-06  Eric Botcazou  <ebotcazou@adacore.com>
             Pascal Obry  <obry@adacore.com>
 
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/ChangeLog
===================================================================
--- gcc/testsuite/ChangeLog	(revision 166397)
+++ gcc/testsuite/ChangeLog	(working copy)
@@ -1,3 +1,13 @@
+2010-11-06  Iain Sandoe  <iains@gcc.gnu.org>
+
+	PR target/44981
+	* 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.
+	* obj-c++.dg/torture/strings/const-cfstring-1.mm: Update for darwin10
+	linker warning.
+
 2010-11-05  Jason Merrill  <jason@redhat.com>
 
 	PR c++/45473
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/torture/strings/const-cfstring-1.mm
===================================================================
--- gcc/testsuite/obj-c++.dg/torture/strings/const-cfstring-1.mm	(revision 166397)
+++ 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 166397)
+++ gcc/c-parser.c	(working copy)
@@ -3278,9 +3278,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 166397)
+++ 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 166397)
+++ gcc/config/darwin-protos.h	(working copy)
@@ -97,7 +97,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 166397)
+++ gcc/config/darwin.h	(working copy)
@@ -1023,9 +1023,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

[-- Attachment #3: Type: text/plain, Size: 3 bytes --]





^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-11-01 13:17     ` Joseph S. Myers
  2010-11-01 14:39       ` IainS
@ 2010-11-01 19:09       ` Nicola Pero
  1 sibling, 0 replies; 29+ messages in thread
From: Nicola Pero @ 2010-11-01 19:09 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: IainS, GCC Patches, Mike Stump, Mike Stump


>> Probably ObjC could return the constant string converted to UTF-8 so that 
>> it can be fed into c-format.c without particular any changes to c-format.c ?
>
> What's really wanted - to do wide string format checking for wprintf etc. 
> (bug 38308), not just for ObjC - are separate accessors / iterators that [...]

Joseph,

thanks for explaining.  That is very interesting.  Would be worth working on it.

At the moment, I guess a first step would be to get NSString format string
parsing with ASCII Objective-C constant strings (ie, the same as printf). :-)

If the constant string is not ASCII, we could simply skip the check for now - and
come back to it in 4.7.0.  And I agree with you that we then want the general solution,
not just a quick hack. ;-)

Thanks

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-11-01 14:39       ` IainS
@ 2010-11-01 14:48         ` Joseph S. Myers
  0 siblings, 0 replies; 29+ messages in thread
From: Joseph S. Myers @ 2010-11-01 14:48 UTC (permalink / raw)
  To: IainS; +Cc: Nicola Pero, GCC Patches, Mike Stump, Mike Stump

On Mon, 1 Nov 2010, IainS wrote:

> This looks like something beyond 4.6?

Yes.

> Can I ask what the position is on the original patch which sets out to check
> syntax and deal with two string formats which are, essentially, outside our
> control?

I have a queue of patches to review.  Two format checking patches are on 
it.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-11-01 13:17     ` Joseph S. Myers
@ 2010-11-01 14:39       ` IainS
  2010-11-01 14:48         ` Joseph S. Myers
  2010-11-01 19:09       ` Nicola Pero
  1 sibling, 1 reply; 29+ messages in thread
From: IainS @ 2010-11-01 14:39 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: Nicola Pero, GCC Patches, Mike Stump, Mike Stump


On 1 Nov 2010, at 13:13, Joseph S. Myers wrote:

> On Mon, 1 Nov 2010, Nicola Pero wrote:
>
>> Probably ObjC could return the constant string converted to UTF-8  
>> so that
>> it can be fed into c-format.c without particular any changes to c- 
>> format.c ?
>
> What's really wanted - to do wide string format checking for wprintf  
> etc.
> (bug 38308), not just for ObjC - are separate accessors / iterators  
> that
> in the narrow string case extract a byte, or a multibyte character,  
> from a
> string.  (C format strings are complicated mixtures of bytes and  
> multibyte
> characters.)  In the wide string case both would just end up  
> extracting a
> single wide character.  It would be strongly desirable to have a  
> design
> for string access that is not specific to format checking but can be  
> used
> everywhere else that looks at contents of strings.  (All such
> optimizations - folding, built-in functions, etc. - ought to work  
> equally
> on narrow and wide strings; I don't think they do at present.)
>
> I will no longer ask that such changes actually define the formats for
> strings for non-8-bit-bytes as I did previously, and rather too
> forcefully, in response to
> <http://gcc.gnu.org/ml/gcc-patches/2001-12/msg01579.html>.  As long  
> as you
> set up central infrastructure for iterating over strings it will be
> significantly easier for anyone adding such a target in future to  
> define
> things in one place and fix other places to use the common  
> infrastructure.
> Nor will I ask that the character set issues (bugs 20110 and 33748)
> necessarily be fixed at the same time.

This looks like something beyond 4.6?

Can I ask what the position is on the original patch which sets out to  
check syntax and deal with two string formats which are, essentially,  
outside our control?

[although the basic layout and capability of CFString might well  
satisfy the objectives for a common string container above, and is  
part of the FSF code-base]

thanks,
Iain

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-11-01  9:42   ` Nicola Pero
  2010-11-01 10:18     ` IainS
@ 2010-11-01 13:17     ` Joseph S. Myers
  2010-11-01 14:39       ` IainS
  2010-11-01 19:09       ` Nicola Pero
  1 sibling, 2 replies; 29+ messages in thread
From: Joseph S. Myers @ 2010-11-01 13:17 UTC (permalink / raw)
  To: Nicola Pero; +Cc: IainS, GCC Patches, Mike Stump, Mike Stump

On Mon, 1 Nov 2010, Nicola Pero wrote:

> Probably ObjC could return the constant string converted to UTF-8 so that 
> it can be fed into c-format.c without particular any changes to c-format.c ?

What's really wanted - to do wide string format checking for wprintf etc. 
(bug 38308), not just for ObjC - are separate accessors / iterators that 
in the narrow string case extract a byte, or a multibyte character, from a 
string.  (C format strings are complicated mixtures of bytes and multibyte 
characters.)  In the wide string case both would just end up extracting a 
single wide character.  It would be strongly desirable to have a design 
for string access that is not specific to format checking but can be used 
everywhere else that looks at contents of strings.  (All such 
optimizations - folding, built-in functions, etc. - ought to work equally 
on narrow and wide strings; I don't think they do at present.)

I will no longer ask that such changes actually define the formats for 
strings for non-8-bit-bytes as I did previously, and rather too 
forcefully, in response to 
<http://gcc.gnu.org/ml/gcc-patches/2001-12/msg01579.html>.  As long as you 
set up central infrastructure for iterating over strings it will be 
significantly easier for anyone adding such a target in future to define 
things in one place and fix other places to use the common infrastructure.  
Nor will I ask that the character set issues (bugs 20110 and 33748) 
necessarily be fixed at the same time.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-11-01  9:42   ` Nicola Pero
@ 2010-11-01 10:18     ` IainS
  2010-11-01 13:17     ` Joseph S. Myers
  1 sibling, 0 replies; 29+ messages in thread
From: IainS @ 2010-11-01 10:18 UTC (permalink / raw)
  To: Nicola Pero; +Cc: Joseph S. Myers, GCC Patches, Mike Stump, Mike Stump


On 1 Nov 2010, at 09:27, Nicola Pero wrote:

>
>> This is because the string literal behind an NS (or CF) string need
>> not be ascii or even utf8 -- it could be utf16 (although we haven't
>> implemented that yet).
>
> Hmmm.  Excellent point by the way. ;-)
>
> I still think we should do the NSString formatting in c-format.c.  I  
> don't
> want to rewrite and maintain the whole of c-format.c in gcc/objc/. ;-)
>
> [and in your patch you have another placeholder for CFString  
> formatting in Darwin ... I
> don't think we'd want to duplicate the entire printf formatting yet  
> another time for
> Darwin just to allow CFStringRefs to be used instead of  
> NSStrings ;-).]

The only addition that could be made to distinguish CFStrings is that,  
in principle, (unimplemented at present) they could be backed by  
pascal style strings.

I agree entirely with the undesirability of maintaining unnecessary  
code.
(In my mind I had the possibility of calling back to c-format.c for  
'normal' string cases)

> We can probably find some sort of solution even for unicode strings.
> Probably ObjC could return the constant string converted to UTF-8 so  
> that
> it can be fed into c-format.c without particular any changes to c- 
> format.c ?

well, I think that would simply involve the two call-outs (perhaps  
with changed names) agreeing to return a utf-8 string.
this involves some @compile-time string conversion - but should be  
feasible (maybe libcpp already has the necessary).

if it's impossible to return utf8 for some reason then the fall-back  
is either to warn or to treat the string as non-literal (silently).

>> In any event, have you any objection to first applying the syntax and
>> parsing logic - assuming Joseph is now happy with it (since that  
>> patch
>> is already reviewed twice) and then filling in the implementation?
>
> No, I have no objection to doing it in two phases.  But it would  
> make sense
> to consider the second step when doing the first one. :-)

of course, I had slightly different plans - but we will converge I'm  
sure.

cheers
Iain

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-11-01  8:59 ` IainS
@ 2010-11-01  9:42   ` Nicola Pero
  2010-11-01 10:18     ` IainS
  2010-11-01 13:17     ` Joseph S. Myers
  0 siblings, 2 replies; 29+ messages in thread
From: Nicola Pero @ 2010-11-01  9:42 UTC (permalink / raw)
  To: IainS; +Cc: Joseph S. Myers, GCC Patches, Mike Stump, Mike Stump


> This is because the string literal behind an NS (or CF) string need  
> not be ascii or even utf8 -- it could be utf16 (although we haven't  
> implemented that yet).

Hmmm.  Excellent point by the way. ;-)

I still think we should do the NSString formatting in c-format.c.  I don't 
want to rewrite and maintain the whole of c-format.c in gcc/objc/. ;-)

[and in your patch you have another placeholder for CFString formatting in Darwin ... I
don't think we'd want to duplicate the entire printf formatting yet another time for 
Darwin just to allow CFStringRefs to be used instead of NSStrings ;-).]

We can probably find some sort of solution even for unicode strings.  
Probably ObjC could return the constant string converted to UTF-8 so that 
it can be fed into c-format.c without particular any changes to c-format.c ?


> In any event, have you any objection to first applying the syntax and  
> parsing logic - assuming Joseph is now happy with it (since that patch  
> is already reviewed twice) and then filling in the implementation?

No, I have no objection to doing it in two phases.  But it would make sense
to consider the second step when doing the first one. :-)

Thanks

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-11-01  4:38 Nicola Pero
  2010-11-01  8:09 ` Paolo Bonzini
@ 2010-11-01  8:59 ` IainS
  2010-11-01  9:42   ` Nicola Pero
  1 sibling, 1 reply; 29+ messages in thread
From: IainS @ 2010-11-01  8:59 UTC (permalink / raw)
  To: Nicola Pero; +Cc: Joseph S. Myers, GCC Patches, Mike Stump, Mike Stump


On 1 Nov 2010, at 04:37, 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)...

> "NSString uses a format string whose syntax is similar to that used  
> by other formatter objects.
> It supports the format characters defined for the ANSI C function  
> printf(), plus %@ for any object
> (see “String Format Specifiers” and the IEEE printf specification)."
>
> In attach is a draft patch I had produced during the weekend - it  
> works for me with the GNU runtime on top
> of my other patches (but it doesn't include documentation (and not  
> enough comments), has a few hacks and
> rough edges, most likelyl won't work on Darwin and it doesn't do  
> Objective-C++ yet). ;-)

May I suggest a possible amalgamation sth like this:

(1) the patch I proposed (which handles the other necessary cases for  
NeXT and Darwin as well).

(2) merge your adjustments to the NSString format declaration.

       add a call to objc that determines if an NSString can be  
represented in a manner parse-able in c-format.c

       if so then it can continue to parse the literal as per the  
existing code (with the addition of the %@)
       otherwise parse in ObjC.

This is because the string literal behind an NS (or CF) string need  
not be ascii or even utf8 -- it could be utf16 (although we haven't  
implemented that yet).

I'm not sure that we shouldn't just keep the whole thing in ObjC (and  
add an objc-format.c file to deal with the future expansion).

In any event, have you any objection to first applying the syntax and  
parsing logic - assuming Joseph is now happy with it (since that patch  
is already reviewed twice) and then filling in the implementation?

cheers,
Iain

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-11-01  8:09 ` Paolo Bonzini
  2010-11-01  8:16   ` Paolo Bonzini
@ 2010-11-01  8:50   ` IainS
  1 sibling, 0 replies; 29+ messages in thread
From: IainS @ 2010-11-01  8:50 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Nicola Pero, Joseph S. Myers, GCC Patches, Mike Stump, Mike Stump


On 1 Nov 2010, at 08:09, Paolo Bonzini wrote:

>> 2010-10-31  Nicola Pero  <nicola.pero@meta-innovation.com>
>>
>> +	* c-common.h (objc_is_string_type): New.
>> +	(objc_maybe_extract_string_cst_from_objc_string): New.
>> +	* stub-objc.c (objc_is_string_type): New.
>> +	(objc_maybe_extract_string_cst_from_objc_string): New.	
>> +	* c-format.c (is_string_type): New.
>> +	(handle_format_arg_attribute): Updated call to
>> +	check_format_string.  Use is_string_type.
>> +	(check_format_string): Added objc_string argument.  If set, check
>> +	that the format string is an Objective-C string.
>> +	(handle_format_attribute): For nsstring_format_type, check that
>> +	format strings are Objective-C strings.
>> +	(struct format_wanted_type): Added objc_object_flag.
>> +	(nsstring_length_specs): New.
>> +	(nsstring_flag_pairs): New.
>> +	(nsstring_flag_specs): New.
>> +	(nsstring_char_table): New.
>> +	(check_format_arg): Implemented nsstring_format_type.
>> +	(check_format_info_main): Implemented '@' as valid flag2.
>> +	(check_format_types): Implemented objc_object_flag.
>> +	* c-format.h: Updated comments.
>> +	(T89_AT): New.	
>
> Just a heads-up: my patch at http://gcc.gnu.org/ml/gcc-patches/2010-10/msg02437.html 
>  conflicts with this a bit, in that it changes a few messages in the  
> attribute((format)) output.  So the tests would have to be adjusted.


I saw your patch and figured that whichever went in first there might  
be some tweaking of things ...
... I'm happy to adjust tests in ObjC*.

Apropos Nicola's additions,  I wonder if we really need to keep the  
handling of ObjC strings in ObJC.
Can we guarantee always to be able to fetch an equivalent string that  
is parse-able by the printf machinery?

(just thinking aloud).
Iain

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-11-01  8:09 ` Paolo Bonzini
@ 2010-11-01  8:16   ` Paolo Bonzini
  2010-11-01  8:50   ` IainS
  1 sibling, 0 replies; 29+ messages in thread
From: Paolo Bonzini @ 2010-11-01  8:16 UTC (permalink / raw)
  To: gcc-patches; +Cc: IainS, Joseph S. Myers, GCC Patches, Mike Stump, Mike Stump

>  2010-10-31  Nicola Pero  <nicola.pero@meta-innovation.com>
>
> +	* c-common.h (objc_is_string_type): New.
> +	(objc_maybe_extract_string_cst_from_objc_string): New.
> +	* stub-objc.c (objc_is_string_type): New.
> +	(objc_maybe_extract_string_cst_from_objc_string): New.	
> +	* c-format.c (is_string_type): New.
> +	(handle_format_arg_attribute): Updated call to
> +	check_format_string.  Use is_string_type.
> +	(check_format_string): Added objc_string argument.  If set, check
> +	that the format string is an Objective-C string.
> +	(handle_format_attribute): For nsstring_format_type, check that
> +	format strings are Objective-C strings.
> +	(struct format_wanted_type): Added objc_object_flag.
> +	(nsstring_length_specs): New.
> +	(nsstring_flag_pairs): New.
> +	(nsstring_flag_specs): New.
> +	(nsstring_char_table): New.
> +	(check_format_arg): Implemented nsstring_format_type.
> +	(check_format_info_main): Implemented '@' as valid flag2.
> +	(check_format_types): Implemented objc_object_flag.
> +	* c-format.h: Updated comments.
> +	(T89_AT): New.	

Just a heads-up: my patch at 
http://gcc.gnu.org/ml/gcc-patches/2010-10/msg02437.html conflicts with 
this a bit, in that it changes a few messages in the attribute((format)) 
output.  So the tests would have to be adjusted.

Paolo

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
  2010-11-01  4:38 Nicola Pero
@ 2010-11-01  8:09 ` Paolo Bonzini
  2010-11-01  8:16   ` Paolo Bonzini
  2010-11-01  8:50   ` IainS
  2010-11-01  8:59 ` IainS
  1 sibling, 2 replies; 29+ messages in thread
From: Paolo Bonzini @ 2010-11-01  8:09 UTC (permalink / raw)
  To: Nicola Pero; +Cc: IainS, Joseph S. Myers, GCC Patches, Mike Stump, Mike Stump

>  2010-10-31  Nicola Pero  <nicola.pero@meta-innovation.com>
>
> +	* c-common.h (objc_is_string_type): New.
> +	(objc_maybe_extract_string_cst_from_objc_string): New.
> +	* stub-objc.c (objc_is_string_type): New.
> +	(objc_maybe_extract_string_cst_from_objc_string): New.	
> +	* c-format.c (is_string_type): New.
> +	(handle_format_arg_attribute): Updated call to
> +	check_format_string.  Use is_string_type.
> +	(check_format_string): Added objc_string argument.  If set, check
> +	that the format string is an Objective-C string.
> +	(handle_format_attribute): For nsstring_format_type, check that
> +	format strings are Objective-C strings.
> +	(struct format_wanted_type): Added objc_object_flag.
> +	(nsstring_length_specs): New.
> +	(nsstring_flag_pairs): New.
> +	(nsstring_flag_specs): New.
> +	(nsstring_char_table): New.
> +	(check_format_arg): Implemented nsstring_format_type.
> +	(check_format_info_main): Implemented '@' as valid flag2.
> +	(check_format_types): Implemented objc_object_flag.
> +	* c-format.h: Updated comments.
> +	(T89_AT): New.	

Just a heads-up: my patch at 
http://gcc.gnu.org/ml/gcc-patches/2010-10/msg02437.html conflicts with 
this a bit, in that it changes a few messages in the attribute((format)) 
output.  So the tests would have to be adjusted.

Paolo

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: Updated: [Patch, c* ,ObjC*] handle string objects in format checking.
@ 2010-11-01  4:38 Nicola Pero
  2010-11-01  8:09 ` Paolo Bonzini
  2010-11-01  8:59 ` IainS
  0 siblings, 2 replies; 29+ messages in thread
From: Nicola Pero @ 2010-11-01  4:38 UTC (permalink / raw)
  To: IainS; +Cc: Joseph S. Myers, GCC Patches, Mike Stump, Mike Stump

[-- Attachment #1: Type: text/plain, Size: 1753 bytes --]


>> 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)...

As far as I know, there are no intended differences other than the addition
of %@ (in other words, my description of the NSString format in my other
email should be correct and complete).

If you need to see Apple documentation, here it is --

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Strings/Articles/FormatStrings.html#//apple_ref/doc/uid/20000943-CJBEAEHH

It says 

"NSString uses a format string whose syntax is similar to that used by other formatter objects. 
It supports the format characters defined for the ANSI C function printf(), plus %@ for any object 
(see “String Format Specifiers” and the IEEE printf specification)."

In attach is a draft patch I had produced during the weekend - it works for me with the GNU runtime on top
of my other patches (but it doesn't include documentation (and not enough comments), has a few hacks and
rough edges, most likelyl won't work on Darwin and it doesn't do Objective-C++ yet). ;-)

Feel free to clean it up, steal the bits that you need, drop the ones that you don't need, make it work with Darwin 
as well as the GNU runtime and generally merge it with yours so we get full NSString format in 4.6.0. :-)

I hope that helps.  I'll now take a few days off the compiler, then come back in a few days to start 
the bug fixing round. :-)

Thanks

[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 25712 bytes --]

diff -rupN --exclude=.svn trunk9/gcc/c-family/c-common.h trunk8/gcc/c-family/c-common.h
--- trunk9/gcc/c-family/c-common.h	2010-10-30 12:26:13.000000000 +0100
+++ trunk8/gcc/c-family/c-common.h	2010-11-01 02:54:43.000000000 +0000
@@ -977,6 +977,7 @@ extern void c_parse_error (const char *,
 extern void objc_write_global_declarations (void);
 extern tree objc_is_class_name (tree);
 extern tree objc_is_object_ptr (tree);
+extern bool objc_is_string_type (tree);
 extern void objc_check_decl (tree);
 extern void objc_check_global_decl (tree);
 extern tree objc_common_type (tree, tree);
@@ -1001,6 +1002,7 @@ extern tree objc_build_selector_expr (lo
 extern tree objc_build_protocol_expr (tree);
 extern tree objc_build_encode_expr (tree);
 extern tree objc_build_string_object (tree);
+extern tree objc_maybe_extract_string_cst_from_objc_string (tree);
 extern tree objc_get_protocol_qualified_type (tree, tree);
 extern tree objc_get_class_reference (tree);
 extern tree objc_get_class_ivars (tree);
diff -rupN --exclude=.svn trunk9/gcc/c-family/c-format.c trunk8/gcc/c-family/c-format.c
--- trunk9/gcc/c-family/c-format.c	2010-10-31 16:14:36.000000000 +0000
+++ trunk8/gcc/c-family/c-format.c	2010-11-01 04:15:59.000000000 +0000
@@ -63,6 +63,7 @@ enum format_type { printf_format_type, a
 		   gcc_diag_format_type, gcc_tdiag_format_type,
 		   gcc_cdiag_format_type,
 		   gcc_cxxdiag_format_type, gcc_gfc_format_type,
+		   nsstring_format_type,
 		   format_type_error = -1};
 
 typedef struct function_format_info
@@ -77,12 +78,20 @@ static int decode_format_type (const cha
 
 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, bool objc_string);
 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);
 
+/* Check that 'type' is a C string type.  */
+static bool
+is_string_type (tree type)
+{
+  return (TREE_CODE (type) == POINTER_TYPE
+	  && (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == char_type_node));
+}
+
 /* Handle a "format_arg" attribute; arguments as in
    struct attribute_spec.handler.  */
 tree
@@ -101,16 +110,16 @@ handle_format_arg_attribute (tree *node,
       return NULL_TREE;
     }
 
+  /* TODO: Support for nsstring_format_type.  */
+
   argument = TYPE_ARG_TYPES (type);
   if (argument)
     {
-      if (!check_format_string (argument, format_num, flags, no_add_attrs))
+      if (!check_format_string (argument, format_num, flags, no_add_attrs, false))
 	return NULL_TREE;
     }
 
-  if (TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
-      || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
-	  != char_type_node))
+  if (!is_string_type (TREE_TYPE (type)))
     {
       if (!(flags & (int) ATTR_FLAG_BUILT_IN))
 	error ("function does not return string type");
@@ -125,7 +134,7 @@ handle_format_arg_attribute (tree *node,
    the format attribute is in error.  */
 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, bool objc_string)
 {
   unsigned HOST_WIDE_INT i;
 
@@ -136,15 +145,25 @@ check_format_string (tree argument, unsi
       argument = TREE_CHAIN (argument);
     }
 
-  if (!argument
-      || TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE
-      || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument)))
-	  != char_type_node))
+  if (!objc_string)
     {
-      if (!(flags & (int) ATTR_FLAG_BUILT_IN))
-	error ("format string argument not a string type");
-      *no_add_attrs = true;
-      return false;
+      if (!argument  ||  !is_string_type (TREE_VALUE (argument)))
+	{
+	  if (!(flags & (int) ATTR_FLAG_BUILT_IN))
+	    error ("format string argument not a string type");
+	  *no_add_attrs = true;
+	  return false;
+	}
+    }
+  else
+    {
+      if (!argument  ||  !objc_is_string_type (TREE_VALUE (argument)))
+	{
+	  if (!(flags & (int) ATTR_FLAG_BUILT_IN))
+	    error ("format string argument not an Objective-C string type");
+	  *no_add_attrs = true;
+	  return false;
+	}
     }
 
   return true;
@@ -273,6 +292,9 @@ typedef struct format_wanted_type
   /* Whether the argument, dereferenced once, is read from and so
      must not be a NULL pointer.  */
   int reading_from_flag;
+  /* Whether the argument must be an Objective-C object pointer type
+     and we need to use objc_is_object_ptr() to check it.  */
+  int objc_object_flag;
   /* If warnings should be of the form "field precision should have
      type 'int'", the name to use (in this case "field precision"),
      otherwise NULL, for "format expects type 'long'" type
@@ -358,6 +380,8 @@ static const format_length_info gcc_gfc_
   { NO_FMT, NO_FMT, 0 }
 };
 
+/* 'NSString' format is identical to printf for these.  */
+#define nsstring_length_specs printf_length_specs
 
 static const format_flag_spec printf_flag_specs[] =
 {
@@ -418,6 +442,8 @@ static const format_flag_pair gcc_gfc_fl
   { 0, 0, 0, 0 }
 };
 
+#define nsstring_flag_pairs printf_flag_pairs
+
 static const format_flag_spec gcc_diag_flag_specs[] =
 {
   { '+',  0, 0, N_("'+' flag"),        N_("the '+' printf flag"),              STD_C89 },
@@ -432,6 +458,8 @@ static const format_flag_spec gcc_diag_f
 #define gcc_cdiag_flag_specs gcc_diag_flag_specs
 #define gcc_cxxdiag_flag_specs gcc_diag_flag_specs
 
+#define nsstring_flag_specs printf_flag_specs
+
 static const format_flag_spec scanf_flag_specs[] =
 {
   { '*',  0, 0, N_("assignment suppression"), N_("the assignment suppression scanf feature"), STD_C89 },
@@ -651,6 +679,32 @@ static const format_char_info gcc_gfc_ch
   { NULL,  0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
 };
 
+/* This is identical to the printf one, except for the addition of %@, used for Objective-C objects.  */
+static const format_char_info nsstring_char_table[] =
+{
+  /* C89 conversion specifiers.  */
+  { "di",  0, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  TEX_LL,  T99_SST, T99_PD,  T99_IM,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +'I",  "i",  NULL },
+  { "oxX", 0, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM, BADLEN,  BADLEN,  BADLEN }, "-wp0#",     "i",  NULL },
+  { "u",   0, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM, BADLEN,  BADLEN,  BADLEN }, "-wp0'I",    "i",  NULL },
+  { "fgG", 0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN,  TEX_D32, TEX_D64, TEX_D128 }, "-wp0 +#'I", "",   NULL },
+  { "eE",  0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN,  TEX_D32, TEX_D64, TEX_D128 }, "-wp0 +#I",  "",   NULL },
+  { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T94_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-w",        "",   NULL },
+  { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-wp",       "cR", NULL },
+  { "p",   1, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-w",        "c",  NULL },
+  { "n",   1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  T99_IM,  BADLEN,  BADLEN,  BADLEN }, "",          "W",  NULL },
+  /* C99 conversion specifiers.  */
+  { "F",   0, STD_C99, { T99_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN,  TEX_D32, TEX_D64, TEX_D128 }, "-wp0 +#'I", "",   NULL },
+  { "aA",  0, STD_C99, { T99_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-wp0 +#",   "",   NULL },
+  /* X/Open conversion specifiers.  */
+  { "C",   0, STD_EXT, { TEX_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-w",        "",   NULL },
+  { "S",   1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-wp",       "R",  NULL },
+  /* GNU conversion specifiers.  */
+  { "m",   0, STD_EXT, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-wp",       "",   NULL },
+  /* Objective-C conversion specfier.  */
+  { "@",   1, STD_C89, { T89_AT,  BADLEN,  BADLEN,  BADLEN,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-wp",       "@", NULL },
+  { NULL,  0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
+};
+
 static const format_char_info scan_char_table[] =
 {
   /* C89 conversion specifiers.  */
@@ -750,6 +804,12 @@ static const format_kind_info format_typ
     0, 0, 0, 0, 0, 0,
     NULL, NULL
   },
+  { "NSString", nsstring_length_specs, nsstring_char_table, "+#0-I", NULL,
+    nsstring_flag_specs, nsstring_flag_pairs,
+    FMT_FLAG_ARG_CONVERT|FMT_FLAG_DOLLAR_MULTIPLE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_EMPTY_PREC_OK,
+    'w', 0, 'p', 0, 'L', 0,
+    &integer_type_node, &integer_type_node
+  },
   { "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,
@@ -1364,16 +1424,31 @@ check_format_arg (void *ctx, tree format
       array_size = DECL_SIZE_UNIT (format_tree);
       format_tree = array_init;
     }
+
+  /* nsstring_format_type is special because the format string is an
+     Objective-C string.  See if we can extract the constant
+     string.  */
+  if (info->format_type == nsstring_format_type)
+    format_tree = objc_maybe_extract_string_cst_from_objc_string (format_tree);
+
   if (TREE_CODE (format_tree) != STRING_CST)
     {
       res->number_non_literal++;
       return;
     }
-  if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (format_tree))) != char_type_node)
+  /* FIXME: The STRING_CST associated with Objective-C constant
+     strings is most definitely a traditional ASCII string, yet it
+     seems not to be marked with a char_type_node.  Until that is
+     fixed, do not perform this test for Objective-C strings.  */
+  if (info->format_type != nsstring_format_type)
     {
-      res->number_wide++;
-      return;
+      if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (format_tree))) != char_type_node)
+	{
+	  res->number_wide++;
+	  return;
+	}
     }
+
   format_chars = TREE_STRING_POINTER (format_tree);
   format_length = TREE_STRING_LENGTH (format_tree);
   if (array_size != 0)
@@ -2081,6 +2156,8 @@ check_format_info_main (format_check_res
 	      wanted_type_ptr->char_lenient_flag = 0;
 	      if (strchr (fci->flags2, 'c') != 0)
 		wanted_type_ptr->char_lenient_flag = 1;
+	      if (strchr (fci->flags2, '@') != 0)
+		wanted_type_ptr->objc_object_flag = 1;
 	      wanted_type_ptr->scalar_identity_flag = 0;
 	      if (scalar_identity_flag)
 		wanted_type_ptr->scalar_identity_flag = 1;
@@ -2241,6 +2318,10 @@ check_format_types (format_wanted_type *
 			  || cur_type == signed_char_type_node
 			  || cur_type == unsigned_char_type_node);
 
+      /* Check for Objective-C objects.  */
+      if (types->objc_object_flag  &&  objc_is_object_ptr (cur_type))
+	continue;
+
       /* Check the type of the "real" argument, if there's a type we want.  */
       if (lang_hooks.types_compatible_p (wanted_type, cur_type))
 	continue;
@@ -2798,8 +2879,16 @@ handle_format_attribute (tree *node, tre
   argument = TYPE_ARG_TYPES (type);
   if (argument)
     {
+      bool objc_string = false;
+
+      /* In Objective-C, the special NSString format type is allowed,
+	 where the format string is an Objective-C string instead of
+	 a C string.  */
+      if (c_dialect_objc ()  &&  info.format_type == nsstring_format_type)
+	objc_string = true;
+
       if (!check_format_string (argument, info.format_num, flags,
-				no_add_attrs))
+				no_add_attrs, objc_string))
 	return NULL_TREE;
 
       if (info.first_arg_num != 0)
diff -rupN --exclude=.svn trunk9/gcc/c-family/c-format.h trunk8/gcc/c-family/c-format.h
--- trunk9/gcc/c-family/c-format.h	2010-09-23 23:39:18.000000000 +0100
+++ trunk8/gcc/c-family/c-format.h	2010-11-01 04:17:07.000000000 +0000
@@ -142,14 +142,16 @@ typedef struct format_char_info
      modifiers.  */
   const char *flag_chars;
   /* List of additional flags describing these conversion specifiers.
-     "c" for generic character pointers being allowed, "2" for strftime
-     two digit year formats, "3" for strftime formats giving two digit
-     years in some locales, "4" for "2" which becomes "3" with an "E" modifier,
-     "o" if use of strftime "O" is a GNU extension beyond C99,
-     "W" if the argument is a pointer which is dereferenced and written into,
-     "R" if the argument is a pointer which is dereferenced and read from,
-     "i" for printf integer formats where the '0' flag is ignored with
-     precision, and "[" for the starting character of a scanf scanset.  */
+     "c" for generic character pointers being allowed, "2" for
+     strftime two digit year formats, "3" for strftime formats giving
+     two digit years in some locales, "4" for "2" which becomes "3"
+     with an "E" modifier, "o" if use of strftime "O" is a GNU
+     extension beyond C99, "W" if the argument is a pointer which is
+     dereferenced and written into, "R" if the argument is a pointer
+     which is dereferenced and read from, "i" for printf integer
+     formats where the '0' flag is ignored with precision, "[" for the
+     starting character of a scanf scanset and "@" for Objective-C
+     objects being allowed.  */
   const char *flags2;
   /* If this format conversion character consumes more than one argument,
      CHAIN points to information about the next argument.  For later
@@ -286,6 +288,9 @@ typedef struct
 #define T99_UC	{ STD_C99, NULL, T_UC }
 #define T_V	&void_type_node
 #define T89_V	{ STD_C89, NULL, T_V }
+/* TODO: In the following, it would be better to print 'id' but we
+   need to avoid the '*' for the pointer.  */
+#define T89_AT	{ STD_C89, "struct object", T_V }
 #define T_W	&wchar_type_node
 #define T94_W	{ STD_C94, "wchar_t", T_W }
 #define TEX_W	{ STD_EXT, "wchar_t", T_W }
diff -rupN --exclude=.svn trunk9/gcc/c-family/ChangeLog trunk8/gcc/c-family/ChangeLog
--- trunk9/gcc/c-family/ChangeLog	2010-10-31 17:36:18.000000000 +0000
+++ trunk8/gcc/c-family/ChangeLog	2010-11-01 04:22:58.000000000 +0000
@@ -1,5 +1,29 @@
 2010-10-31  Nicola Pero  <nicola.pero@meta-innovation.com>
 
+	* c-common.h (objc_is_string_type): New.
+	(objc_maybe_extract_string_cst_from_objc_string): New.
+	* stub-objc.c (objc_is_string_type): New.
+	(objc_maybe_extract_string_cst_from_objc_string): New.	
+	* c-format.c (is_string_type): New.
+	(handle_format_arg_attribute): Updated call to
+	check_format_string.  Use is_string_type.
+	(check_format_string): Added objc_string argument.  If set, check
+	that the format string is an Objective-C string.
+	(handle_format_attribute): For nsstring_format_type, check that
+	format strings are Objective-C strings.
+	(struct format_wanted_type): Added objc_object_flag.
+	(nsstring_length_specs): New.
+	(nsstring_flag_pairs): New.
+	(nsstring_flag_specs): New.
+	(nsstring_char_table): New.
+	(check_format_arg): Implemented nsstring_format_type.
+	(check_format_info_main): Implemented '@' as valid flag2.
+	(check_format_types): Implemented objc_object_flag.
+	* c-format.h: Updated comments.
+	(T89_AT): New.	
+	
+2010-10-31  Nicola Pero  <nicola.pero@meta-innovation.com>
+
 	Implemented format and noreturn attributes for Objective-C methods.
 	* c-common.c (handle_noreturn_attribute): Recognize 'noreturn'
 	attribute for Objective-C methods.
diff -rupN --exclude=.svn trunk9/gcc/c-family/stub-objc.c trunk8/gcc/c-family/stub-objc.c
--- trunk9/gcc/c-family/stub-objc.c	2010-10-30 12:26:13.000000000 +0100
+++ trunk8/gcc/c-family/stub-objc.c	2010-11-01 02:54:50.000000000 +0000
@@ -44,6 +44,12 @@ objc_is_object_ptr (tree ARG_UNUSED (arg
   return 0;
 }
 
+bool
+objc_is_string_type (tree ARG_UNUSED (arg))
+{
+  return 0;
+}
+
 bool objc_diagnose_private_ivar (tree ARG_UNUSED (arg))
 {
   return false;
@@ -281,6 +287,12 @@ objc_build_string_object (tree ARG_UNUSE
 }
 
 tree
+objc_maybe_extract_string_cst_from_objc_string (tree ARG_UNUSED (str))
+{
+  return 0;
+}
+
+tree
 objc_get_class_reference (tree ARG_UNUSED (name))
 {
   return 0;
diff -rupN --exclude=.svn trunk9/gcc/objc/ChangeLog trunk8/gcc/objc/ChangeLog
--- trunk9/gcc/objc/ChangeLog	2010-10-31 17:36:23.000000000 +0000
+++ trunk8/gcc/objc/ChangeLog	2010-11-01 04:23:36.000000000 +0000
@@ -1,5 +1,10 @@
 2010-10-31  Nicola Pero  <nicola.pero@meta-innovation.com>
 
+	* objc-act.c (objc_is_string_type): New.
+	(objc_maybe_extract_string_cst_from_objc_string): New.
+	
+2010-10-31  Nicola Pero  <nicola.pero@meta-innovation.com>
+
 	Implemented format and noreturn attributes for Objective-C methods.
 	* objc-act.c (objc_start_method_definition): If method attributes
 	are specified emit a warning and ignore them.
diff -rupN --exclude=.svn trunk9/gcc/objc/objc-act.c trunk8/gcc/objc/objc-act.c
--- trunk9/gcc/objc/objc-act.c	2010-10-31 17:52:48.000000000 +0000
+++ trunk8/gcc/objc/objc-act.c	2010-11-01 04:23:27.000000000 +0000
@@ -2611,6 +2611,61 @@ objc_build_string_object (tree string)
   return addr;
 }
 
+/* This is the inversion of objc_build_string_object: examine
+   'objc_string', and if it is an Objective-C constant string created
+   by objc_build_string_object, extract the C string embedded into it
+   and return it as a STRING_CST node.  Return 'objc_string' if
+   'objc_string' is not an Objective-C constant string, or if we could
+   not extract the STRING_CST.  */
+tree
+objc_maybe_extract_string_cst_from_objc_string (tree objc_string)
+{
+  tree constructor, expr;
+  VEC(constructor_elt,gc) *elts;
+
+  /* This is a simple implementation.  */
+  /* TODO: Better error checking.  */
+  if (TREE_CODE (objc_string) != VAR_DECL
+      || TREE_CODE (TREE_TYPE (objc_string)) != RECORD_TYPE)
+    return objc_string;
+
+  constructor = DECL_INITIAL (objc_string);
+
+  if (!TREE_READONLY (constructor)
+      || !TREE_CONSTANT (constructor)
+      || !TREE_STATIC (constructor))
+    return objc_string;
+
+  if (TREE_CODE (constructor) != CONSTRUCTOR)
+    return objc_string;
+
+  /* Get the second field (the first one is 'isa', the second one is
+     the constant string, the third one is the length.  */
+  elts = CONSTRUCTOR_ELTS (constructor);
+  if (VEC_length (constructor_elt, elts) != 3)
+    return objc_string;
+
+  expr = VEC_index (constructor_elt, elts, 1)->value;
+
+  if (!expr || TREE_CODE (expr) != ADDR_EXPR)
+    {
+      printf ("expr not ADDR_EXPR\n");
+      debug_tree (expr);
+      return objc_string;
+    }
+
+  expr = TREE_OPERAND (expr, 0);
+
+  if (!expr || TREE_CODE (expr) != STRING_CST)
+    {
+      printf ("expr not STRING_CST\n");
+      debug_tree (expr);
+      return objc_string;
+    }
+
+  return expr;
+}
+
 /* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR.  */
 
 static GTY(()) int num_static_inst;
@@ -3667,6 +3722,55 @@ objc_is_object_ptr (tree type)
   return ret;
 }
 
+/* Check whether TYPE is an Objective-C string class; at the moment,
+   this means NSString, NSMutableString or the constant string class.
+   This is used to check that a function or method marked with
+   __attribute__ ((format (NSString, 1, 2))) has the correct prototype
+   with an (NSString *) argument for the format string.  */
+
+bool
+objc_is_string_type (tree type)
+{
+  tree objc_type_name;
+
+  /* First, determine that it looks roughly like an Objective-C object
+     type.  */
+  type = TYPE_MAIN_VARIANT (type);
+  if (!POINTER_TYPE_P (type))
+    return false;
+
+  /* We determined it is a pointer; get what it points to.  */
+  type = TREE_TYPE (type);
+
+  /* It should point to a RECORD_TYPE (the Class).  */
+  if (TREE_CODE (type) != RECORD_TYPE)
+    return false;
+
+  /* Now, try to determine if it is an Objective-C string type.  A
+     careful check (TODO) would look at the class hierarchy and accept
+     any Objective-C class that inherits from NSString.  In practice,
+     this function is used to check the string format argument in an
+     NSString format type, which is practically always NSString, so we
+     can just check that the class name is NSString.  To be a bit more
+     flexible, we also accept NSMutableString and the constant string
+     class name.  */
+  objc_type_name = OBJC_TYPE_NAME (type);
+
+  if (objc_type_name  &&  TREE_CODE (objc_type_name) == IDENTIFIER_NODE)
+    {
+      const char * name = IDENTIFIER_POINTER (objc_type_name);
+      if (TYPE_HAS_OBJC_INFO (type)  &&  TYPE_OBJC_INTERFACE (type))
+	{
+	  if (strcmp (name, constant_string_class_name) == 0
+	      || strncmp (name, "NSString", 8) == 0
+	      || strncmp (name, "NSMutableString", 15) == 0)
+	    return true;
+	}
+    }
+
+  return false;
+}
+
 static int
 objc_is_gcable_type (tree type, int or_strong_p)
 {
diff -rupN --exclude=.svn trunk9/gcc/testsuite/ChangeLog trunk8/gcc/testsuite/ChangeLog
--- trunk9/gcc/testsuite/ChangeLog	2010-10-31 17:59:55.000000000 +0000
+++ trunk8/gcc/testsuite/ChangeLog	2010-11-01 04:23:59.000000000 +0000
@@ -1,4 +1,8 @@
 2010-10-31  Nicola Pero  <nicola.pero@meta-innovation.com>
+	
+	* objc.dg/attributes/method-format-2.m: New.
+
+2010-10-31  Nicola Pero  <nicola.pero@meta-innovation.com>
 
 	Implemented format and noreturn attributes for Objective-C methods.
 	* objc.dg/attributes/method-attribute-2.m: Updated warnings.
diff -rupN --exclude=.svn trunk9/gcc/testsuite/objc.dg/attributes/method-format-2.m trunk8/gcc/testsuite/objc.dg/attributes/method-format-2.m
--- trunk9/gcc/testsuite/objc.dg/attributes/method-format-2.m	1970-01-01 01:00:00.000000000 +0100
+++ trunk8/gcc/testsuite/objc.dg/attributes/method-format-2.m	2010-11-01 04:28:07.000000000 +0000
@@ -0,0 +1,59 @@
+/* Contributed by Nicola Pero <nicola.pero@meta-innovation.com>, October 2010.  */
+/* { dg-do compile } */
+/* { dg-options "-Wall -fconstant-string-class=MyString" } */
+
+#include <objc/objc.h>
+#include <stdlib.h>
+
+@interface MyString
+{
+@public
+  Class isa;
+  char *c_string;
+  unsigned int len;
+}
+@end
+
+@implementation MyString
+@end
+
+@interface LogObject
+{
+  Class isa;
+} 
++ (void) log: (int)level  message: (MyString *) my_format, ...  __attribute__ ((format (NSString, 2, 3)));
+- (void) log: (int)level  message: (MyString *) my_format, ...  __attribute__ ((format (NSString, 2, 3)));
+
++ (void) debug: (MyString *) my_format, ...  __attribute__ ((format (NSString, 1, 2)));
+- (void) debug: (MyString *) my_format, ...  __attribute__ ((format (NSString, 1, 2)));
+
+/* Just make sure a missing or invalid attribute won't crash the compiler.  */
+- (void) log2: (int)level  message: (MyString *) my_format, ...  __attribute__ ((format (NSString, 2)));      /* { dg-error "wrong" } */
+- (void) log3: (int)level  message: (const char *) my_format, ...  __attribute__ ((format (NSString, 2, 3))); /* { dg-error "not an Objective.C string type" } */
+- (void) log4: (int)level  message: (LogObject *) my_format, ...  __attribute__ ((format (NSString, 2, 3)));  /* { dg-error "not an Objective.C string type" } */
++ (void) debug2: (MyString *) my_format, ...  __attribute__ ((format (NSString))); /* { dg-error "wrong" } */
+- (void) debug2: (MyString *) my_format, ...  __attribute__ ((format (NSString))); /* { dg-error "wrong" } */
++ (void) alert: (MyString *) my_format __attribute__ ((format (NSString, 1, 2))); /* { dg-error "args to be formatted is not ..." } */
+- (void) alert: (MyString *) my_format __attribute__ ((format (NSString, 1, 2))); /* { dg-error "args to be formatted is not ..." } */
+@end
+
+void test (LogObject *object)
+{
+  [object log: 2  message: @"attribute only applies to variadic functions"];
+  [object log: 2  message: @"%d: attribute %@ only applies to variadic functions", 23, @"'format'"];
+  [object log: 2  message: @"%d: attribute %@ only applies to variadic functions", 23]; /* { dg-warning "too few arguments for format" } */
+  [object log: 2  message: @"%d: attribute %@ only applies to variadic functions", @"'format'", 23]; /* { dg-warning "format ..@. expects" } */
+
+  [object debug: @"attribute only applies to variadic functions"];
+  [object debug: @"%d:%d: attribute %@ only applies to variadic functions", 23, 11, @"'format'"];
+  [object debug: @"%d:%d: attribute %@ only applies to variadic functions", 23, @"'format'"]; /* { dg-warning "too few arguments for format" } */
+  [object debug: @"%d:%d: attribute %@ only applies to variadic functions", 23, @"'format'", 11]; /* { dg-warning "format ..@. expects" } */
+
+  [LogObject log: 2  message: @"attribute only applies to variadic functions"];
+  [LogObject log: 2  message: @"attribute %@ only applies to variadic functions", @"'format'"];
+  [LogObject log: 2  message: @"attribute %@ only applies to variadic functions"]; /* { dg-warning "too few arguments for format" } */
+
+  [LogObject debug: @"attribute only applies to variadic functions"];
+  [LogObject debug: @"attribute %@ only applies to variadic functions", @"'format'"];
+  [LogObject debug: @"attribute %@ only applies to variadic functions"]; /* { dg-warning "too few arguments for format" } */
+}
Binary files trunk9/gcc/testsuite/objc.dg/attributes/method-format-2.o and trunk8/gcc/testsuite/objc.dg/attributes/method-format-2.o differ

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2010-11-06 11:24 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-24 15:09 [Patch, c* ,ObjC*] handle string objects in format checking IainS
2010-10-24 17:13 ` Joseph S. Myers
2010-10-24 19:08   ` IainS
2010-10-24 19:25     ` Joseph S. Myers
2010-10-24 19:47       ` IainS
2010-10-25  2:07         ` Jack Howarth
2010-10-25  2:32           ` Nicola Pero
2010-10-25  9:48             ` IainS
2010-10-25 10:36         ` Mike Stump
2010-10-28 18:05           ` Updated: " IainS
2010-10-28 19:43             ` Joseph S. Myers
2010-10-28 22:59               ` IainS
2010-10-31 21:39                 ` Nicola Pero
2010-10-31 22:03                   ` IainS
2010-10-31 23:24                     ` Nicola Pero
2010-10-31 23:38                       ` IainS
2010-11-05 17:05                 ` Joseph S. Myers
2010-11-06 11:25                   ` IainS
2010-11-01  4:38 Nicola Pero
2010-11-01  8:09 ` Paolo Bonzini
2010-11-01  8:16   ` Paolo Bonzini
2010-11-01  8:50   ` IainS
2010-11-01  8:59 ` IainS
2010-11-01  9:42   ` Nicola Pero
2010-11-01 10:18     ` IainS
2010-11-01 13:17     ` Joseph S. Myers
2010-11-01 14:39       ` IainS
2010-11-01 14:48         ` Joseph S. Myers
2010-11-01 19:09       ` Nicola Pero

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).