Automatic Reference Counting.

Language-design credit goes to a lot of people, but I particularly want
to single out Blaine Garst and Patrick Beard for their contributions.

Compiler implementation credit goes to Argyrios, Doug, Fariborz, and myself,
in no particular order.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133103 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index c929b49..1324926 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -169,6 +169,8 @@
     Res.push_back("-fno-use-cxa-atexit");
   if (Opts.CXXCtorDtorAliases)
     Res.push_back("-mconstructor-aliases");
+  if (Opts.ObjCAutoRefCountExceptions)
+    Res.push_back("-fobjc-arc-eh");
   if (!Opts.DebugPass.empty()) {
     Res.push_back("-mdebug-pass");
     Res.push_back(Opts.DebugPass);
@@ -670,6 +672,10 @@
       Res.push_back("-fobjc-gc-only");
     }
   }
+  if (Opts.ObjCAutoRefCount)
+    Res.push_back("-fobjc-arc");
+  if (Opts.ObjCNoAutoRefCountRuntime)
+    Res.push_back("-fobjc-no-arc-runtime");
   if (!Opts.ObjCInferRelatedResultType)
     Res.push_back("-fno-objc-infer-related-result-type");
   
@@ -951,6 +957,7 @@
                      (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize);
 
   Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose);
+  Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions);
   Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit);
   Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases);
   Opts.CodeModel = Args.getLastArgValue(OPT_mcode_model);
@@ -1480,17 +1487,26 @@
   if (Args.hasArg(OPT_fno_operator_names))
     Opts.CXXOperatorNames = 0;
 
+  if (Opts.ObjC1) {
+    if (Args.hasArg(OPT_fobjc_gc_only))
+      Opts.setGCMode(LangOptions::GCOnly);
+    else if (Args.hasArg(OPT_fobjc_gc))
+      Opts.setGCMode(LangOptions::HybridGC);
+    else if (Args.hasArg(OPT_fobjc_arc)) {
+      Opts.ObjCAutoRefCount = 1;
+      if (!Args.hasArg(OPT_fobjc_nonfragile_abi))
+        Diags.Report(diag::err_arc_nonfragile_abi);
+      if (Args.hasArg(OPT_fobjc_no_arc_runtime))
+        Opts.ObjCNoAutoRefCountRuntime = 1;
+    }
+
+    if (Args.hasArg(OPT_fno_objc_infer_related_result_type))
+      Opts.ObjCInferRelatedResultType = 0;
+  }
+    
   if (Args.hasArg(OPT_fgnu89_inline))
     Opts.GNUInline = 1;
 
-  if (Args.hasArg(OPT_fobjc_gc_only))
-    Opts.setGCMode(LangOptions::GCOnly);
-  else if (Args.hasArg(OPT_fobjc_gc))
-    Opts.setGCMode(LangOptions::HybridGC);
-  
-  if (Args.hasArg(OPT_fno_objc_infer_related_result_type))
-    Opts.ObjCInferRelatedResultType = 0;
-  
   if (Args.hasArg(OPT_fapple_kext)) {
     if (!Opts.CPlusPlus)
       Diags.Report(diag::warn_c_kext);
@@ -1715,6 +1731,19 @@
 
     Opts.addRemappedFile(Split.first, Split.second);
   }
+  
+  if (Arg *A = Args.getLastArg(OPT_fobjc_arc_cxxlib_EQ)) {
+    llvm::StringRef Name = A->getValue(Args);
+    unsigned Library = llvm::StringSwitch<unsigned>(Name)
+      .Case("libc++", ARCXX_libcxx)
+      .Case("libstdc++", ARCXX_libstdcxx)
+      .Case("none", ARCXX_nolib)
+      .Default(~0U);
+    if (Library == ~0U)
+      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
+    else
+      Opts.ObjCXXARCStandardLibrary = (ObjCXXARCStandardLibraryKind)Library;
+  }
 }
 
 static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 147a8df..f1e1d47 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -221,6 +221,125 @@
                         ConstSuffix);
 }
 
