aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-06-15 23:02:42 +0000
committerJohn McCall <rjmccall@apple.com>2011-06-15 23:02:42 +0000
commitf85e193739c953358c865005855253af4f68a497 (patch)
treee242284beb7fd2b88a2f3ce08644585497d5910d /lib/Frontend
parent204e13395d83524e9a557c3f3fd6df2e2f353b9d (diff)
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
Diffstat (limited to 'lib/Frontend')
-rw-r--r--lib/Frontend/CompilerInvocation.cpp45
-rw-r--r--lib/Frontend/InitPreprocessor.cpp145
2 files changed, 178 insertions, 12 deletions
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index c929b4926d..1324926f94 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -169,6 +169,8 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts,
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 @@ static void LangOptsToArgs(const LangOptions &Opts,
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 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
(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 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
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 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
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 147a8df037..f1e1d47713 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -221,6 +221,125 @@ static void DefineExactWidthIntType(TargetInfo::IntType Ty,
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 @@ void clang::InitializePreprocessor(Preprocessor &PP,
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 @@ void clang::InitializePreprocessor(Preprocessor &PP,
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.