Index: gcc/target.def
===================================================================
--- gcc/target.def	(revision 165683)
+++ gcc/target.def	(working copy)
@@ -2510,4 +2519,10 @@ DEFHOOK
  bool, (size_t code, const char *arg, int value),
  default_handle_c_option)
 
+DEFHOOK
+(objc_construct_string,
+ "Construct a constant string representation for @var{string}",
+ tree, (tree string),
+ NULL)
+
 HOOK_VECTOR_END (C90_EMPTY_HACK)
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(revision 165683)
+++ gcc/doc/tm.texi	(working copy)
@@ -757,6 +757,10 @@ 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}
+@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 165683)
+++ gcc/doc/tm.texi.in	(working copy)
@@ -757,6 +757,8 @@ only available in the C (and related language) fro
 should use @code{TARGET_HANDLE_C_OPTION} instead.
 @end deftypefn
 
+@hook TARGET_OBJC_CONSTRUCT_STRING
+
 @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/config/t-darwin
===================================================================
--- gcc/config/t-darwin	(revision 165683)
+++ gcc/config/t-darwin	(working copy)
@@ -21,7 +21,7 @@ darwin.o: $(srcdir)/config/darwin.c $(CONFIG_H) $(
   $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(REAL_H) insn-config.h         \
   conditions.h insn-flags.h output.h insn-attr.h flags.h $(TREE_H) expr.h   \
   reload.h function.h $(GGC_H) langhooks.h $(TARGET_H) $(TM_P_H) gt-darwin.h \
-  config/darwin-sections.def
+  c-tree.h c-lang.h config/darwin-sections.def
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
 		$(srcdir)/config/darwin.c
 
Index: gcc/config/darwin.opt
===================================================================
--- gcc/config/darwin.opt	(revision 165683)
+++ gcc/config/darwin.opt	(working copy)
@@ -18,6 +18,14 @@
 ; along with GCC; see the file COPYING3.  If not see
 ; <http://www.gnu.org/licenses/>.
 
+mconstant-cfstrings
+Target Report Var(darwin_constant_cfstrings) Init(1)
+Generate compile-time CFString objects
+
+Wnonportable-cfstrings
+Target Report Var(darwin_warn_nonportable_cfstrings) Init(1) Warning
+Warn if constant CFString objects contain non-portable characters
+
 mfix-and-continue
 Target Report Var(darwin_fix_and_continue)
 Generate code suitable for fast turn around debugging
Index: gcc/config/darwin-c.c
===================================================================
--- gcc/config/darwin-c.c	(revision 165683)
+++ gcc/config/darwin-c.c	(working copy)
@@ -608,6 +608,9 @@ darwin_cpp_builtins (cpp_reader *pfile)
      to be defined and won't work if it isn't.  */
   builtin_define_with_value ("__APPLE_CC__", "1", false);
 
+  if (darwin_constant_cfstrings)
+    builtin_define ("__CONSTANT_CFSTRINGS__");
+
   builtin_define_with_value ("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__",
 			     version_as_macro(), false);
 
@@ -658,3 +661,20 @@ handle_c_option (size_t code,
 #define TARGET_HANDLE_C_OPTION handle_c_option
 
 struct gcc_targetcm targetcm = TARGETCM_INITIALIZER;
+
+/* Allow ObjC* access to CFStrings.  */
+tree
+darwin_objc_construct_string (tree str)
+{
+  if (!darwin_constant_cfstrings)
+    {
+    /* Even though we are not using CFStrings, place our literal
+       into the cfstring_htab hash table, so that the
+       darwin_constant_cfstring_p() function will see it.  */
+      darwin_enter_string_into_cfstring_table (str);
+      /* Fall back to NSConstantString.  */
+      return NULL_TREE;
+    }
+
+  return darwin_build_constant_cfstring (str);
+}
Index: gcc/config/i386/darwin.h
===================================================================
--- gcc/config/i386/darwin.h	(revision 165683)
+++ gcc/config/i386/darwin.h	(working copy)
@@ -314,3 +314,10 @@ extern int darwin_emit_branch_islands;
 #define MACHO_SYMBOL_FLAG_VARIABLE ((SYMBOL_FLAG_MACH_DEP) << 3)
 
 #define SUBTARGET32_DEFAULT_CPU "i686"
+
+#undef  SUBTARGET_INIT_BUILTINS
+#define SUBTARGET_INIT_BUILTINS		\
+do {					\
+  darwin_init_cfstring_builtins ();	\
+} while(0)
+
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 165683)
+++ gcc/config/i386/i386.c	(working copy)
@@ -24390,6 +24390,10 @@ ix86_init_builtins (void)
 
   if (TARGET_64BIT)
     ix86_init_builtins_va_builtins_abi ();
+
+#ifdef SUBTARGET_INIT_BUILTINS
+  SUBTARGET_INIT_BUILTINS;
+#endif
 }
 
 /* Return the ix86 builtin for CODE.  */
