aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2012-08-21 02:47:43 +0000
committerJohn McCall <rjmccall@apple.com>2012-08-21 02:47:43 +0000
commit0a7dd788dbef975f35f273c7ab913f480f7edd60 (patch)
tree4ff726c6ed21d7c822a307b124bf4fec48ffc89a
parenteb8f2efb17c74620510a38cb437e792ea9c76021 (diff)
Screw around with ObjCRuntime some more, changing the
diagnostics for bad deployment targets and adding a few more predicates. Includes a patch by Jonathan Schleifer to enable ARC for ObjFW. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162252 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td8
-rw-r--r--include/clang/Basic/LangOptions.def2
-rw-r--r--include/clang/Basic/ObjCRuntime.h30
-rw-r--r--include/clang/Driver/ToolChain.h4
-rw-r--r--lib/ARCMigrate/ARCMT.cpp2
-rw-r--r--lib/ARCMigrate/Transforms.cpp2
-rw-r--r--lib/CodeGen/CGObjC.cpp4
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp47
-rw-r--r--lib/Driver/ToolChains.cpp7
-rw-r--r--lib/Driver/ToolChains.h2
-rw-r--r--lib/Driver/Tools.cpp5
-rw-r--r--lib/Frontend/CompilerInvocation.cpp16
-rw-r--r--lib/Frontend/InitPreprocessor.cpp2
-rw-r--r--lib/Lex/PPMacroExpansion.cpp3
-rw-r--r--lib/Sema/SemaCodeComplete.cpp3
-rw-r--r--lib/Sema/SemaObjCProperty.cpp2
-rw-r--r--lib/Sema/SemaType.cpp2
-rw-r--r--test/Driver/arc.c6
18 files changed, 102 insertions, 45 deletions
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index 583b2345c9..a2e15395d6 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -91,10 +91,10 @@ def err_drv_invalid_arch_for_deployment_target : Error<
"invalid architecture '%0' for deployment target '%1'">;
def err_drv_objc_gc_arr : Error<
"cannot specify both '-fobjc-arc' and '%0'">;
-def err_arc_nonfragile_abi : Error<
- "-fobjc-arc is not supported with legacy abi">;
-def err_arc_unsupported : Error<
- "-fobjc-arc is not supported on current deployment target">;
+def err_arc_unsupported_on_runtime : Error<
+ "-fobjc-arc is not supported on platforms using the legacy runtime">;
+def err_arc_unsupported_on_toolchain : Error<
+ "-fobjc-arc is not supported on %select{versions of Mac OS prior to 10.6}0">;
def err_drv_mg_requires_m_or_mm : Error<
"option '-MG' requires '-M' or '-MM'">;
def err_drv_asan_android_requires_pie : Error<
diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def
index fab17a2fe5..3c70028ee3 100644
--- a/include/clang/Basic/LangOptions.def
+++ b/include/clang/Basic/LangOptions.def
@@ -135,7 +135,7 @@ LANGOPT(DefaultFPContract , 1, 0, "FP_CONTRACT")
LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment")
LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility")
LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting")
-LANGOPT(ObjCRuntimeHasWeak , 1, 0, "__weak support in the ARC runtime")
+LANGOPT(ObjCARCWeak , 1, 0, "__weak support in the ARC runtime")
LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map")
LANGOPT(MRTD , 1, 0, "-mrtd calling convention")
diff --git a/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h
index b24fe7cd91..2ca421bb57 100644
--- a/include/clang/Basic/ObjCRuntime.h
+++ b/include/clang/Basic/ObjCRuntime.h
@@ -126,12 +126,25 @@ public:
return !isGNUFamily();
}
+ /// \brief Does this runtime allow ARC at all?
+ bool allowsARC() const {
+ switch (getKind()) {
+ case FragileMacOSX: return false;
+ case MacOSX: return true;
+ case iOS: return true;
+ case GCC: return false;
+ case GNUstep: return true;
+ case ObjFW: return true;
+ }
+ llvm_unreachable("bad kind");
+ }
+
/// \brief Does this runtime natively provide the ARC entrypoints?
///
/// ARC cannot be directly supported on a platform that does not provide
/// these entrypoints, although it may be supportable via a stub
/// library.
- bool hasARC() const {
+ bool hasNativeARC() const {
switch (getKind()) {
case FragileMacOSX: return false;
case MacOSX: return getVersion() >= VersionTuple(10, 7);
@@ -139,16 +152,22 @@ public:
case GCC: return false;
case GNUstep: return getVersion() >= VersionTuple(1, 6);
- case ObjFW: return false; // XXX: this will change soon
+ case ObjFW: return true;
}
llvm_unreachable("bad kind");
}
+ /// Does this runtime allow the use of __weak?
+ bool allowsWeak() const {
+ return hasNativeWeak();
+ }
+
/// \brief Does this runtime natively provide ARC-compliant 'weak'
/// entrypoints?
- bool hasWeak() const {
- // Right now, this is always equivalent to the ARC decision.
- return hasARC();
+ bool hasNativeWeak() const {
+ // Right now, this is always equivalent to whether the runtime
+ // natively supports ARC decision.
+ return hasNativeARC();
}
/// \brief Does this runtime directly support the subscripting methods?
@@ -226,6 +245,7 @@ public:
}
llvm_unreachable("bad kind");
}
+
/// \brief Does this runtime use zero-cost exceptions?
bool hasUnwindExceptions() const {
switch (getKind()) {
diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h
index ab417bb577..bc6331e897 100644
--- a/include/clang/Driver/ToolChain.h
+++ b/include/clang/Driver/ToolChain.h
@@ -183,8 +183,8 @@ public:
/// Does this tool chain support Objective-C garbage collection.
virtual bool SupportsObjCGC() const { return true; }
- /// Does this tool chain support Objective-C ARC.
- virtual bool SupportsObjCARC() const { return true; }
+ /// Complain if this tool chain doesn't support Objective-C ARC.
+ virtual void CheckObjCARC() const {}
/// UseDwarfDebugFlags - Embed the compile options to clang into the Dwarf
/// compile unit information.
diff --git a/lib/ARCMigrate/ARCMT.cpp b/lib/ARCMigrate/ARCMT.cpp
index f291dec21f..14e13ba58c 100644
--- a/lib/ARCMigrate/ARCMT.cpp
+++ b/lib/ARCMigrate/ARCMT.cpp
@@ -237,7 +237,7 @@ createInvocationForMigration(CompilerInvocation &origCI) {
WarnOpts.push_back("error=arc-unsafe-retained-assign");
CInvok->getDiagnosticOpts().Warnings = llvm_move(WarnOpts);
- CInvok->getLangOpts()->ObjCRuntimeHasWeak = HasARCRuntime(origCI);
+ CInvok->getLangOpts()->ObjCARCWeak = HasARCRuntime(origCI);
return CInvok.take();
}
diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp
index 1175c36316..f01dfa9c15 100644
--- a/lib/ARCMigrate/Transforms.cpp
+++ b/lib/ARCMigrate/Transforms.cpp
@@ -40,7 +40,7 @@ bool MigrationPass::CFBridgingFunctionsDefined() {
bool trans::canApplyWeak(ASTContext &Ctx, QualType type,
bool AllowOnUnknownClass) {
- if (!Ctx.getLangOpts().ObjCRuntimeHasWeak)
+ if (!Ctx.getLangOpts().ObjCARCWeak)
return false;
QualType T = type;
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index e0762846dc..4a8a07994a 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -1706,7 +1706,7 @@ static llvm::Constant *createARCRuntimeFunction(CodeGenModule &CGM,
// references to the runtime support library. We don't really
// permit this to fail, but we need a particular relocation style.
if (llvm::Function *f = dyn_cast<llvm::Function>(fn)) {
- if (!CGM.getLangOpts().ObjCRuntime.hasARC())
+ if (!CGM.getLangOpts().ObjCRuntime.hasNativeARC())
f->setLinkage(llvm::Function::ExternalWeakLinkage);
// set nonlazybind attribute for these APIs for performance.
if (fnName == "objc_retain" || fnName == "objc_release")
@@ -2739,7 +2739,7 @@ void CodeGenFunction::EmitObjCAutoreleasePoolStmt(
// Keep track of the current cleanup stack depth.
RunCleanupsScope Scope(*this);
- if (CGM.getLangOpts().ObjCRuntime.hasARC()) {
+ if (CGM.getLangOpts().ObjCRuntime.hasNativeARC()) {
llvm::Value *token = EmitObjCAutoreleasePoolPush();
EHStack.pushCleanup<CallObjCAutoreleasePoolObject>(NormalCleanup, token);
} else {
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index 6d129d02a5..f1c5f19ffa 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -653,11 +653,40 @@ class CGObjCGNUstep : public CGObjCGNU {
}
};
-/// The ObjFW runtime, which closely follows the GCC runtime's
-/// compiler ABI. Support here is due to Jonathan Schleifer, the
-/// ObjFW maintainer.
-class CGObjCObjFW : public CGObjCGCC {
- /// Emit class references unconditionally as direct symbol references.
+/// Support for the ObjFW runtime. Support here is due to
+/// Jonathan Schleifer <js@webkeks.org>, the ObjFW maintainer.
+class CGObjCObjFW: public CGObjCGNU {
+protected:
+ /// The GCC ABI message lookup function. Returns an IMP pointing to the
+ /// method implementation for this message.
+ LazyRuntimeFunction MsgLookupFn;
+ /// The GCC ABI superclass message lookup function. Takes a pointer to a
+ /// structure describing the receiver and the class, and a selector as
+ /// arguments. Returns the IMP for the corresponding method.
+ LazyRuntimeFunction MsgLookupSuperFn;
+
+ virtual llvm::Value *LookupIMP(CodeGenFunction &CGF,
+ llvm::Value *&Receiver,
+ llvm::Value *cmd,
+ llvm::MDNode *node) {
+ CGBuilderTy &Builder = CGF.Builder;
+ llvm::Value *args[] = {
+ EnforceType(Builder, Receiver, IdTy),
+ EnforceType(Builder, cmd, SelectorTy) };
+ llvm::CallSite imp = CGF.EmitCallOrInvoke(MsgLookupFn, args);
+ imp->setMetadata(msgSendMDKind, node);
+ return imp.getInstruction();
+ }
+
+ virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF,
+ llvm::Value *ObjCSuper,
+ llvm::Value *cmd) {
+ CGBuilderTy &Builder = CGF.Builder;
+ llvm::Value *lookupArgs[] = {EnforceType(Builder, ObjCSuper,
+ PtrToObjCSuperTy), cmd};
+ return Builder.CreateCall(MsgLookupSuperFn, lookupArgs);
+ }
+
virtual llvm::Value *GetClassNamed(CGBuilderTy &Builder,
const std::string &Name, bool isWeak) {
if (isWeak)
@@ -678,7 +707,13 @@ class CGObjCObjFW : public CGObjCGCC {
}
public:
- CGObjCObjFW(CodeGenModule &Mod): CGObjCGCC(Mod) {}
+ CGObjCObjFW(CodeGenModule &Mod): CGObjCGNU(Mod, 9, 3) {
+ // IMP objc_msg_lookup(id, SEL);
+ MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy, NULL);
+ // IMP objc_msg_lookup_super(struct objc_super*, SEL);
+ MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy,
+ PtrToObjCSuperTy, SelectorTy, NULL);
+ }
};
} // end anonymous namespace
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index 5cf97b702b..46259139cd 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -951,8 +951,11 @@ bool Darwin::SupportsObjCGC() const {
return !isTargetIPhoneOS();
}
-bool Darwin::SupportsObjCARC() const {
- return isTargetIPhoneOS() || !isMacosxVersionLT(10, 6);
+void Darwin::CheckObjCARC() const {
+ if (isTargetIPhoneOS() || !isMacosxVersionLT(10, 6))
+ return;
+ getDriver().Diag(diag::err_arc_unsupported_on_toolchain)
+ << 0; // "versions of Mac OS X prior to 10.6"
}
std::string
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index 95a11beea1..752cdfdcaa 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -354,7 +354,7 @@ public:
virtual bool SupportsObjCGC() const;
- virtual bool SupportsObjCARC() const;
+ virtual void CheckObjCARC() const;
virtual bool UseDwarfDebugFlags() const;
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index ed67f7b9a1..e9f1aab90b 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -2541,8 +2541,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// NOTE: This logic is duplicated in ToolChains.cpp.
bool ARC = isObjCAutoRefCount(Args);
if (ARC) {
- if (!getToolChain().SupportsObjCARC())
- D.Diag(diag::err_arc_unsupported);
+ getToolChain().CheckObjCARC();
CmdArgs.push_back("-fobjc-arc");
@@ -4481,7 +4480,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
ObjCRuntime runtime =
getDarwinToolChain().getDefaultObjCRuntime(/*nonfragile*/ true);
// We use arclite library for both ARC and subscripting support.
- if ((!runtime.hasARC() && isObjCAutoRefCount(Args)) ||
+ if ((!runtime.hasNativeARC() && isObjCAutoRefCount(Args)) ||
!runtime.hasSubscripting())
getDarwinToolChain().AddLinkARCArgs(Args, CmdArgs);
}
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index d39679caf1..d90bd92b9d 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -812,7 +812,7 @@ static void LangOptsToArgs(const LangOptions &Opts, ToArgsList &Res) {
Res.push_back("-fobjc-runtime=" + Opts.ObjCRuntime.getAsString());
if (Opts.ObjCAutoRefCount)
Res.push_back("-fobjc-arc");
- if (Opts.ObjCRuntimeHasWeak)
+ if (Opts.ObjCARCWeak)
Res.push_back("-fobjc-runtime-has-weak");
if (!Opts.ObjCInferRelatedResultType)
Res.push_back("-fno-objc-infer-related-result-type");
@@ -1941,14 +1941,16 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.setGC(LangOptions::HybridGC);
else if (Args.hasArg(OPT_fobjc_arc)) {
Opts.ObjCAutoRefCount = 1;
- if (!Opts.ObjCRuntime.isNonFragile())
- Diags.Report(diag::err_arc_nonfragile_abi);
+ if (!Opts.ObjCRuntime.allowsARC())
+ Diags.Report(diag::err_arc_unsupported_on_runtime);
+
+ // Only set ObjCARCWeak if ARC is enabled.
+ if (Args.hasArg(OPT_fobjc_runtime_has_weak))
+ Opts.ObjCARCWeak = 1;
+ else
+ Opts.ObjCARCWeak = Opts.ObjCRuntime.allowsWeak();
}
- Opts.ObjCRuntimeHasWeak = Opts.ObjCRuntime.hasWeak();
- if (Args.hasArg(OPT_fobjc_runtime_has_weak))
- Opts.ObjCRuntimeHasWeak = 1;
-
if (Args.hasArg(OPT_fno_objc_infer_related_result_type))
Opts.ObjCInferRelatedResultType = 0;
}
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 1440da6e37..edb0710534 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -247,7 +247,7 @@ static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts,
<< "};\n"
<< "\n";
- if (LangOpts.ObjCRuntimeHasWeak) {
+ if (LangOpts.ObjCARCWeak) {
Out << "template<typename _Tp>\n"
<< "struct __is_scalar<__attribute__((objc_ownership(weak))) _Tp> {\n"
<< " enum { __value = 0 };\n"
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index ebdb6446d1..96d6b2c729 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -641,8 +641,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
// Objective-C features
.Case("objc_arr", LangOpts.ObjCAutoRefCount) // FIXME: REMOVE?
.Case("objc_arc", LangOpts.ObjCAutoRefCount)
- .Case("objc_arc_weak", LangOpts.ObjCAutoRefCount &&
- LangOpts.ObjCRuntimeHasWeak)
+ .Case("objc_arc_weak", LangOpts.ObjCARCWeak)
.Case("objc_default_synthesize_properties", LangOpts.ObjC2)
.Case("objc_fixed_enum", LangOpts.ObjC2)
.Case("objc_instancetype", LangOpts.ObjC2)
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index eb03d253a5..6c140ac692 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -4649,8 +4649,7 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Results.AddResult(CodeCompletionResult("atomic"));
// Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
- if ((getLangOpts().ObjCAutoRefCount && getLangOpts().ObjCRuntimeHasWeak) ||
- getLangOpts().getGC() != LangOptions::NonGC)
+ if (getLangOpts().ObjCARCWeak || getLangOpts().getGC() != LangOptions::NonGC)
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Results.AddResult(CodeCompletionResult("weak"));
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index 8a8927d362..6aa59229fa 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -880,7 +880,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
Diag(property->getLocation(), diag::note_property_declare);
err = true;
}
- if (!err && !getLangOpts().ObjCRuntimeHasWeak) {
+ if (!err && !getLangOpts().ObjCARCWeak) {
Diag(PropertyDiagLoc, diag::err_arc_weak_no_runtime);
Diag(property->getLocation(), diag::note_property_declare);
}
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 54f8dbaf01..3e72c2d06f 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -3588,7 +3588,7 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
// Forbid __weak if the runtime doesn't support it.
if (lifetime == Qualifiers::OCL_Weak &&
- !S.getLangOpts().ObjCRuntimeHasWeak && !NonObjCPointer) {
+ !S.getLangOpts().ObjCARCWeak && !NonObjCPointer) {
// Actually, delay this until we know what we're parsing.
if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
diff --git a/test/Driver/arc.c b/test/Driver/arc.c
index 5a5720c04a..1072e6b7bb 100644
--- a/test/Driver/arc.c
+++ b/test/Driver/arc.c
@@ -8,10 +8,10 @@
// Just to test clang is working.
# foo
-// CHECK: error: -fobjc-arc is not supported with legacy abi
+// CHECK: error: -fobjc-arc is not supported on platforms using the legacy runtime
// CHECK-NOT: invalid preprocessing directive
-// NOTOBJC-NOT: error: -fobjc-arc is not supported with legacy abi
+// NOTOBJC-NOT: error: -fobjc-arc is not supported on platforms using the legacy runtime
// NOTOBJC: invalid preprocessing directive
-// UNSUPPORTED: error: -fobjc-arc is not supported on current deployment target
+// UNSUPPORTED: error: -fobjc-arc is not supported on versions of Mac OS prior to 10.6