+/// \brief Add definitions required for a smooth interaction between
+/// Objective-C++ automatic reference counting and libc++.
+static void AddObjCXXARCLibcxxDefines(const LangOptions &LangOpts, 
+                                      MacroBuilder &Builder) {
+  Builder.defineMacro("_LIBCPP_PREDEFINED_OBJC_ARC_ADDRESSOF");
+  
+  std::string Result;
+  {
+    // Provide overloads of the function std::__1::addressof() that accept
+    // references to lifetime-qualified objects. libc++'s (more general)
+    // std::__1::addressof() template fails to instantiate with such types,
+    // because it attempts to convert the object to a char& before 
+    // dereferencing.
+    llvm::raw_string_ostream Out(Result);
+    
+    Out << "#pragma clang diagnostic push\n"
+        << "#pragma clang diagnostic ignored \"-Wc++0x-extensions\"\n"
+        << "namespace std { inline namespace __1 {\n"
+        << "\n";
+    
+    Out << "template <class _Tp>\n"
+        << "inline __attribute__ ((__visibility__(\"hidden\"), "
+        << "__always_inline__))\n"
+        << "__attribute__((objc_lifetime(strong))) _Tp*\n"
+        << "addressof(__attribute__((objc_lifetime(strong))) _Tp& __x) {\n"
+        << "  return &__x;\n"
+        << "}\n"
+        << "\n";
+      
+    if (!LangOpts.ObjCNoAutoRefCountRuntime) {
+      Out << "template <class _Tp>\n"
+          << "inline __attribute__ ((__visibility__(\"hidden\"),"
+          << "__always_inline__))\n"
+          << "__attribute__((objc_lifetime(weak))) _Tp*\n"
+          << "addressof(__attribute__((objc_lifetime(weak))) _Tp& __x) {\n"
+          << "  return &__x;\n"
+          << "};\n"
+          << "\n";
+    }
+      
+    Out << "template <class _Tp>\n"
+        << "inline __attribute__ ((__visibility__(\"hidden\"),"
+        << "__always_inline__))\n"
+        << "__attribute__((objc_lifetime(autoreleasing))) _Tp*\n"
+        << "addressof(__attribute__((objc_lifetime(autoreleasing))) _Tp& __x) "
+        << "{\n"
+        << " return &__x;\n"
+        << "}\n"
+        << "\n";
+    
+    Out << "template <class _Tp>\n"
+        << "inline __attribute__ ((__visibility__(\"hidden\"), "
+        << "__always_inline__))\n"
+        << "__unsafe_unretained _Tp* addressof(__unsafe_unretained _Tp& __x)"
+        << " {\n"
+        << "  return &__x;\n"
+        << "}\n";
+      
+    Out << "\n"
+        << "} }\n"
+        << "#pragma clang diagnostic pop\n"
+        << "\n";    
+  }
+  Builder.append(Result);
+}
+
+/// \brief Add definitions required for a smooth interaction between
+/// Objective-C++ automated reference counting and libstdc++ (4.2).
+static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts, 
+                                         MacroBuilder &Builder) {
+  Builder.defineMacro("_GLIBCXX_PREDEFINED_OBJC_ARC_IS_SCALAR");
+  
+  std::string Result;
+  {
+    // Provide specializations for the __is_scalar type trait so that 
+    // lifetime-qualified objects are not considered "scalar" types, which
+    // libstdc++ uses as an indicator of the presence of trivial copy, assign,
+    // default-construct, and destruct semantics (none of which hold for
+    // lifetime-qualified objects in ARC).
+    llvm::raw_string_ostream Out(Result);
+    
+    Out << "namespace std {\n"
+        << "\n"
+        << "struct __true_type;\n"
+        << "struct __false_type;\n"
+        << "\n";
+    
+    Out << "template<typename _Tp> struct __is_scalar;\n"
+        << "\n";
+      
+    Out << "template<typename _Tp>\n"
+        << "struct __is_scalar<__attribute__((objc_lifetime(strong))) _Tp> {\n"
+        << "  enum { __value = 0 };\n"
+        << "  typedef __false_type __type;\n"
+        << "};\n"
+        << "\n";
+      
+    if (!LangOpts.ObjCNoAutoRefCountRuntime) {
+      Out << "template<typename _Tp>\n"
+          << "struct __is_scalar<__attribute__((objc_lifetime(weak))) _Tp> {\n"
+          << "  enum { __value = 0 };\n"
+          << "  typedef __false_type __type;\n"
+          << "};\n"
+          << "\n";
+    }
+    
+    Out << "template<typename _Tp>\n"
+        << "struct __is_scalar<__attribute__((objc_lifetime(autoreleasing)))"
+        << " _Tp> {\n"
+        << "  enum { __value = 0 };\n"
+        << "  typedef __false_type __type;\n"
+        << "};\n"
+        << "\n";
+      
+    Out << "}\n";
+  }
+  Builder.append(Result);
+}
+
 static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
                                                const LangOptions &LangOpts,
                                                const FrontendOptions &FEOpts,
@@ -560,6 +679,7 @@
                                    const PreprocessorOptions &InitOpts,
                                    const HeaderSearchOptions &HSOpts,
                                    const FrontendOptions &FEOpts) {
+  const LangOptions &LangOpts = PP.getLangOptions();
   std::string PredefineBuffer;
   PredefineBuffer.reserve(4080);
   llvm::raw_string_ostream Predefines(PredefineBuffer);
@@ -575,10 +695,27 @@
     Builder.append("# 1 \"<built-in>\" 3");
 
   // Install things like __POWERPC__, __GNUC__, etc into the macro table.
-  if (InitOpts.UsePredefines)
-    InitializePredefinedMacros(PP.getTargetInfo(), PP.getLangOptions(),
-                               FEOpts, Builder);
+  if (InitOpts.UsePredefines) {
+    InitializePredefinedMacros(PP.getTargetInfo(), LangOpts, FEOpts, Builder);
 
+    // Install definitions to make Objective-C++ ARC work well with various
+    // C++ Standard Library implementations.
+    if (LangOpts.ObjC1 && LangOpts.CPlusPlus && LangOpts.ObjCAutoRefCount) {
+      switch (InitOpts.ObjCXXARCStandardLibrary) {
+      case ARCXX_nolib:
+        break;
+
+      case ARCXX_libcxx:
+        AddObjCXXARCLibcxxDefines(LangOpts, Builder);
+        break;
+
+      case ARCXX_libstdcxx:
+        AddObjCXXARCLibstdcxxDefines(LangOpts, Builder);
+        break;
+      }
+    }
+  }
+  
   // Even with predefines off, some macros are still predefined.
   // These should all be defined in the preprocessor according to the
   // current language configuration.