Index: gcc/config/darwin-protos.h
===================================================================
--- gcc/config/darwin-protos.h	(revision 165683)
+++ gcc/config/darwin-protos.h	(working copy)
@@ -91,6 +91,14 @@ extern void darwin_asm_declare_constant_name (FILE
 					      const_tree, HOST_WIDE_INT);
 extern bool darwin_binds_local_p (const_tree);
 extern void darwin_cpp_builtins (struct cpp_reader *);
+
+extern void darwin_init_cfstring_builtins (void);
+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 void darwin_enter_string_into_cfstring_table (tree);
+
 extern void darwin_asm_output_anchor (rtx symbol);
 extern bool darwin_kextabi_p (void);
 extern void darwin_override_options (void);
Index: gcc/config/rs6000/darwin.h
===================================================================
--- gcc/config/rs6000/darwin.h	(revision 165683)
+++ gcc/config/rs6000/darwin.h	(working copy)
@@ -436,5 +436,10 @@ extern int darwin_emit_branch_islands;
    default, as kernel code doesn't save/restore those registers.  */
 #define OS_MISSING_ALTIVEC (flag_mkernel || flag_apple_kext)
 
-/* Darwin has to rename some of the long double builtins.  */
-#define SUBTARGET_INIT_BUILTINS darwin_patch_builtins ()
+/* PPC Darwin has to rename some of the long double builtins.  */
+#undef  SUBTARGET_INIT_BUILTINS
+#define SUBTARGET_INIT_BUILTINS		\
+do {					\
+  darwin_patch_builtins ();		\
+  darwin_init_cfstring_builtins ();	\
+} while(0)
Index: gcc/config/darwin.c
===================================================================
--- gcc/config/darwin.c	(revision 165683)
+++ gcc/config/darwin.c	(working copy)
@@ -41,6 +41,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "target.h"
 #include "tm_p.h"
+#include "c-tree.h"
+#include "c-lang.h"
 #include "diagnostic-core.h"
 #include "toplev.h"
 #include "hashtab.h"
@@ -85,12 +87,26 @@ along with GCC; see the file COPYING3.  If not see
    kernel) the stubs might still be required, and this will be set true.  */
 int darwin_emit_branch_islands = false;
 
+/* A flag to determine whether we are running c++ or obj-c++.  This has to be
+   settable from non-c-family contexts too (i.e. we can't use the c_dialect_
+   functions).  */
+int darwin_running_cxx;
+
 /* Section names.  */
 section * darwin_sections[NUM_DARWIN_SECTIONS];
 
 /* True if we're setting __attribute__ ((ms_struct)).  */
 int darwin_ms_struct = false;
 
+/* We declare target-specific builtins.  */
+enum darwin_builtins
+{
+  DARWIN_BUILTIN_MIN = (int)END_BUILTINS,
+
+  DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING,
+  DARWIN_BUILTIN_MAX
+};
+
 /* A get_unnamed_section callback used to switch to an ObjC section.
    DIRECTIVE is as for output_section_asm_op.  */
 
@@ -1256,6 +1272,8 @@ machopic_select_section (tree decl,
           else
             return darwin_sections[objc_string_object_section];
         }
+      else if (!strcmp (IDENTIFIER_POINTER (name), "__builtin_CFString"))
+	return darwin_sections[cfstring_constant_object_section];
       else
         return base_section;
     }
@@ -1910,6 +1915,9 @@ darwin_override_options (void)
   if (darwin_macosx_version_min
       && strverscmp (darwin_macosx_version_min, "10.5") < 0)
     darwin_emit_branch_islands = true;
+
+  /* The c_dialect...() macros are not available to us here.  */
+  darwin_running_cxx = (strstr (lang_hooks.name, "C++") != 0);
 }
 
 /* Add $LDBL128 suffix to long double builtins.  */
@@ -1954,5 +1962,300 @@ darwin_patch_builtins (void)
 #undef PATCH_BUILTIN_VARIADIC
 }
 
