mirror of https://github.com/microsoft/clang.git
Define weak and __weak to mean ARC-style weak references, even in MRC.
Previously, __weak was silently accepted and ignored in MRC mode. That makes this a potentially source-breaking change that we have to roll out cautiously. Accordingly, for the time being, actual support for __weak references in MRC is experimental, and the compiler will reject attempts to actually form such references. The intent is to eventually enable the feature by default in all non-GC modes. (It is, of course, incompatible with ObjC GC's interpretation of __weak.) If you like, you can enable this feature with -Xclang -fobjc-weak but like any -Xclang option, this option may be removed at any point, e.g. if/when it is eventually enabled by default. This patch also enables the use of the ARC __unsafe_unretained qualifier in MRC. Unlike __weak, this is being enabled immediately. Since variables are essentially __unsafe_unretained by default in MRC, the only practical uses are (1) communication and (2) changing the default behavior of by-value block capture. As an implementation matter, this means that the ObjC ownership qualifiers may appear in any ObjC language mode, and so this patch removes a number of checks for getLangOpts().ObjCAutoRefCount that were guarding the processing of these qualifiers. I don't expect this to be a significant drain on performance; it may even be faster to just check for these qualifiers directly on a type (since it's probably in a register anyway) than to do N dependent loads to grab the LangOptions. rdar://9674298 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@251041 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
93fdb3f356
commit
abdd82457f
|
@ -108,6 +108,10 @@ 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< // feel free to generalize this
|
||||
"-fobjc-arc is not supported on versions of OS X prior to 10.6">;
|
||||
def err_objc_weak_with_gc : Error<
|
||||
"-fobjc-weak is not supported in Objective-C garbage collection">;
|
||||
def err_objc_weak_unsupported : Error<
|
||||
"-fobjc-weak is not supported on the current deployment target">;
|
||||
def err_drv_mg_requires_m_or_mm : Error<
|
||||
"option '-MG' requires '-M' or '-MM'">;
|
||||
def err_drv_unknown_objc_runtime : Error<
|
||||
|
|
|
@ -907,8 +907,6 @@ def error_bad_property_context : Error<
|
|||
def error_missing_property_ivar_decl : Error<
|
||||
"synthesized property %0 must either be named the same as a compatible"
|
||||
" instance variable or must explicitly name an instance variable">;
|
||||
def error_synthesize_weak_non_arc_or_gc : Error<
|
||||
"@synthesize of 'weak' property is only allowed in ARC or GC mode">;
|
||||
def err_arc_perform_selector_retains : Error<
|
||||
"performSelector names a selector which retains the object">;
|
||||
def warn_arc_perform_selector_leaks : Warning<
|
||||
|
@ -4527,6 +4525,11 @@ let CategoryName = "ARC Weak References" in {
|
|||
|
||||
def err_arc_weak_no_runtime : Error<
|
||||
"the current deployment target does not support automated __weak references">;
|
||||
def err_arc_weak_disabled : Error<
|
||||
"automated __weak references are disabled in manual reference counting">;
|
||||
def warn_objc_weak_compat : Warning<
|
||||
"the meaning of __weak has changed in manual reference-counting">,
|
||||
InGroup<DiagGroup<"objc-weak-compat">>, DefaultIgnore;
|
||||
def err_arc_unsupported_weak_class : Error<
|
||||
"class is incompatible with __weak references">;
|
||||
def err_arc_weak_unavailable_assign : Error<
|
||||
|
|
|
@ -193,7 +193,8 @@ 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(ObjCARCWeak , 1, 0, "__weak support in the ARC runtime")
|
||||
LANGOPT(ObjCWeakRuntime , 1, 0, "__weak support in the ARC runtime")
|
||||
LANGOPT(ObjCWeak , 1, 0, "Objective-C __weak in ARC and MRC files")
|
||||
LANGOPT(ObjCSubscriptingLegacyRuntime , 1, 0, "Subscripting support in legacy ObjectiveC runtime")
|
||||
LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map")
|
||||
ENUM_LANGOPT(AddressSpaceMapMangling , AddrSpaceMapMangling, 2, ASMM_Target, "OpenCL address space map mangling mode")
|
||||
|
|
|
@ -511,6 +511,8 @@ def fobjc_runtime_has_weak : Flag<["-"], "fobjc-runtime-has-weak">,
|
|||
HelpText<"The target Objective-C runtime supports ARC weak operations">;
|
||||
def fobjc_dispatch_method_EQ : Joined<["-"], "fobjc-dispatch-method=">,
|
||||
HelpText<"Objective-C dispatch method to use">;
|
||||
def fobjc_weak : Flag<["-"], "fobjc-weak">, Group<f_Group>,
|
||||
HelpText<"Enable ARC-style __weak references">;
|
||||
def disable_objc_default_synthesize_properties : Flag<["-"], "disable-objc-default-synthesize-properties">,
|
||||
HelpText<"disable the default synthesis of Objective-C properties">;
|
||||
def fencode_extended_block_signature : Flag<["-"], "fencode-extended-block-signature">,
|
||||
|
|
|
@ -206,7 +206,8 @@ createInvocationForMigration(CompilerInvocation &origCI,
|
|||
WarnOpts.push_back("error=arc-unsafe-retained-assign");
|
||||
CInvok->getDiagnosticOpts().Warnings = std::move(WarnOpts);
|
||||
|
||||
CInvok->getLangOpts()->ObjCARCWeak = HasARCRuntime(origCI);
|
||||
CInvok->getLangOpts()->ObjCWeakRuntime = HasARCRuntime(origCI);
|
||||
CInvok->getLangOpts()->ObjCWeak = CInvok->getLangOpts()->ObjCWeakRuntime;
|
||||
|
||||
return CInvok.release();
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ bool MigrationPass::CFBridgingFunctionsDefined() {
|
|||
|
||||
bool trans::canApplyWeak(ASTContext &Ctx, QualType type,
|
||||
bool AllowOnUnknownClass) {
|
||||
if (!Ctx.getLangOpts().ObjCARCWeak)
|
||||
if (!Ctx.getLangOpts().ObjCWeakRuntime)
|
||||
return false;
|
||||
|
||||
QualType T = type;
|
||||
|
|
|
@ -4946,8 +4946,6 @@ bool ASTContext::BlockRequiresCopying(QualType Ty,
|
|||
|
||||
// If we have lifetime, that dominates.
|
||||
if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) {
|
||||
assert(getLangOpts().ObjCAutoRefCount);
|
||||
|
||||
switch (lifetime) {
|
||||
case Qualifiers::OCL_None: llvm_unreachable("impossible");
|
||||
|
||||
|
@ -4981,14 +4979,14 @@ bool ASTContext::getByrefLifetime(QualType Ty,
|
|||
if (Ty->isRecordType()) {
|
||||
HasByrefExtendedLayout = true;
|
||||
LifeTime = Qualifiers::OCL_None;
|
||||
}
|
||||
else if (getLangOpts().ObjCAutoRefCount)
|
||||
LifeTime = Ty.getObjCLifetime();
|
||||
// MRR.
|
||||
else if (Ty->isObjCObjectPointerType() || Ty->isBlockPointerType())
|
||||
} else if ((LifeTime = Ty.getObjCLifetime())) {
|
||||
// Honor the ARC qualifiers.
|
||||
} else if (Ty->isObjCObjectPointerType() || Ty->isBlockPointerType()) {
|
||||
// The MRR rule.
|
||||
LifeTime = Qualifiers::OCL_ExplicitNone;
|
||||
else
|
||||
} else {
|
||||
LifeTime = Qualifiers::OCL_None;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -118,19 +118,11 @@ static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
|
|||
if (Opts.Sanitize.has(SanitizerKind::Address))
|
||||
Builder.defineMacro("_FORTIFY_SOURCE", "0");
|
||||
|
||||
if (!Opts.ObjCAutoRefCount) {
|
||||
// Darwin defines __weak, __strong, and __unsafe_unretained even in C mode.
|
||||
if (!Opts.ObjC1) {
|
||||
// __weak is always defined, for use in blocks and with objc pointers.
|
||||
Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))");
|
||||
|
||||
// Darwin defines __strong even in C mode (just to nothing).
|
||||
if (Opts.getGC() != LangOptions::NonGC)
|
||||
Builder.defineMacro("__strong", "__attribute__((objc_gc(strong)))");
|
||||
else
|
||||
Builder.defineMacro("__strong", "");
|
||||
|
||||
// __unsafe_unretained is defined to nothing in non-ARC mode. We even
|
||||
// allow this in C, since one might have block pointers in structs that
|
||||
// are used in pure C code and in Objective-C ARC.
|
||||
Builder.defineMacro("__strong", "");
|
||||
Builder.defineMacro("__unsafe_unretained", "");
|
||||
}
|
||||
|
||||
|
|
|
@ -1393,31 +1393,31 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
|
|||
flags = BLOCK_FIELD_IS_BLOCK;
|
||||
|
||||
// Special rules for ARC captures:
|
||||
if (getLangOpts().ObjCAutoRefCount) {
|
||||
Qualifiers qs = type.getQualifiers();
|
||||
Qualifiers qs = type.getQualifiers();
|
||||
|
||||
// We need to register __weak direct captures with the runtime.
|
||||
if (qs.getObjCLifetime() == Qualifiers::OCL_Weak) {
|
||||
useARCWeakCopy = true;
|
||||
// We need to register __weak direct captures with the runtime.
|
||||
if (qs.getObjCLifetime() == Qualifiers::OCL_Weak) {
|
||||
useARCWeakCopy = true;
|
||||
|
||||
// We need to retain the copied value for __strong direct captures.
|
||||
} else if (qs.getObjCLifetime() == Qualifiers::OCL_Strong) {
|
||||
// If it's a block pointer, we have to copy the block and
|
||||
// assign that to the destination pointer, so we might as
|
||||
// well use _Block_object_assign. Otherwise we can avoid that.
|
||||
if (!isBlockPointer)
|
||||
useARCStrongCopy = true;
|
||||
|
||||
// Otherwise the memcpy is fine.
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
// We need to retain the copied value for __strong direct captures.
|
||||
} else if (qs.getObjCLifetime() == Qualifiers::OCL_Strong) {
|
||||
// If it's a block pointer, we have to copy the block and
|
||||
// assign that to the destination pointer, so we might as
|
||||
// well use _Block_object_assign. Otherwise we can avoid that.
|
||||
if (!isBlockPointer)
|
||||
useARCStrongCopy = true;
|
||||
|
||||
// Non-ARC captures of retainable pointers are strong and
|
||||
// therefore require a call to _Block_object_assign.
|
||||
} else {
|
||||
} else if (!qs.getObjCLifetime() && !getLangOpts().ObjCAutoRefCount) {
|
||||
// fall through
|
||||
|
||||
// Otherwise the memcpy is fine.
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
// For all other types, the memcpy is fine.
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
@ -1564,21 +1564,24 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
|
|||
flags = BLOCK_FIELD_IS_BLOCK;
|
||||
|
||||
// Special rules for ARC captures.
|
||||
if (getLangOpts().ObjCAutoRefCount) {
|
||||
Qualifiers qs = type.getQualifiers();
|
||||
Qualifiers qs = type.getQualifiers();
|
||||
|
||||
// Don't generate special dispose logic for a captured object
|
||||
// unless it's __strong or __weak.
|
||||
if (!qs.hasStrongOrWeakObjCLifetime())
|
||||
continue;
|
||||
// Use objc_storeStrong for __strong direct captures; the
|
||||
// dynamic tools really like it when we do this.
|
||||
if (qs.getObjCLifetime() == Qualifiers::OCL_Strong) {
|
||||
useARCStrongDestroy = true;
|
||||
|
||||
// Support __weak direct captures.
|
||||
if (qs.getObjCLifetime() == Qualifiers::OCL_Weak)
|
||||
useARCWeakDestroy = true;
|
||||
// Support __weak direct captures.
|
||||
} else if (qs.getObjCLifetime() == Qualifiers::OCL_Weak) {
|
||||
useARCWeakDestroy = true;
|
||||
|
||||
// Tools really want us to use objc_storeStrong here.
|
||||
else
|
||||
useARCStrongDestroy = true;
|
||||
// Non-ARC captures are strong, and we need to use _Block_object_dispose.
|
||||
} else if (!qs.hasObjCLifetime() && !getLangOpts().ObjCAutoRefCount) {
|
||||
// fall through
|
||||
|
||||
// Otherwise, we have nothing to do.
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
|
@ -1958,8 +1961,6 @@ CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
|
|||
|
||||
// If we have lifetime, that dominates.
|
||||
if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) {
|
||||
assert(getLangOpts().ObjCAutoRefCount);
|
||||
|
||||
switch (lifetime) {
|
||||
case Qualifiers::OCL_None: llvm_unreachable("impossible");
|
||||
|
||||
|
|
|
@ -202,11 +202,8 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M,
|
|||
// need to perform retain/release operations on the temporary.
|
||||
//
|
||||
// FIXME: This should be looking at E, not M.
|
||||
if (CGF.getLangOpts().ObjCAutoRefCount &&
|
||||
M->getType()->isObjCLifetimeType()) {
|
||||
QualType ObjCARCReferenceLifetimeType = M->getType();
|
||||
switch (Qualifiers::ObjCLifetime Lifetime =
|
||||
ObjCARCReferenceLifetimeType.getObjCLifetime()) {
|
||||
if (auto Lifetime = M->getType().getObjCLifetime()) {
|
||||
switch (Lifetime) {
|
||||
case Qualifiers::OCL_None:
|
||||
case Qualifiers::OCL_ExplicitNone:
|
||||
// Carry on to normal cleanup handling.
|
||||
|
@ -247,11 +244,11 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M,
|
|||
}
|
||||
if (Duration == SD_FullExpression)
|
||||
CGF.pushDestroy(CleanupKind, ReferenceTemporary,
|
||||
ObjCARCReferenceLifetimeType, *Destroy,
|
||||
M->getType(), *Destroy,
|
||||
CleanupKind & EHCleanup);
|
||||
else
|
||||
CGF.pushLifetimeExtendedDestroy(CleanupKind, ReferenceTemporary,
|
||||
ObjCARCReferenceLifetimeType,
|
||||
M->getType(),
|
||||
*Destroy, CleanupKind & EHCleanup);
|
||||
return;
|
||||
|
||||
|
@ -355,10 +352,9 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
|
|||
|
||||
// FIXME: ideally this would use EmitAnyExprToMem, however, we cannot do so
|
||||
// as that will cause the lifetime adjustment to be lost for ARC
|
||||
if (getLangOpts().ObjCAutoRefCount &&
|
||||
M->getType()->isObjCLifetimeType() &&
|
||||
M->getType().getObjCLifetime() != Qualifiers::OCL_None &&
|
||||
M->getType().getObjCLifetime() != Qualifiers::OCL_ExplicitNone) {
|
||||
auto ownership = M->getType().getObjCLifetime();
|
||||
if (ownership != Qualifiers::OCL_None &&
|
||||
ownership != Qualifiers::OCL_ExplicitNone) {
|
||||
Address Object = createReferenceTemporary(*this, M, E);
|
||||
if (auto *Var = dyn_cast<llvm::GlobalVariable>(Object.getPointer())) {
|
||||
Object = Address(llvm::ConstantExpr::getBitCast(Var,
|
||||
|
@ -1424,6 +1420,12 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
|
|||
AddrWeakObj));
|
||||
}
|
||||
if (LV.getQuals().getObjCLifetime() == Qualifiers::OCL_Weak) {
|
||||
// In MRC mode, we do a load+autorelease.
|
||||
if (!getLangOpts().ObjCAutoRefCount) {
|
||||
return RValue::get(EmitARCLoadWeak(LV.getAddress()));
|
||||
}
|
||||
|
||||
// In ARC mode, we load retained and then consume the value.
|
||||
llvm::Value *Object = EmitARCLoadWeakRetained(LV.getAddress());
|
||||
Object = EmitObjCConsumeObject(LV.getType(), Object);
|
||||
return RValue::get(Object);
|
||||
|
@ -3511,10 +3513,7 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
|
|||
if (const auto *PseudoDtor =
|
||||
dyn_cast<CXXPseudoDestructorExpr>(E->getCallee()->IgnoreParens())) {
|
||||
QualType DestroyedType = PseudoDtor->getDestroyedType();
|
||||
if (getLangOpts().ObjCAutoRefCount &&
|
||||
DestroyedType->isObjCLifetimeType() &&
|
||||
(DestroyedType.getObjCLifetime() == Qualifiers::OCL_Strong ||
|
||||
DestroyedType.getObjCLifetime() == Qualifiers::OCL_Weak)) {
|
||||
if (DestroyedType.hasStrongOrWeakObjCLifetime()) {
|
||||
// Automatic Reference Counting:
|
||||
// If the pseudo-expression names a retainable object with weak or
|
||||
// strong lifetime, the object shall be released.
|
||||
|
@ -3534,7 +3533,7 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
|
|||
BaseQuals = BaseTy.getQualifiers();
|
||||
}
|
||||
|
||||
switch (PseudoDtor->getDestroyedType().getObjCLifetime()) {
|
||||
switch (DestroyedType.getObjCLifetime()) {
|
||||
case Qualifiers::OCL_None:
|
||||
case Qualifiers::OCL_ExplicitNone:
|
||||
case Qualifiers::OCL_Autoreleasing:
|
||||
|
|
|
@ -1526,9 +1526,8 @@ static void EmitObjectDelete(CodeGenFunction &CGF,
|
|||
/*ForVirtualBase=*/false,
|
||||
/*Delegating=*/false,
|
||||
Ptr);
|
||||
else if (CGF.getLangOpts().ObjCAutoRefCount &&
|
||||
ElementType->isObjCLifetimeType()) {
|
||||
switch (ElementType.getObjCLifetime()) {
|
||||
else if (auto Lifetime = ElementType.getObjCLifetime()) {
|
||||
switch (Lifetime) {
|
||||
case Qualifiers::OCL_None:
|
||||
case Qualifiers::OCL_ExplicitNone:
|
||||
case Qualifiers::OCL_Autoreleasing:
|
||||
|
|
|
@ -323,6 +323,21 @@ shouldExtendReceiverForInnerPointerMessage(const ObjCMessageExpr *message) {
|
|||
llvm_unreachable("invalid receiver kind");
|
||||
}
|
||||
|
||||
/// Given an expression of ObjC pointer type, check whether it was
|
||||
/// immediately loaded from an ARC __weak l-value.
|
||||
static const Expr *findWeakLValue(const Expr *E) {
|
||||
assert(E->getType()->isObjCRetainableType());
|
||||
E = E->IgnoreParens();
|
||||
if (auto CE = dyn_cast<CastExpr>(E)) {
|
||||
if (CE->getCastKind() == CK_LValueToRValue) {
|
||||
if (CE->getSubExpr()->getType().getObjCLifetime() == Qualifiers::OCL_Weak)
|
||||
return CE->getSubExpr();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
|
||||
ReturnValueSlot Return) {
|
||||
// Only the lookup mechanism and first two arguments of the method
|
||||
|
@ -333,6 +348,17 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
|
|||
|
||||
const ObjCMethodDecl *method = E->getMethodDecl();
|
||||
|
||||
// If the method is -retain, and the receiver's being loaded from
|
||||
// a __weak variable, peephole the entire operation to objc_loadWeakRetained.
|
||||
if (method && E->getReceiverKind() == ObjCMessageExpr::Instance &&
|
||||
method->getMethodFamily() == OMF_retain) {
|
||||
if (auto lvalueExpr = findWeakLValue(E->getInstanceReceiver())) {
|
||||
LValue lvalue = EmitLValue(lvalueExpr);
|
||||
llvm::Value *result = EmitARCLoadWeakRetained(lvalue.getAddress());
|
||||
return AdjustObjCObjectType(*this, E->getType(), RValue::get(result));
|
||||
}
|
||||
}
|
||||
|
||||
// We don't retain the receiver in delegate init calls, and this is
|
||||
// safe because the receiver value is always loaded from 'self',
|
||||
// which we zero out. We don't want to Block_copy block receivers,
|
||||
|
@ -976,7 +1002,11 @@ CodeGenFunction::generateObjCGetterBody(const ObjCImplementationDecl *classImpl,
|
|||
} else {
|
||||
// We want to load and autoreleaseReturnValue ARC __weak ivars.
|
||||
if (LV.getQuals().getObjCLifetime() == Qualifiers::OCL_Weak) {
|
||||
value = emitARCRetainLoadOfScalar(*this, LV, ivarType);
|
||||
if (getLangOpts().ObjCAutoRefCount) {
|
||||
value = emitARCRetainLoadOfScalar(*this, LV, ivarType);
|
||||
} else {
|
||||
value = EmitARCLoadWeak(LV.getAddress());
|
||||
}
|
||||
|
||||
// Otherwise we want to do a simple load, suppressing the
|
||||
// final autorelease.
|
||||
|
|
|
@ -913,10 +913,28 @@ protected:
|
|||
/// BuildIvarLayout - Builds ivar layout bitmap for the class
|
||||
/// implementation for the __strong or __weak case.
|
||||
///
|
||||
/// \param hasMRCWeakIvars - Whether we are compiling in MRC and there
|
||||
/// are any weak ivars defined directly in the class. Meaningless unless
|
||||
/// building a weak layout. Does not guarantee that the layout will
|
||||
/// actually have any entries, because the ivar might be under-aligned.
|
||||
llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
|
||||
CharUnits beginOffset,
|
||||
CharUnits endOffset,
|
||||
bool ForStrongLayout);
|
||||
bool forStrongLayout,
|
||||
bool hasMRCWeakIvars);
|
||||
|
||||
llvm::Constant *BuildStrongIvarLayout(const ObjCImplementationDecl *OI,
|
||||
CharUnits beginOffset,
|
||||
CharUnits endOffset) {
|
||||
return BuildIvarLayout(OI, beginOffset, endOffset, true, false);
|
||||
}
|
||||
|
||||
llvm::Constant *BuildWeakIvarLayout(const ObjCImplementationDecl *OI,
|
||||
CharUnits beginOffset,
|
||||
CharUnits endOffset,
|
||||
bool hasMRCWeakIvars) {
|
||||
return BuildIvarLayout(OI, beginOffset, endOffset, false, hasMRCWeakIvars);
|
||||
}
|
||||
|
||||
Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout);
|
||||
|
||||
|
@ -1060,7 +1078,8 @@ private:
|
|||
/// to store the weak ivar layout and properties. The return value
|
||||
/// has type ClassExtensionPtrTy.
|
||||
llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID,
|
||||
CharUnits InstanceSize);
|
||||
CharUnits instanceSize,
|
||||
bool hasMRCWeakIvars);
|
||||
|
||||
/// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
|
||||
/// for the given class.
|
||||
|
@ -2049,8 +2068,7 @@ llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
|
|||
const CGBlockInfo &blockInfo) {
|
||||
|
||||
llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
|
||||
if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
|
||||
!CGM.getLangOpts().ObjCAutoRefCount)
|
||||
if (CGM.getLangOpts().getGC() == LangOptions::NonGC)
|
||||
return nullPtr;
|
||||
|
||||
IvarLayoutBuilder builder(CGM, CharUnits::Zero(), blockInfo.BlockSize,
|
||||
|
@ -2129,10 +2147,15 @@ void IvarLayoutBuilder::visitBlock(const CGBlockInfo &blockInfo) {
|
|||
/// the type of the variable captured in the block.
|
||||
Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT,
|
||||
bool ByrefLayout) {
|
||||
// If it has an ownership qualifier, we're done.
|
||||
if (auto lifetime = FQT.getObjCLifetime())
|
||||
return lifetime;
|
||||
|
||||
// If it doesn't, and this is ARC, it has no ownership.
|
||||
if (CGM.getLangOpts().ObjCAutoRefCount)
|
||||
return FQT.getObjCLifetime();
|
||||
return Qualifiers::OCL_None;
|
||||
|
||||
// MRR.
|
||||
// In MRC, retainable pointers are owned by non-__block variables.
|
||||
if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
|
||||
return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong;
|
||||
|
||||
|
@ -3060,11 +3083,24 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
|
|||
}
|
||||
|
||||
enum FragileClassFlags {
|
||||
/// Apparently: is not a meta-class.
|
||||
FragileABI_Class_Factory = 0x00001,
|
||||
|
||||
/// Is a meta-class.
|
||||
FragileABI_Class_Meta = 0x00002,
|
||||
|
||||
/// Has a non-trivial constructor or destructor.
|
||||
FragileABI_Class_HasCXXStructors = 0x02000,
|
||||
|
||||
/// Has hidden visibility.
|
||||
FragileABI_Class_Hidden = 0x20000,
|
||||
FragileABI_Class_CompiledByARC = 0x04000000
|
||||
|
||||
/// Class implementation was compiled under ARC.
|
||||
FragileABI_Class_CompiledByARC = 0x04000000,
|
||||
|
||||
/// Class implementation was compiled under MRC and has MRC weak ivars.
|
||||
/// Exclusive with CompiledByARC.
|
||||
FragileABI_Class_HasMRCWeakIvars = 0x08000000,
|
||||
};
|
||||
|
||||
enum NonFragileClassFlags {
|
||||
|
@ -3074,7 +3110,7 @@ enum NonFragileClassFlags {
|
|||
/// Is a root class.
|
||||
NonFragileABI_Class_Root = 0x00002,
|
||||
|
||||
/// Has a C++ constructor and destructor.
|
||||
/// Has a non-trivial constructor or destructor.
|
||||
NonFragileABI_Class_HasCXXStructors = 0x00004,
|
||||
|
||||
/// Has hidden visibility.
|
||||
|
@ -3090,9 +3126,46 @@ enum NonFragileClassFlags {
|
|||
NonFragileABI_Class_CompiledByARC = 0x00080,
|
||||
|
||||
/// Class has non-trivial destructors, but zero-initialization is okay.
|
||||
NonFragileABI_Class_HasCXXDestructorOnly = 0x00100
|
||||
NonFragileABI_Class_HasCXXDestructorOnly = 0x00100,
|
||||
|
||||
/// Class implementation was compiled under MRC and has MRC weak ivars.
|
||||
/// Exclusive with CompiledByARC.
|
||||
NonFragileABI_Class_HasMRCWeakIvars = 0x00200,
|
||||
};
|
||||
|
||||
static bool hasWeakMember(QualType type) {
|
||||
if (type.getObjCLifetime() == Qualifiers::OCL_Weak) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (auto recType = type->getAs<RecordType>()) {
|
||||
for (auto field : recType->getDecl()->fields()) {
|
||||
if (hasWeakMember(field->getType()))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// For compatibility, we only want to set the "HasMRCWeakIvars" flag
|
||||
/// (and actually fill in a layout string) if we really do have any
|
||||
/// __weak ivars.
|
||||
static bool hasMRCWeakIvars(CodeGenModule &CGM,
|
||||
const ObjCImplementationDecl *ID) {
|
||||
if (!CGM.getLangOpts().ObjCWeak) return false;
|
||||
assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
|
||||
|
||||
for (const ObjCIvarDecl *ivar =
|
||||
ID->getClassInterface()->all_declared_ivar_begin();
|
||||
ivar; ivar = ivar->getNextIvar()) {
|
||||
if (hasWeakMember(ivar->getType()))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
struct _objc_class {
|
||||
Class isa;
|
||||
|
@ -3127,8 +3200,12 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
|
|||
if (ID->hasNonZeroConstructors() || ID->hasDestructors())
|
||||
Flags |= FragileABI_Class_HasCXXStructors;
|
||||
|
||||
bool hasMRCWeak = false;
|
||||
|
||||
if (CGM.getLangOpts().ObjCAutoRefCount)
|
||||
Flags |= FragileABI_Class_CompiledByARC;
|
||||
else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
|
||||
Flags |= FragileABI_Class_HasMRCWeakIvars;
|
||||
|
||||
CharUnits Size =
|
||||
CGM.getContext().getASTObjCImplementationLayout(ID).getSize();
|
||||
|
@ -3183,8 +3260,8 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
|
|||
// cache is always NULL.
|
||||
Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
|
||||
Values[ 9] = Protocols;
|
||||
Values[10] = BuildIvarLayout(ID, CharUnits::Zero(), Size, true);
|
||||
Values[11] = EmitClassExtension(ID, Size);
|
||||
Values[10] = BuildStrongIvarLayout(ID, CharUnits::Zero(), Size);
|
||||
Values[11] = EmitClassExtension(ID, Size, hasMRCWeak);
|
||||
llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
|
||||
Values);
|
||||
std::string Name("OBJC_CLASS_");
|
||||
|
@ -3323,13 +3400,14 @@ llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
|
|||
*/
|
||||
llvm::Constant *
|
||||
CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID,
|
||||
CharUnits InstanceSize) {
|
||||
CharUnits InstanceSize, bool hasMRCWeakIvars) {
|
||||
uint64_t Size =
|
||||
CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
|
||||
|
||||
llvm::Constant *Values[3];
|
||||
Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
|
||||
Values[1] = BuildIvarLayout(ID, CharUnits::Zero(), InstanceSize, false);
|
||||
Values[1] = BuildWeakIvarLayout(ID, CharUnits::Zero(), InstanceSize,
|
||||
hasMRCWeakIvars);
|
||||
Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
|
||||
ID, ID->getClassInterface(), ObjCTypes);
|
||||
|
||||
|
@ -4827,10 +4905,13 @@ llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
|
|||
llvm::Constant *
|
||||
CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
|
||||
CharUnits beginOffset, CharUnits endOffset,
|
||||
bool ForStrongLayout) {
|
||||
bool ForStrongLayout, bool HasMRCWeakIvars) {
|
||||
// If this is MRC, and we're either building a strong layout or there
|
||||
// are no weak ivars, bail out early.
|
||||
llvm::Type *PtrTy = CGM.Int8PtrTy;
|
||||
if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
|
||||
!CGM.getLangOpts().ObjCAutoRefCount)
|
||||
!CGM.getLangOpts().ObjCAutoRefCount &&
|
||||
(ForStrongLayout || !HasMRCWeakIvars))
|
||||
return llvm::Constant::getNullValue(PtrTy);
|
||||
|
||||
const ObjCInterfaceDecl *OI = OMD->getClassInterface();
|
||||
|
@ -4844,8 +4925,10 @@ CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
|
|||
// runtimes, that means starting at InstanceStart. In fragile runtimes,
|
||||
// there's no InstanceStart, so it means starting at the end of the
|
||||
// superclass, rounded up to word alignment.
|
||||
//
|
||||
// MRC weak layout strings follow the ARC style.
|
||||
CharUnits baseOffset;
|
||||
if (CGM.getLangOpts().ObjCAutoRefCount) {
|
||||
if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
|
||||
for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin();
|
||||
IVD; IVD = IVD->getNextIvar())
|
||||
ivars.push_back(IVD);
|
||||
|
@ -5662,8 +5745,11 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
|
|||
CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
|
||||
CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);
|
||||
|
||||
bool hasMRCWeak = false;
|
||||
if (CGM.getLangOpts().ObjCAutoRefCount)
|
||||
flags |= NonFragileABI_Class_CompiledByARC;
|
||||
else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
|
||||
flags |= NonFragileABI_Class_HasMRCWeakIvars;
|
||||
|
||||
Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
|
||||
Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
|
||||
|
@ -5671,7 +5757,7 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
|
|||
// FIXME. For 64bit targets add 0 here.
|
||||
Values[ 3] = (flags & NonFragileABI_Class_Meta)
|
||||
? GetIvarLayoutName(nullptr, ObjCTypes)
|
||||
: BuildIvarLayout(ID, beginInstance, endInstance, true);
|
||||
: BuildStrongIvarLayout(ID, beginInstance, endInstance);
|
||||
Values[ 4] = GetClassName(ID->getObjCRuntimeNameAsString());
|
||||
// const struct _method_list_t * const baseMethods;
|
||||
std::vector<llvm::Constant*> Methods;
|
||||
|
@ -5718,7 +5804,8 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
|
|||
Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
|
||||
} else {
|
||||
Values[ 7] = EmitIvarList(ID);
|
||||
Values[ 8] = BuildIvarLayout(ID, beginInstance, endInstance, false);
|
||||
Values[ 8] = BuildWeakIvarLayout(ID, beginInstance, endInstance,
|
||||
hasMRCWeak);
|
||||
Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getObjCRuntimeNameAsString(),
|
||||
ID, ID->getClassInterface(), ObjCTypes);
|
||||
}
|
||||
|
|
|
@ -4765,6 +4765,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
options::OPT_fno_objc_arc_exceptions,
|
||||
/*default*/ types::isCXX(InputType)))
|
||||
CmdArgs.push_back("-fobjc-arc-exceptions");
|
||||
|
||||
}
|
||||
|
||||
// -fobjc-infer-related-result-type is the default, except in the Objective-C
|
||||
|
|
|
@ -1421,12 +1421,28 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
|
|||
Opts.ObjCAutoRefCount = 1;
|
||||
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();
|
||||
// ObjCWeakRuntime tracks whether the runtime supports __weak, not
|
||||
// whether the feature is actually enabled. This is predominantly
|
||||
// determined by -fobjc-runtime, but we allow it to be overridden
|
||||
// from the command line for testing purposes.
|
||||
if (Args.hasArg(OPT_fobjc_runtime_has_weak))
|
||||
Opts.ObjCWeakRuntime = 1;
|
||||
else
|
||||
Opts.ObjCWeakRuntime = Opts.ObjCRuntime.allowsWeak();
|
||||
|
||||
// ObjCWeak determines whether __weak is actually enabled.
|
||||
if (Opts.ObjCAutoRefCount) {
|
||||
Opts.ObjCWeak = Opts.ObjCWeakRuntime;
|
||||
} else if (Args.hasArg(OPT_fobjc_weak)) {
|
||||
if (Opts.getGC() != LangOptions::NonGC) {
|
||||
Diags.Report(diag::err_objc_weak_with_gc);
|
||||
} else if (Opts.ObjCWeakRuntime) {
|
||||
Opts.ObjCWeak = true;
|
||||
} else {
|
||||
Diags.Report(diag::err_objc_weak_unsupported);
|
||||
}
|
||||
}
|
||||
|
||||
if (Args.hasArg(OPT_fno_objc_infer_related_result_type))
|
||||
|
|
|
@ -323,15 +323,17 @@ static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts,
|
|||
|
||||
Out << "template<typename _Tp> struct __is_scalar;\n"
|
||||
<< "\n";
|
||||
|
||||
if (LangOpts.ObjCAutoRefCount) {
|
||||
Out << "template<typename _Tp>\n"
|
||||
<< "struct __is_scalar<__attribute__((objc_ownership(strong))) _Tp> {\n"
|
||||
<< " enum { __value = 0 };\n"
|
||||
<< " typedef __false_type __type;\n"
|
||||
<< "};\n"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
Out << "template<typename _Tp>\n"
|
||||
<< "struct __is_scalar<__attribute__((objc_ownership(strong))) _Tp> {\n"
|
||||
<< " enum { __value = 0 };\n"
|
||||
<< " typedef __false_type __type;\n"
|
||||
<< "};\n"
|
||||
<< "\n";
|
||||
|
||||
if (LangOpts.ObjCARCWeak) {
|
||||
if (LangOpts.ObjCWeak) {
|
||||
Out << "template<typename _Tp>\n"
|
||||
<< "struct __is_scalar<__attribute__((objc_ownership(weak))) _Tp> {\n"
|
||||
<< " enum { __value = 0 };\n"
|
||||
|
@ -340,13 +342,15 @@ static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts,
|
|||
<< "\n";
|
||||
}
|
||||
|
||||
Out << "template<typename _Tp>\n"
|
||||
<< "struct __is_scalar<__attribute__((objc_ownership(autoreleasing)))"
|
||||
<< " _Tp> {\n"
|
||||
<< " enum { __value = 0 };\n"
|
||||
<< " typedef __false_type __type;\n"
|
||||
<< "};\n"
|
||||
<< "\n";
|
||||
if (LangOpts.ObjCAutoRefCount) {
|
||||
Out << "template<typename _Tp>\n"
|
||||
<< "struct __is_scalar<__attribute__((objc_ownership(autoreleasing)))"
|
||||
<< " _Tp> {\n"
|
||||
<< " enum { __value = 0 };\n"
|
||||
<< " typedef __false_type __type;\n"
|
||||
<< "};\n"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
Out << "}\n";
|
||||
}
|
||||
|
@ -851,9 +855,6 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
|
|||
else if (LangOpts.getStackProtector() == LangOptions::SSPReq)
|
||||
Builder.defineMacro("__SSP_ALL__", "3");
|
||||
|
||||
if (FEOpts.ProgramAction == frontend::RewriteObjC)
|
||||
Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))");
|
||||
|
||||
// Define a macro that exists only when using the static analyzer.
|
||||
if (FEOpts.ProgramAction == frontend::RunAnalysis)
|
||||
Builder.defineMacro("__clang_analyzer__");
|
||||
|
@ -861,7 +862,11 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
|
|||
if (LangOpts.FastRelaxedMath)
|
||||
Builder.defineMacro("__FAST_RELAXED_MATH__");
|
||||
|
||||
if (LangOpts.ObjCAutoRefCount) {
|
||||
if (FEOpts.ProgramAction == frontend::RewriteObjC ||
|
||||
LangOpts.getGC() != LangOptions::NonGC) {
|
||||
Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))");
|
||||
Builder.defineMacro("__strong", "__attribute__((objc_gc(strong)))");
|
||||
} else if (LangOpts.ObjC1) {
|
||||
Builder.defineMacro("__weak", "__attribute__((objc_ownership(weak)))");
|
||||
Builder.defineMacro("__strong", "__attribute__((objc_ownership(strong)))");
|
||||
Builder.defineMacro("__autoreleasing",
|
||||
|
@ -928,10 +933,11 @@ void clang::InitializePreprocessor(
|
|||
|
||||
// Install definitions to make Objective-C++ ARC work well with various
|
||||
// C++ Standard Library implementations.
|
||||
if (LangOpts.ObjC1 && LangOpts.CPlusPlus && LangOpts.ObjCAutoRefCount) {
|
||||
if (LangOpts.ObjC1 && LangOpts.CPlusPlus &&
|
||||
(LangOpts.ObjCAutoRefCount || LangOpts.ObjCWeak)) {
|
||||
switch (InitOpts.ObjCXXARCStandardLibrary) {
|
||||
case ARCXX_nolib:
|
||||
case ARCXX_libcxx:
|
||||
case ARCXX_libcxx:
|
||||
break;
|
||||
|
||||
case ARCXX_libstdcxx:
|
||||
|
|
|
@ -1089,7 +1089,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.ObjCARCWeak)
|
||||
.Case("objc_arc_weak", LangOpts.ObjCWeak)
|
||||
.Case("objc_default_synthesize_properties", LangOpts.ObjC2)
|
||||
.Case("objc_fixed_enum", LangOpts.ObjC2)
|
||||
.Case("objc_instancetype", LangOpts.ObjC2)
|
||||
|
|
|
@ -2050,7 +2050,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P,
|
|||
DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull);
|
||||
}
|
||||
|
||||
if (S.getLangOpts().ObjCARCWeak &&
|
||||
if (S.getLangOpts().ObjCWeak &&
|
||||
!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, D->getLocStart()))
|
||||
diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap());
|
||||
|
||||
|
|
|
@ -489,9 +489,9 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
|
|||
QualType *TheOffendingDestType = nullptr,
|
||||
Qualifiers *CastAwayQualifiers = nullptr) {
|
||||
// If the only checking we care about is for Objective-C lifetime qualifiers,
|
||||
// and we're not in ARC mode, there's nothing to check.
|
||||
// and we're not in ObjC mode, there's nothing to check.
|
||||
if (!CheckCVR && CheckObjCLifetime &&
|
||||
!Self.Context.getLangOpts().ObjCAutoRefCount)
|
||||
!Self.Context.getLangOpts().ObjC1)
|
||||
return false;
|
||||
|
||||
// Casting away constness is defined in C++ 5.2.11p8 with reference to
|
||||
|
|
|
@ -4912,7 +4912,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().ObjCARCWeak || getLangOpts().getGC() != LangOptions::NonGC)
|
||||
if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
|
||||
if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
|
||||
Results.AddResult(CodeCompletionResult("weak"));
|
||||
|
||||
|
|
|
@ -9815,9 +9815,9 @@ Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc,
|
|||
void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
|
||||
if (var->isInvalidDecl()) return;
|
||||
|
||||
// In ARC, don't allow jumps past the implicit initialization of a
|
||||
// In Objective-C, don't allow jumps past the implicit initialization of a
|
||||
// local retaining variable.
|
||||
if (getLangOpts().ObjCAutoRefCount &&
|
||||
if (getLangOpts().ObjC1 &&
|
||||
var->hasLocalStorage()) {
|
||||
switch (var->getType().getObjCLifetime()) {
|
||||
case Qualifiers::OCL_None:
|
||||
|
|
|
@ -1702,7 +1702,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
|
|||
|
||||
MarkDeclRefReferenced(E);
|
||||
|
||||
if (getLangOpts().ObjCARCWeak && isa<VarDecl>(D) &&
|
||||
if (getLangOpts().ObjCWeak && isa<VarDecl>(D) &&
|
||||
Ty.getObjCLifetime() == Qualifiers::OCL_Weak &&
|
||||
!Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, E->getLocStart()))
|
||||
recordUseOfEvaluatedWeak(E);
|
||||
|
|
|
@ -663,8 +663,10 @@ static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc,
|
|||
// We're fine if they match.
|
||||
if (propertyLifetime == ivarLifetime) return;
|
||||
|
||||
// These aren't valid lifetimes for object ivars; don't diagnose twice.
|
||||
if (ivarLifetime == Qualifiers::OCL_None ||
|
||||
// None isn't a valid lifetime for an object ivar in ARC, and
|
||||
// __autoreleasing is never valid; don't diagnose twice.
|
||||
if ((ivarLifetime == Qualifiers::OCL_None &&
|
||||
S.getLangOpts().ObjCAutoRefCount) ||
|
||||
ivarLifetime == Qualifiers::OCL_Autoreleasing)
|
||||
return;
|
||||
|
||||
|
@ -953,18 +955,46 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
|
|||
ObjCPropertyDecl::PropertyAttributeKind kind
|
||||
= property->getPropertyAttributes();
|
||||
|
||||
// Add GC __weak to the ivar type if the property is weak.
|
||||
if ((kind & ObjCPropertyDecl::OBJC_PR_weak) &&
|
||||
getLangOpts().getGC() != LangOptions::NonGC) {
|
||||
assert(!getLangOpts().ObjCAutoRefCount);
|
||||
if (PropertyIvarType.isObjCGCStrong()) {
|
||||
Diag(PropertyDiagLoc, diag::err_gc_weak_property_strong_type);
|
||||
Diag(property->getLocation(), diag::note_property_declare);
|
||||
bool isARCWeak = false;
|
||||
if (kind & ObjCPropertyDecl::OBJC_PR_weak) {
|
||||
// Add GC __weak to the ivar type if the property is weak.
|
||||
if (getLangOpts().getGC() != LangOptions::NonGC) {
|
||||
assert(!getLangOpts().ObjCAutoRefCount);
|
||||
if (PropertyIvarType.isObjCGCStrong()) {
|
||||
Diag(PropertyDiagLoc, diag::err_gc_weak_property_strong_type);
|
||||
Diag(property->getLocation(), diag::note_property_declare);
|
||||
} else {
|
||||
PropertyIvarType =
|
||||
Context.getObjCGCQualType(PropertyIvarType, Qualifiers::Weak);
|
||||
}
|
||||
|
||||
// Otherwise, check whether ARC __weak is enabled and works with
|
||||
// the property type.
|
||||
} else {
|
||||
PropertyIvarType =
|
||||
Context.getObjCGCQualType(PropertyIvarType, Qualifiers::Weak);
|
||||
if (!getLangOpts().ObjCWeak) {
|
||||
if (getLangOpts().ObjCWeakRuntime) {
|
||||
Diag(PropertyDiagLoc, diag::err_arc_weak_disabled);
|
||||
} else {
|
||||
Diag(PropertyDiagLoc, diag::err_arc_weak_no_runtime);
|
||||
}
|
||||
Diag(property->getLocation(), diag::note_property_declare);
|
||||
} else {
|
||||
isARCWeak = true;
|
||||
if (const ObjCObjectPointerType *ObjT =
|
||||
PropertyIvarType->getAs<ObjCObjectPointerType>()) {
|
||||
const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl();
|
||||
if (ObjI && ObjI->isArcWeakrefUnavailable()) {
|
||||
Diag(property->getLocation(),
|
||||
diag::err_arc_weak_unavailable_property)
|
||||
<< PropertyIvarType;
|
||||
Diag(ClassImpDecl->getLocation(), diag::note_implemented_by_class)
|
||||
<< ClassImpDecl->getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AtLoc.isInvalid()) {
|
||||
// Check when default synthesizing a property that there is
|
||||
// an ivar matching property name and issue warning; since this
|
||||
|
@ -987,7 +1017,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
|
|||
if (!Ivar) {
|
||||
// In ARC, give the ivar a lifetime qualifier based on the
|
||||
// property attributes.
|
||||
if (getLangOpts().ObjCAutoRefCount &&
|
||||
if ((getLangOpts().ObjCAutoRefCount || isARCWeak) &&
|
||||
!PropertyIvarType.getObjCLifetime() &&
|
||||
PropertyIvarType->isObjCRetainableType()) {
|
||||
|
||||
|
@ -1002,24 +1032,6 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
|
|||
Qualifiers::ObjCLifetime lifetime =
|
||||
getImpliedARCOwnership(kind, PropertyIvarType);
|
||||
assert(lifetime && "no lifetime for property?");
|
||||
if (lifetime == Qualifiers::OCL_Weak) {
|
||||
bool err = false;
|
||||
if (const ObjCObjectPointerType *ObjT =
|
||||
PropertyIvarType->getAs<ObjCObjectPointerType>()) {
|
||||
const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl();
|
||||
if (ObjI && ObjI->isArcWeakrefUnavailable()) {
|
||||
Diag(property->getLocation(),
|
||||
diag::err_arc_weak_unavailable_property) << PropertyIvarType;
|
||||
Diag(ClassImpDecl->getLocation(), diag::note_implemented_by_class)
|
||||
<< ClassImpDecl->getName();
|
||||
err = true;
|
||||
}
|
||||
}
|
||||
if (!err && !getLangOpts().ObjCARCWeak) {
|
||||
Diag(PropertyDiagLoc, diag::err_arc_weak_no_runtime);
|
||||
Diag(property->getLocation(), diag::note_property_declare);
|
||||
}
|
||||
}
|
||||
|
||||
Qualifiers qs;
|
||||
qs.addObjCLifetime(lifetime);
|
||||
|
@ -1027,13 +1039,6 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
|
|||
}
|
||||
}
|
||||
|
||||
if (kind & ObjCPropertyDecl::OBJC_PR_weak &&
|
||||
!getLangOpts().ObjCAutoRefCount &&
|
||||
getLangOpts().getGC() == LangOptions::NonGC) {
|
||||
Diag(PropertyDiagLoc, diag::error_synthesize_weak_non_arc_or_gc);
|
||||
Diag(property->getLocation(), diag::note_property_declare);
|
||||
}
|
||||
|
||||
Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl,
|
||||
PropertyIvarLoc,PropertyIvarLoc, PropertyIvar,
|
||||
PropertyIvarType, /*Dinfo=*/nullptr,
|
||||
|
@ -1121,7 +1126,8 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
|
|||
// Fall thru - see previous comment
|
||||
}
|
||||
}
|
||||
if (getLangOpts().ObjCAutoRefCount)
|
||||
if (getLangOpts().ObjCAutoRefCount || isARCWeak ||
|
||||
Ivar->getType().getObjCLifetime())
|
||||
checkARCPropertyImpl(*this, PropertyLoc, property, Ivar);
|
||||
} else if (PropertyIvar)
|
||||
// @dynamic
|
||||
|
|
|
@ -4408,7 +4408,7 @@ TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
|
|||
TypeSourceInfo *ReturnTypeInfo = nullptr;
|
||||
QualType declSpecTy = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
|
||||
|
||||
if (getLangOpts().ObjCAutoRefCount) {
|
||||
if (getLangOpts().ObjC1) {
|
||||
Qualifiers::ObjCLifetime ownership = Context.getInnerObjCOwnership(FromTy);
|
||||
if (ownership != Qualifiers::OCL_None)
|
||||
transferARCOwnership(state, declSpecTy, ownership);
|
||||
|
@ -5092,11 +5092,6 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
|
|||
return true;
|
||||
}
|
||||
|
||||
// Consume lifetime attributes without further comment outside of
|
||||
// ARC mode.
|
||||
if (!S.getLangOpts().ObjCAutoRefCount)
|
||||
return true;
|
||||
|
||||
IdentifierInfo *II = attr.getArgAsIdent(0)->Ident;
|
||||
Qualifiers::ObjCLifetime lifetime;
|
||||
if (II->isStr("none"))
|
||||
|
@ -5114,6 +5109,14 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
|
|||
return true;
|
||||
}
|
||||
|
||||
// Just ignore lifetime attributes other than __weak and __unsafe_unretained
|
||||
// outside of ARC mode.
|
||||
if (!S.getLangOpts().ObjCAutoRefCount &&
|
||||
lifetime != Qualifiers::OCL_Weak &&
|
||||
lifetime != Qualifiers::OCL_ExplicitNone) {
|
||||
return true;
|
||||
}
|
||||
|
||||
SplitQualType underlyingType = type.split();
|
||||
|
||||
// Check for redundant/conflicting ownership qualifiers.
|
||||
|
@ -5164,24 +5167,36 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
|
|||
type = S.Context.getAttributedType(AttributedType::attr_objc_ownership,
|
||||
origType, type);
|
||||
|
||||
// Forbid __weak if the runtime doesn't support it.
|
||||
// Sometimes, __weak isn't allowed.
|
||||
if (lifetime == Qualifiers::OCL_Weak &&
|
||||
!S.getLangOpts().ObjCARCWeak && !NonObjCPointer) {
|
||||
!S.getLangOpts().ObjCWeak && !NonObjCPointer) {
|
||||
|
||||
// Actually, delay this until we know what we're parsing.
|
||||
// Use a specialized diagnostic if the runtime just doesn't support them.
|
||||
unsigned diagnostic =
|
||||
(S.getLangOpts().ObjCWeakRuntime ? diag::err_arc_weak_disabled
|
||||
: diag::err_arc_weak_no_runtime);
|
||||
|
||||
// In any case, delay the diagnostic until we know what we're parsing.
|
||||
if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
|
||||
S.DelayedDiagnostics.add(
|
||||
sema::DelayedDiagnostic::makeForbiddenType(
|
||||
S.getSourceManager().getExpansionLoc(AttrLoc),
|
||||
diag::err_arc_weak_no_runtime, type, /*ignored*/ 0));
|
||||
diagnostic, type, /*ignored*/ 0));
|
||||
} else {
|
||||
S.Diag(AttrLoc, diag::err_arc_weak_no_runtime);
|
||||
S.Diag(AttrLoc, diagnostic);
|
||||
}
|
||||
|
||||
attr.setInvalid();
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we accepted __weak, we might still need to warn about it.
|
||||
if (lifetime == Qualifiers::OCL_Weak &&
|
||||
!S.getLangOpts().ObjCAutoRefCount &&
|
||||
S.getLangOpts().ObjCWeak) {
|
||||
S.Diag(AttrLoc, diag::warn_objc_weak_compat);
|
||||
}
|
||||
|
||||
// Forbid __weak for class objects marked as
|
||||
// objc_arc_weak_reference_unavailable
|
||||
if (lifetime == Qualifiers::OCL_Weak) {
|
||||
|
@ -5189,9 +5204,9 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
|
|||
type->getAs<ObjCObjectPointerType>()) {
|
||||
if (ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl()) {
|
||||
if (Class->isArcWeakrefUnavailable()) {
|
||||
S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class);
|
||||
S.Diag(ObjT->getInterfaceDecl()->getLocation(),
|
||||
diag::note_class_declared);
|
||||
S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class);
|
||||
S.Diag(ObjT->getInterfaceDecl()->getLocation(),
|
||||
diag::note_class_declared);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
// RUN: arcmt-test --args -triple x86_64-apple-macosx10.6 -fsyntax-only -fobjc-gc-only -x objective-c++ %s > %t
|
||||
// RUN: diff %t %s.result
|
||||
|
||||
// MRC __weak broke this test somehow.
|
||||
// XFAIL: *
|
||||
|
||||
#include "Common.h"
|
||||
#include "GC.h"
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ void test2(Test2 *x) {
|
|||
// CHECK: [[T0:%.*]] = bitcast [[WEAK_T]]* [[WEAKX]] to i8*
|
||||
// CHECK: call void @_Block_object_dispose(i8* [[T0]], i32 8)
|
||||
|
||||
__weak __block Test2 *weakX = x;
|
||||
__attribute__((objc_gc(weak))) __block Test2 *weakX = x;
|
||||
test2_helper(^{ [weakX destroy]; });
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-10.10 -emit-llvm -fblocks -fobjc-weak -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-MODERN
|
||||
// RUN: %clang_cc1 -triple i386-apple-darwin10 -fobjc-runtime=macosx-fragile-10.10 -emit-llvm -fblocks -fobjc-weak -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-FRAGILE
|
||||
|
||||
@interface Object
|
||||
- (instancetype) retain;
|
||||
- (void) run;
|
||||
@end
|
||||
|
||||
// CHECK-MODERN: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\01\00"
|
||||
// CHECK-MODERN: @"\01l_OBJC_CLASS_RO_$_Foo" = {{.*}} { i32 772
|
||||
// 772 == 0x304
|
||||
// ^ HasMRCWeakIvars
|
||||
// ^ HasCXXDestructorOnly
|
||||
// ^ HasCXXStructors
|
||||
|
||||
// CHECK-FRAGILE: @OBJC_CLASS_NAME_{{.*}} = {{.*}} c"\01\00"
|
||||
// CHECK-FRAGILE: @OBJC_CLASS_Foo = {{.*}} i32 134225921,
|
||||
// 134225921 == 0x08002001
|
||||
// ^ HasMRCWeakIvars
|
||||
// ^ HasCXXStructors
|
||||
// ^ Factory
|
||||
@interface Foo : Object {
|
||||
__weak id ivar;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation Foo
|
||||
// CHECK-LABEL: define internal void @"\01-[Foo .cxx_destruct]"
|
||||
// CHECK: call void @objc_destroyWeak
|
||||
@end
|
||||
|
||||
|
||||
void test1(__weak id x) {}
|
||||
// CHECK-LABEL: define void @test1
|
||||
// CHECK: [[X:%.*]] = alloca i8*,
|
||||
// CHECK-NEXT: objc_initWeak
|
||||
// CHECK-NEXT: objc_destroyWeak
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
void test2(id y) {
|
||||
__weak id z = y;
|
||||
}
|
||||
// CHECK-LABEL: define void @test2
|
||||
// CHECK: [[Y:%.*]] = alloca i8*,
|
||||
// CHECK-NEXT: [[Z:%.*]] = alloca i8*,
|
||||
// CHECK-NEXT: store
|
||||
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
|
||||
// CHECK-NEXT: call i8* @objc_initWeak(i8** [[Z]], i8* [[T0]])
|
||||
// CHECK-NEXT: call void @objc_destroyWeak(i8** [[Z]])
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
void test3(id y) {
|
||||
__weak id z;
|
||||
z = y;
|
||||
}
|
||||
// CHECK-LABEL: define void @test3
|
||||
// CHECK: [[Y:%.*]] = alloca i8*,
|
||||
// CHECK-NEXT: [[Z:%.*]] = alloca i8*,
|
||||
// CHECK-NEXT: store
|
||||
// CHECK-NEXT: store i8* null, i8** [[Z]]
|
||||
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
|
||||
// CHECK-NEXT: call i8* @objc_storeWeak(i8** [[Z]], i8* [[T0]])
|
||||
// CHECK-NEXT: call void @objc_destroyWeak(i8** [[Z]])
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
void test4(__weak id *p) {
|
||||
id y = *p;
|
||||
}
|
||||
// CHECK-LABEL: define void @test4
|
||||
// CHECK: [[P:%.*]] = alloca i8**,
|
||||
// CHECK-NEXT: [[Y:%.*]] = alloca i8*,
|
||||
// CHECK-NEXT: store
|
||||
// CHECK-NEXT: [[T0:%.*]] = load i8**, i8*** [[P]]
|
||||
// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[T0]])
|
||||
// CHECK-NEXT: store i8* [[T1]], i8** [[Y]]
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
void test5(__weak id *p) {
|
||||
id y = [*p retain];
|
||||
}
|
||||
// CHECK-LABEL: define void @test5
|
||||
// CHECK: [[P:%.*]] = alloca i8**,
|
||||
// CHECK-NEXT: [[Y:%.*]] = alloca i8*,
|
||||
// CHECK-NEXT: store
|
||||
// CHECK-NEXT: [[T0:%.*]] = load i8**, i8*** [[P]]
|
||||
// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T0]])
|
||||
// CHECK-NEXT: store i8* [[T1]], i8** [[Y]]
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
void test6(__weak Foo **p) {
|
||||
Foo *y = [*p retain];
|
||||
}
|
||||
// CHECK-LABEL: define void @test6
|
||||
// CHECK: [[P:%.*]] = alloca [[FOO:%.*]]**,
|
||||
// CHECK-NEXT: [[Y:%.*]] = alloca [[FOO]]*,
|
||||
// CHECK-NEXT: store
|
||||
// CHECK-NEXT: [[T0:%.*]] = load [[FOO]]**, [[FOO]]*** [[P]]
|
||||
// CHECK-NEXT: [[T1:%.*]] = bitcast [[FOO]]** [[T0]] to i8**
|
||||
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T1]])
|
||||
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[FOO]]*
|
||||
// CHECK-NEXT: store [[FOO]]* [[T3]], [[FOO]]** [[Y]]
|
||||
// CHECK-NEXT: ret void
|
||||
|
||||
extern id get_object(void);
|
||||
extern void use_block(void (^)(void));
|
||||
|
||||
void test7(void) {
|
||||
__weak Foo *p = get_object();
|
||||
use_block(^{ [p run ]; });
|
||||
}
|
||||
// CHECK-LABEL: define void @test7
|
||||
// CHECK: [[P:%.*]] = alloca [[FOO]]*,
|
||||
// CHECK: [[T0:%.*]] = call i8* @get_object()
|
||||
// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[FOO]]*
|
||||
// CHECK-NEXT: [[T2:%.*]] = bitcast [[FOO]]** [[P]] to i8**
|
||||
// CHECK-NEXT: [[T3:%.*]] = bitcast [[FOO]]* [[T1]] to i8*
|
||||
// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]])
|
||||
// CHECK: call void @objc_copyWeak
|
||||
// CHECK: call void @use_block
|
||||
// CHECK: call void @objc_destroyWeak
|
||||
|
||||
// CHECK-LABEL: define internal void @__copy_helper_block
|
||||
// CHECK: @objc_copyWeak
|
||||
|
||||
// CHECK-LABEL: define internal void @__destroy_helper_block
|
||||
// CHECK: @objc_destroyWeak
|
||||
|
||||
void test8(void) {
|
||||
__block __weak Foo *p = get_object();
|
||||
use_block(^{ [p run ]; });
|
||||
}
|
||||
// CHECK-LABEL: define void @test8
|
||||
// CHECK: call i8* @objc_initWeak
|
||||
// CHECK-NOT: call void @objc_copyWeak
|
||||
// CHECK: call void @use_block
|
||||
// CHECK: call void @objc_destroyWeak
|
||||
|
||||
// CHECK-LABEL: define internal void @__Block_byref_object_copy
|
||||
// CHECK: call void @objc_moveWeak
|
||||
|
||||
// CHECK-LABEL: define internal void @__Block_byref_object_dispose
|
||||
// CHECK: call void @objc_destroyWeak
|
|
@ -1,6 +1,6 @@
|
|||
// RUN: %clang_cc1 -fblocks -fobjc-runtime-has-weak -triple x86_64-apple-darwin -print-ivar-layout -emit-llvm -o /dev/null %s > %t-64.layout
|
||||
// RUN: %clang_cc1 -fblocks -fobjc-runtime-has-weak -fobjc-arc -triple x86_64-apple-darwin -print-ivar-layout -emit-llvm -o /dev/null %s > %t-64.layout
|
||||
// RUN: FileCheck -check-prefix=CHECK -check-prefix=CHECK-64 --input-file=%t-64.layout %s
|
||||
// RUN: %clang_cc1 -fblocks -fobjc-runtime-has-weak -triple i386-apple-darwin -print-ivar-layout -emit-llvm -o /dev/null %s > %t-32.layout
|
||||
// RUN: %clang_cc1 -fblocks -fobjc-runtime-has-weak -fobjc-arc -triple i386-apple-darwin -print-ivar-layout -emit-llvm -o /dev/null %s > %t-32.layout
|
||||
// RUN: FileCheck -check-prefix=CHECK -check-prefix=CHECK-32 --input-file=%t-32.layout %s
|
||||
// rdar://12184410
|
||||
// rdar://12184410
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
@property(copy) Foo *myprop;
|
||||
@property(retain, nonatomic) id xx;
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:7:11 %s -fno-objc-arc | FileCheck -check-prefix=CHECK-CC1 %s
|
||||
// RUN: c-index-test -code-completion-at=%s:7:11 %s -fobjc-runtime=macosx-10.4 -fno-objc-arc | FileCheck -check-prefix=CHECK-CC1 -check-prefix=CHECK-CC1-NOWEAK %s
|
||||
// RUN: c-index-test -code-completion-at=%s:7:11 %s -fobjc-runtime=macosx-10.8 -Xclang -fobjc-weak -fno-objc-arc | FileCheck -check-prefix=CHECK-CC1 -check-prefix=CHECK-CC1-WEAK %s
|
||||
// CHECK-CC1: {TypedText assign}
|
||||
// CHECK-CC1-NEXT: {TypedText atomic}
|
||||
// CHECK-CC1-NEXT: {TypedText copy}
|
||||
|
@ -23,7 +24,8 @@
|
|||
// CHECK-CC1-NEXT: {TypedText setter}{Text =}{Placeholder method}
|
||||
// CHECK-CC1-NEXT: {TypedText strong}
|
||||
// CHECK-CC1-NEXT: {TypedText unsafe_unretained}
|
||||
// CHECK-CC1-NOT: {TypedText weak}
|
||||
// CHECK-CC1-NOWEAK-NOT: {TypedText weak}
|
||||
// CHECK-CC1-WEAK-NEXT: {TypedText weak}
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:7:11 %s -fobjc-arc -fobjc-runtime=macosx-10.7 | FileCheck -check-prefix=CHECK-CC1-ARC %s
|
||||
// CHECK-CC1-ARC: {TypedText assign}
|
||||
|
|
|
@ -9,13 +9,13 @@ static id __attribute((objc_gc(hello))) f; // expected-warning{{'objc_gc' attrib
|
|||
|
||||
static int __attribute__((objc_gc(weak))) g; // expected-warning {{'objc_gc' only applies to pointer types; type here is 'int'}}
|
||||
|
||||
static __weak int h; // expected-warning {{'__weak' only applies to pointer types; type here is 'int'}}
|
||||
static __weak int h; // expected-warning {{'__weak' only applies to Objective-C object or block pointer types; type here is 'int'}}
|
||||
|
||||
// TODO: it would be great if this reported as __weak
|
||||
#define WEAK __weak
|
||||
static WEAK int h; // expected-warning {{'objc_gc' only applies to pointer types; type here is 'int'}}
|
||||
static WEAK int h; // expected-warning {{'objc_ownership' only applies to Objective-C object or block pointer types; type here is 'int'}}
|
||||
|
||||
/* expected-warning {{'__weak' only applies to pointer types; type here is 'int'}}*/ static __we\
|
||||
/* expected-warning {{'__weak' only applies to Objective-C object or block pointer types; type here is 'int'}}*/ static __we\
|
||||
ak int i;
|
||||
|
||||
// rdar://problem/9126213
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
// RUN: %clang_cc1 -fobjc-runtime-has-weak -fobjc-weak -fsyntax-only -verify %s
|
||||
|
||||
__attribute__((objc_root_class))
|
||||
@interface A
|
||||
@property (weak) id wa; // expected-note {{property declared here}}
|
||||
@property (weak) id wb;
|
||||
@property (weak) id wc; // expected-note {{property declared here}}
|
||||
@property (weak) id wd;
|
||||
@property (unsafe_unretained) id ua;
|
||||
@property (unsafe_unretained) id ub; // expected-note {{property declared here}}
|
||||
@property (unsafe_unretained) id uc;
|
||||
@property (unsafe_unretained) id ud;
|
||||
@property (strong) id sa;
|
||||
@property (strong) id sb; // expected-note {{property declared here}}
|
||||
@property (strong) id sc; // expected-note {{property declared here}}
|
||||
@property (strong) id sd;
|
||||
@end
|
||||
|
||||
@implementation A {
|
||||
id _wa; // expected-error {{existing instance variable '_wa' for __weak property 'wa' must be __weak}}
|
||||
__weak id _wb;
|
||||
__unsafe_unretained id _wc; // expected-error {{existing instance variable '_wc' for __weak property 'wc' must be __weak}}
|
||||
id _ua;
|
||||
__weak id _ub; // expected-error {{existing instance variable '_ub' for property 'ub' with unsafe_unretained attribute must be __unsafe_unretained}}
|
||||
__unsafe_unretained id _uc;
|
||||
id _sa;
|
||||
__weak id _sb; // expected-error {{existing instance variable '_sb' for strong property 'sb' may not be __weak}}
|
||||
__unsafe_unretained id _sc; // expected-error {{existing instance variable '_sc' for strong property 'sc' may not be __unsafe_unretained}}
|
||||
}
|
||||
@synthesize wa = _wa; // expected-note {{property synthesized here}}
|
||||
@synthesize wb = _wb;
|
||||
@synthesize wc = _wc; // expected-note {{property synthesized here}}
|
||||
@synthesize wd = _wd;
|
||||
@synthesize ua = _ua;
|
||||
@synthesize ub = _ub; // expected-note {{property synthesized here}}
|
||||
@synthesize uc = _uc;
|
||||
@synthesize ud = _ud;
|
||||
@synthesize sa = _sa;
|
||||
@synthesize sb = _sb; // expected-note {{property synthesized here}}
|
||||
@synthesize sc = _sc; // expected-note {{property synthesized here}}
|
||||
@synthesize sd = _sd;
|
||||
@end
|
||||
|
||||
void test_goto() {
|
||||
goto after; // expected-error {{cannot jump from this goto statement to its label}}
|
||||
__weak id x; // expected-note {{jump bypasses initialization of __weak variable}}}
|
||||
after:
|
||||
return;
|
||||
}
|
||||
|
||||
void test_weak_cast(id *value) {
|
||||
__weak id *a = (__weak id*) value;
|
||||
id *b = (__weak id*) value; // expected-error {{initializing 'id *' with an expression of type '__weak id *' changes retain/release properties of pointer}}
|
||||
__weak id *c = (id*) value; // expected-error {{initializing '__weak id *' with an expression of type 'id *' changes retain/release properties of pointer}}
|
||||
}
|
||||
|
||||
void test_unsafe_unretained_cast(id *value) {
|
||||
__unsafe_unretained id *a = (__unsafe_unretained id*) value;
|
||||
id *b = (__unsafe_unretained id*) value;
|
||||
__unsafe_unretained id *c = (id*) value;
|
||||
}
|
||||
|
||||
void test_cast_qualifier_inference(__weak id *value) {
|
||||
__weak id *a = (id*) value;
|
||||
__unsafe_unretained id *b = (id*) value; // expected-error {{initializing '__unsafe_unretained id *' with an expression of type '__weak id *' changes retain/release properties of pointer}}
|
||||
}
|
||||
|
|
@ -1,11 +1,10 @@
|
|||
// RUN: %clang_cc1 -triple i386-apple-darwin9 -fsyntax-only -verify -Wno-objc-root-class %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
@interface Subtask
|
||||
{
|
||||
id _delegate;
|
||||
}
|
||||
@property(nonatomic,readwrite,assign) id __weak delegate;
|
||||
@property(nonatomic,readwrite,assign) id __weak delegate; // expected-error {{the current deployment target does not support automated __weak references}}
|
||||
@end
|
||||
|
||||
@implementation Subtask
|
||||
|
@ -15,15 +14,15 @@
|
|||
|
||||
@interface PVSelectionOverlayView2
|
||||
{
|
||||
id __weak _selectionRect;
|
||||
id __weak _selectionRect; // expected-error {{the current deployment target does not support automated __weak references}} expected-error {{existing instance variable '_selectionRect' for property 'selectionRect' with assign attribute must be __unsafe_unretained}}
|
||||
}
|
||||
|
||||
@property(assign) id selectionRect;
|
||||
@property(assign) id selectionRect; // expected-note {{property declared here}}
|
||||
|
||||
@end
|
||||
|
||||
@implementation PVSelectionOverlayView2
|
||||
|
||||
@synthesize selectionRect = _selectionRect;
|
||||
@synthesize selectionRect = _selectionRect; // expected-note {{property synthesized here}}
|
||||
@end
|
||||
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.8.0 -fobjc-runtime=macosx-10.8.0 -fsyntax-only -Wunused-function %s > %t.nonarc 2>&1
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.8.0 -fobjc-runtime=macosx-10.8.0 -fsyntax-only -Wunused-function -fobjc-arc %s > %t.arc 2>&1
|
||||
// RUN: FileCheck -input-file=%t.nonarc %s
|
||||
// RUN: FileCheck -input-file=%t.arc -check-prefix=ARC %s
|
||||
|
||||
static void bar() {} // Intentionally unused.
|
||||
|
||||
void foo(id self) {
|
||||
__weak id weakSelf = self;
|
||||
}
|
||||
|
||||
// CHECK: 9:13: warning: __weak attribute cannot be specified on an automatic variable when ARC is not enabled
|
||||
// CHECK: 6:13: warning: unused function 'bar'
|
||||
// CHECK: 2 warnings generated
|
||||
// ARC: 6:13: warning: unused function 'bar'
|
||||
// ARC: 1 warning generated
|
|
@ -1,5 +1,5 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -verify -Weverything %s
|
||||
// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fsyntax-only -verify -Weverything %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fobjc-weak -verify -Weverything -Wno-objc-weak-compat %s
|
||||
// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin11 -fobjc-runtime-has-weak -fobjc-weak -fsyntax-only -verify -Weverything -Wno-objc-weak-compat %s
|
||||
// rdar://12103400
|
||||
|
||||
@class NSString;
|
||||
|
|
|
@ -57,5 +57,5 @@ int f0(I *a) { return a->IP; } // expected-error {{instance variable 'IP' is pri
|
|||
|
||||
@implementation A
|
||||
// rdar://9605088
|
||||
@synthesize testObjectWeakProperty; // expected-error {{@synthesize of 'weak' property is only allowed in ARC or GC mode}}
|
||||
@synthesize testObjectWeakProperty; // expected-error {{the current deployment target does not support automated __weak references}}
|
||||
@end
|
||||
|
|
Loading…
Reference in New Issue