+/*  CFStrings implementation.  */
+static GTY(()) tree cfstring_class_reference = NULL_TREE;
+static GTY(()) tree cfstring_type_node = NULL_TREE;
+static GTY(()) tree ccfstring_type_node = NULL_TREE;
+static GTY(()) tree pccfstring_type_node = NULL_TREE;
+static GTY(()) tree pcint_type_node = NULL_TREE;
+static GTY(()) tree pcchar_type_node = NULL_TREE;
 
+/* Store all constructed constant CFStrings in a hash table so that
+   they get uniqued properly.  */
+
+typedef struct GTY (()) cfstring_descriptor {
+  /* The string literal.  */
+  tree literal;
+  /* The resulting constant CFString.  */
+  tree constructor;
+} cfstring_descriptor;
+
+static GTY ((param_is (struct cfstring_descriptor))) htab_t cfstring_htab;
+
+static hashval_t cfstring_hash (const void *);
+static int cfstring_eq (const void *, const void *);
+
+static tree
+add_builtin_field_decl (tree type, const char *name, tree **chain)
+{
+  tree field = build_decl (BUILTINS_LOCATION, FIELD_DECL, 
+			    get_identifier (name), type);
+
+  if (*chain != NULL)
+    **chain = field;
+  *chain = &DECL_CHAIN (field);
+
+  return field;
+}
+
+void
+darwin_init_cfstring_builtins (void)
+{
+  tree cfsfun, fields, pccfstring_ftype_pcchar;
+  tree *chain = NULL;
+
+  /* struct __builtin_CFString {
+       const int *isa;		(will point at
+       int flags;		 __CFConstantStringClassReference)
+       const char *str;
+       long length;
+     };  */
+
+  pcint_type_node = build_pointer_type 
+		   (build_qualified_type (integer_type_node, TYPE_QUAL_CONST));
+
+  pcchar_type_node = build_pointer_type 
+		   (build_qualified_type (char_type_node, TYPE_QUAL_CONST));
+
+  cfstring_type_node = (*lang_hooks.types.make_type) (RECORD_TYPE);
+
+  /* Have to build backwards for finish struct.  */
+  fields = add_builtin_field_decl (long_integer_type_node, "length", &chain);
+  add_builtin_field_decl (pcchar_type_node, "str", &chain);
+  add_builtin_field_decl (integer_type_node, "flags", &chain);
+  add_builtin_field_decl (pcint_type_node, "isa", &chain);
+  finish_builtin_struct (cfstring_type_node, "__builtin_CFString",
+			 fields, NULL_TREE);
+
+  /* const struct __builtin_CFstring *
+     __builtin___CFStringMakeConstantString (const char *); */
+
+  ccfstring_type_node = build_qualified_type 
+			(cfstring_type_node, TYPE_QUAL_CONST);
+  pccfstring_type_node = build_pointer_type (ccfstring_type_node);
+  pccfstring_ftype_pcchar = build_function_type_list 
+			(pccfstring_type_node, pcchar_type_node, NULL_TREE);
+
+  cfsfun  = build_decl (BUILTINS_LOCATION, FUNCTION_DECL, 
+			get_identifier ("__builtin___CFStringMakeConstantString"),
+			pccfstring_ftype_pcchar);
+
+  TREE_PUBLIC (cfsfun) = 1;
+  DECL_EXTERNAL (cfsfun) = 1;
+  DECL_ARTIFICIAL (cfsfun) = 1;
+  DECL_LANG_SPECIFIC (cfsfun) =  ggc_alloc_cleared_lang_decl (sizeof
+                                                          (struct lang_decl));
+  DECL_BUILT_IN_CLASS (cfsfun) = BUILT_IN_MD;
+  DECL_FUNCTION_CODE (cfsfun) = 
+	    (enum built_in_function) DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING;
+  lang_hooks.builtin_function (cfsfun);
+
+  /* extern int __CFConstantStringClassReference[];  */
+  cfstring_class_reference = build_decl (BUILTINS_LOCATION, VAR_DECL,
+		 get_identifier ("__CFConstantStringClassReference"),
+		 build_array_type (integer_type_node, NULL_TREE));
+
+  TREE_PUBLIC (cfstring_class_reference) = 1;
+  TREE_USED (cfstring_class_reference) = 1;
+  DECL_ARTIFICIAL (cfstring_class_reference) = 1;
+  (*lang_hooks.decls.pushdecl) (cfstring_class_reference);
+  DECL_EXTERNAL (cfstring_class_reference) = 1;
+  rest_of_decl_compilation (cfstring_class_reference, 0, 0);
+  
+  /* Initialize the hash table used to hold the constant CFString objects.  */
+  cfstring_htab = htab_create_ggc (31, cfstring_hash, cfstring_eq, NULL);
+}
+
+tree
+darwin_fold_builtin (tree fndecl, int n_args, tree *argp, 
+		     bool ARG_UNUSED (ignore))
+{
+  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+
+  if (fcode == DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING)
+    {
+      if (!darwin_constant_cfstrings)
+	{
+	  error ("built-in function %qD requires the" 
+		 " %<-mconstant-cfstrings%> flag", fndecl);
+	  return error_mark_node;
+	}
+
+      if (n_args != 1)
+	{
+	  error ("built-in function %qD takes one argument only", fndecl);
+	  return error_mark_node;
+	}
+
+      return darwin_build_constant_cfstring (*argp);
+    }
+
+  return NULL_TREE;
+}
+
+static hashval_t
+cfstring_hash (const void *ptr)
+{
+  tree str = ((const struct cfstring_descriptor *)ptr)->literal;
+  const unsigned char *p = (const unsigned char *) TREE_STRING_POINTER (str);
+  int i, len = TREE_STRING_LENGTH (str);
+  hashval_t h = len;
+
+  for (i = 0; i < len; i++)
+    h = ((h * 613) + p[i]);
+
+  return h;
+}
+
+static int
+cfstring_eq (const void *ptr1, const void *ptr2)
+{
+  tree str1 = ((const struct cfstring_descriptor *)ptr1)->literal;
+  tree str2 = ((const struct cfstring_descriptor *)ptr2)->literal;
+  int len1 = TREE_STRING_LENGTH (str1);
+
+  return (len1 == TREE_STRING_LENGTH (str2)
+	  && !memcmp (TREE_STRING_POINTER (str1), TREE_STRING_POINTER (str2),
+		      len1));
+}
+
+tree
+darwin_build_constant_cfstring (tree str)
+{
+  struct cfstring_descriptor *desc, key;
+  void **loc;
+  tree addr;
+
+  if (!str)
+    {
+      error ("CFString literal is missing");
+      return error_mark_node;
+    }
+
+  STRIP_NOPS (str);
+
+  if (TREE_CODE (str) == ADDR_EXPR)
+    str = TREE_OPERAND (str, 0);
+
+  if (TREE_CODE (str) != STRING_CST)
+    {
+      error ("CFString literal expression is not a string constant");
+      return error_mark_node;
+    }
+
+  /* Perhaps we already constructed a constant CFString just like this one? */
+  key.literal = str;
+  loc = htab_find_slot (cfstring_htab, &key, INSERT);
+  desc = (struct cfstring_descriptor *) *loc;
+
+  if (!desc)
+    {
+      tree var, constructor, field ;
+      VEC(constructor_elt,gc) *v = NULL;
+      int length = TREE_STRING_LENGTH (str) - 1;
+
+      if (darwin_warn_nonportable_cfstrings)
+	{
+	  const char *s = TREE_STRING_POINTER (str);
+	  int l = 0;
+
+	  for (l = 0; l < length; l++)
+	    if (!s[l] || !isascii (s[l]))
+	      {
+		warning (darwin_warn_nonportable_cfstrings, "%s in CFString literal",
+			 s[l] ? "non-ASCII character" : "embedded NUL");
+		break;
+	      }
+	}
+
+      *loc = desc = ggc_alloc_cleared_cfstring_descriptor ();
+      desc->literal = str;
+
+      /* isa *. */
+      field = TYPE_FIELDS (ccfstring_type_node);
+      CONSTRUCTOR_APPEND_ELT(v, NULL_TREE, 
+			     build1 (ADDR_EXPR,  TREE_TYPE (field),  
+				     cfstring_class_reference));
+      /* flags */
+      field = DECL_CHAIN (field);
+      CONSTRUCTOR_APPEND_ELT(v, NULL_TREE, 
+			     build_int_cst (TREE_TYPE (field), 0x000007c8));
+      /* string *. */
+      field = DECL_CHAIN (field);
+      CONSTRUCTOR_APPEND_ELT(v, NULL_TREE,
+			     build1 (ADDR_EXPR, TREE_TYPE (field), str));
+      /* length */
+      field = DECL_CHAIN (field);
+      CONSTRUCTOR_APPEND_ELT(v, NULL_TREE,
+			     build_int_cst (TREE_TYPE (field), length));
+
+      constructor = build_constructor (ccfstring_type_node, v);
+      TREE_READONLY (constructor) = 1;
+      TREE_CONSTANT (constructor) = 1;
+      TREE_STATIC (constructor) = 1;
+
+      /* Fromage: The C++ flavor of 'build_unary_op' expects constructor nodes
+	 to have the TREE_HAS_CONSTRUCTOR (...) bit set.  However, this file is
+	 being built without any knowledge of C++ tree accessors; hence, we shall
+	 use the generic accessor that TREE_HAS_CONSTRUCTOR actually maps to!  */
+      if (darwin_running_cxx)
+	TREE_LANG_FLAG_4 (constructor) = 1;  /* TREE_HAS_CONSTRUCTOR  */
+
+      /* Create an anonymous global variable for this CFString.  */
+      var = build_decl (input_location, CONST_DECL, 
+			NULL, TREE_TYPE (constructor));
+      DECL_INITIAL (var) = constructor;
+      TREE_STATIC (var) = 1;
+      DECL_CONTEXT (var) = NULL_TREE;
+      desc->constructor = var;
+    }
+
+  addr = build1 (ADDR_EXPR, pccfstring_type_node, desc->constructor);
+  TREE_CONSTANT (addr) = 1;
+
+  return addr;
+}
+
+bool
+darwin_cfstring_p (tree str)
+{
+  struct cfstring_descriptor key;
+  void **loc;
+
+  if (!str)
+    return false;
+
+  STRIP_NOPS (str);
+
+  if (TREE_CODE (str) == ADDR_EXPR)
+    str = TREE_OPERAND (str, 0);
+
+  if (TREE_CODE (str) != STRING_CST)
+    return false;
+
+  key.literal = str;
+  loc = htab_find_slot (cfstring_htab, &key, NO_INSERT);
+  
+  if (loc)
+    return true;
+
+  return false;
+}
+
+void
+darwin_enter_string_into_cfstring_table (tree str)
+{
+  struct cfstring_descriptor key;
+  void **loc;
+
+  key.literal = str;
+  loc = htab_find_slot (cfstring_htab, &key, INSERT);
+
+  if (!*loc)
+    {
+      *loc = ggc_alloc_cleared_cfstring_descriptor ();
+      ((struct cfstring_descriptor *)*loc)->literal = str;
+    }
+}
+
 #include "gt-darwin.h"
Index: gcc/config/darwin-sections.def
===================================================================
--- gcc/config/darwin-sections.def	(revision 165683)
+++ gcc/config/darwin-sections.def	(working copy)
@@ -33,6 +33,9 @@ DEF_SECTION (cstring_section, SECTION_MERGE | SECT
 DEF_SECTION (literal4_section, SECTION_MERGE, ".literal4", 0)
 DEF_SECTION (literal8_section, SECTION_MERGE, ".literal8", 0)
 DEF_SECTION (literal16_section, SECTION_MERGE, ".literal16", 0)
+/* Unlike constant NSStrings, constant CFStrings do not live  in the __OBJC segment
+  since they may also occur in pure C  or C++ programs.  */
+DEF_SECTION (cfstring_constant_object_section, 0, ".section __DATA, __cfstring", 0)
 DEF_SECTION (constructor_section, 0, ".constructor", 0)
 DEF_SECTION (mod_init_section, 0, ".mod_init_func", 0)
 DEF_SECTION (mod_term_section, 0, ".mod_term_func", 0)
Index: gcc/config/darwin.h
===================================================================
--- gcc/config/darwin.h	(revision 165683)
+++ gcc/config/darwin.h	(working copy)
@@ -1054,6 +1060,12 @@ __enable_execute_stack (void *addr)
 #define TARGET_CXX_CDTOR_RETURNS_THIS (darwin_kextabi_p)
 #define TARGET_KEXTABI flag_apple_kext
 
+/* We have target-specific builtins.  */
+#define TARGET_FOLD_BUILTIN darwin_fold_builtin
+
+#define TARGET_OBJC_CONSTRUCT_STRING \
+  darwin_objc_construct_string
+
 #define TARGET_HAS_TARGETCM 1
 
 #ifndef CROSS_DIRECTORY_STRUCTURE
