r251041 - Define weak and __weak to mean ARC-style weak references, even in MRC.

Nico Weber via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 30 17:39:52 PDT 2015


Hi John,

this breaks programs that use __weak and target 10.6, like so:

$ cat test.m
#import <Foundation/Foundation.h>
@interface I : NSObject {
  __weak NSObject* foo_;
}
- (NSObject*)foo;
@end

@implementation I
- (NSObject *)foo {
  return foo_;
}
@end
$ clang -c test.m -mmacosx-version-min=10.6  # works with Xcode's clang
$ ~/src/llvm-build/bin/clang -c test.m -isysroot $(xcrun -show-sdk-path)
-mmacosx-version-min=10.6
test.m:10:10: error: 'foo_' is unavailable: cannot use weak references
because the current deployment target does not support them
  return foo_;
         ^
test.m:3:20: note: unsupported declaration here
  __weak NSObject* foo_;
                   ^
test.m:3:20: error: cannot create __weak reference because the current
deployment target does not support weak references
  __weak NSObject* foo_;
                   ^
2 errors generated.


We target 10.6 (and don't use ARC) and some library we use has __weak
ivars. After this change, we can't build it any longer. This isn't a huge
issue: we can change the library to use a WEAK macro that expands to
nothing for us and __weak if ARC is enabled, but it sounded like you're
interested in hearing about this.

Nico


On Thu, Oct 22, 2015 at 11:38 AM, John McCall via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

> Author: rjmccall
> Date: Thu Oct 22 13:38:17 2015
> New Revision: 251041
>
> URL: http://llvm.org/viewvc/llvm-project?rev=251041&view=rev
> Log:
> 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
>
> Added:
>     cfe/trunk/test/CodeGenObjC/mrc-weak.m
>     cfe/trunk/test/SemaObjC/mrc-weak.m
> Removed:
>     cfe/trunk/test/SemaObjC/nonarc-weak.m
> Modified:
>     cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td
>     cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>     cfe/trunk/include/clang/Basic/LangOptions.def
>     cfe/trunk/include/clang/Driver/CC1Options.td
>     cfe/trunk/lib/ARCMigrate/ARCMT.cpp
>     cfe/trunk/lib/ARCMigrate/Transforms.cpp
>     cfe/trunk/lib/AST/ASTContext.cpp
>     cfe/trunk/lib/Basic/Targets.cpp
>     cfe/trunk/lib/CodeGen/CGBlocks.cpp
>     cfe/trunk/lib/CodeGen/CGExpr.cpp
>     cfe/trunk/lib/CodeGen/CGExprCXX.cpp
>     cfe/trunk/lib/CodeGen/CGObjC.cpp
>     cfe/trunk/lib/CodeGen/CGObjCMac.cpp
>     cfe/trunk/lib/Driver/Tools.cpp
>     cfe/trunk/lib/Frontend/CompilerInvocation.cpp
>     cfe/trunk/lib/Frontend/InitPreprocessor.cpp
>     cfe/trunk/lib/Lex/PPMacroExpansion.cpp
>     cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
>     cfe/trunk/lib/Sema/SemaCast.cpp
>     cfe/trunk/lib/Sema/SemaCodeComplete.cpp
>     cfe/trunk/lib/Sema/SemaDecl.cpp
>     cfe/trunk/lib/Sema/SemaExpr.cpp
>     cfe/trunk/lib/Sema/SemaObjCProperty.cpp
>     cfe/trunk/lib/Sema/SemaType.cpp
>     cfe/trunk/test/ARCMT/GC-no-arc-runtime.m
>     cfe/trunk/test/CodeGenObjC/blocks.m
>     cfe/trunk/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m
>     cfe/trunk/test/Index/complete-property-flags.m
>     cfe/trunk/test/SemaObjC/attr-objc-gc.m
>     cfe/trunk/test/SemaObjC/no-gc-weak-test.m
>     cfe/trunk/test/SemaObjC/property-in-class-extension-1.m
>     cfe/trunk/test/SemaObjC/synthesized-ivar.m
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td Thu Oct 22
> 13:38:17 2015
> @@ -108,6 +108,10 @@ def err_arc_unsupported_on_runtime : Err
>    "-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<
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Oct 22
> 13:38:17 2015
> @@ -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"
>
>  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<
>
> Modified: cfe/trunk/include/clang/Basic/LangOptions.def
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.def?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/LangOptions.def (original)
> +++ cfe/trunk/include/clang/Basic/LangOptions.def Thu Oct 22 13:38:17 2015
> @@ -193,7 +193,8 @@ LANGOPT(DefaultFPContract , 1, 0, "FP_CO
>  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")
>
> Modified: cfe/trunk/include/clang/Driver/CC1Options.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Driver/CC1Options.td (original)
> +++ cfe/trunk/include/clang/Driver/CC1Options.td Thu Oct 22 13:38:17 2015
> @@ -511,6 +511,8 @@ def fobjc_runtime_has_weak : Flag<["-"],
>    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">,
>
> Modified: cfe/trunk/lib/ARCMigrate/ARCMT.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/ARCMT.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/ARCMigrate/ARCMT.cpp (original)
> +++ cfe/trunk/lib/ARCMigrate/ARCMT.cpp Thu Oct 22 13:38:17 2015
> @@ -206,7 +206,8 @@ createInvocationForMigration(CompilerInv
>    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();
>  }
>
> Modified: cfe/trunk/lib/ARCMigrate/Transforms.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/Transforms.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/ARCMigrate/Transforms.cpp (original)
> +++ cfe/trunk/lib/ARCMigrate/Transforms.cpp Thu Oct 22 13:38:17 2015
> @@ -42,7 +42,7 @@ bool MigrationPass::CFBridgingFunctionsD
>
>  bool trans::canApplyWeak(ASTContext &Ctx, QualType type,
>                           bool AllowOnUnknownClass) {
> -  if (!Ctx.getLangOpts().ObjCARCWeak)
> +  if (!Ctx.getLangOpts().ObjCWeakRuntime)
>      return false;
>
>    QualType T = type;
>
> Modified: cfe/trunk/lib/AST/ASTContext.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ASTContext.cpp (original)
> +++ cfe/trunk/lib/AST/ASTContext.cpp Thu Oct 22 13:38:17 2015
> @@ -4946,8 +4946,6 @@ bool ASTContext::BlockRequiresCopying(Qu
>
>    // 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(QualTy
>    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;
>  }
>
>
> Modified: cfe/trunk/lib/Basic/Targets.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Basic/Targets.cpp (original)
> +++ cfe/trunk/lib/Basic/Targets.cpp Thu Oct 22 13:38:17 2015
> @@ -118,19 +118,11 @@ static void getDarwinDefines(MacroBuilde
>    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", "");
>    }
>
>
> Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Thu Oct 22 13:38:17 2015
> @@ -1393,31 +1393,31 @@ CodeGenFunction::GenerateCopyHelperFunct
>          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 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 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;
>
>        // 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::GenerateDestroyHelperFu
>          flags = BLOCK_FIELD_IS_BLOCK;
>
>        // Special rules for ARC captures.
> -      if (getLangOpts().ObjCAutoRefCount) {
> -        Qualifiers qs = type.getQualifiers();
> +      Qualifiers qs = type.getQualifiers();
> +
> +      // 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.
> +      } else if (qs.getObjCLifetime() == Qualifiers::OCL_Weak) {
> +        useARCWeakDestroy = true;
> +
> +      // Non-ARC captures are strong, and we need to use
> _Block_object_dispose.
> +      } else if (!qs.hasObjCLifetime() &&
> !getLangOpts().ObjCAutoRefCount) {
> +        // fall through
>
> -        // Don't generate special dispose logic for a captured object
> -        // unless it's __strong or __weak.
> -        if (!qs.hasStrongOrWeakObjCLifetime())
> -          continue;
> -
> -        // Support __weak direct captures.
> -        if (qs.getObjCLifetime() == Qualifiers::OCL_Weak)
> -          useARCWeakDestroy = true;
> -
> -        // Tools really want us to use objc_storeStrong here.
> -        else
> -          useARCStrongDestroy = true;
> +      // Otherwise, we have nothing to do.
> +      } else {
> +        continue;
>        }
>      } else {
>        continue;
> @@ -1958,8 +1961,6 @@ CodeGenFunction::buildByrefHelpers(llvm:
>
>    // If we have lifetime, that dominates.
>    if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) {
> -    assert(getLangOpts().ObjCAutoRefCount);
> -
>      switch (lifetime) {
>      case Qualifiers::OCL_None: llvm_unreachable("impossible");
>
>
> Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Thu Oct 22 13:38:17 2015
> @@ -202,11 +202,8 @@ pushTemporaryCleanup(CodeGenFunction &CG
>    //   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 &CG
>          }
>          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 Mater
>
>      // 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
>
> 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(con
>    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(con
>          BaseQuals = BaseTy.getQualifiers();
>        }
>
> -      switch (PseudoDtor->getDestroyedType().getObjCLifetime()) {
> +      switch (DestroyedType.getObjCLifetime()) {
>        case Qualifiers::OCL_None:
>        case Qualifiers::OCL_ExplicitNone:
>        case Qualifiers::OCL_Autoreleasing:
>
> Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Thu Oct 22 13:38:17 2015
> @@ -1526,9 +1526,8 @@ static void EmitObjectDelete(CodeGenFunc
>                                /*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:
>
> Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGObjC.cpp Thu Oct 22 13:38:17 2015
> @@ -323,6 +323,21 @@ shouldExtendReceiverForInnerPointerMessa
>    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::EmitObjCMessageE
>
>    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(
>        } 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.
>
> Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Thu Oct 22 13:38:17 2015
> @@ -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::BuildGC
>                                                  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
>  /// 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 O
>  }
>
>  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 ObjC
>    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 ObjC
>    // 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::EmitSuperClassRe
>  */
>  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::build
>  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 O
>    // 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 * CGObjCNonFragileA
>    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 * CGObjCNonFragileA
>    // 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 * CGObjCNonFragileA
>      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);
>    }
>
> Modified: cfe/trunk/lib/Driver/Tools.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Driver/Tools.cpp (original)
> +++ cfe/trunk/lib/Driver/Tools.cpp Thu Oct 22 13:38:17 2015
> @@ -4765,6 +4765,7 @@ void Clang::ConstructJob(Compilation &C,
>                       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
>
> Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
> +++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Thu Oct 22 13:38:17 2015
> @@ -1421,12 +1421,28 @@ static void ParseLangArgs(LangOptions &O
>        Opts.ObjCAutoRefCount = 1;
>        if (!Opts.ObjCRuntime.allowsARC())
>          Diags.Report(diag::err_arc_unsupported_on_runtime);
> +    }
> +
> +    // 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();
>
> -      // Only set ObjCARCWeak if ARC is enabled.
> -      if (Args.hasArg(OPT_fobjc_runtime_has_weak))
> -        Opts.ObjCARCWeak = 1;
> -      else
> -        Opts.ObjCARCWeak = 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))
>
> Modified: cfe/trunk/lib/Frontend/InitPreprocessor.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/InitPreprocessor.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Frontend/InitPreprocessor.cpp (original)
> +++ cfe/trunk/lib/Frontend/InitPreprocessor.cpp Thu Oct 22 13:38:17 2015
> @@ -323,15 +323,17 @@ static void AddObjCXXARCLibstdcxxDefines
>
>      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
>            << "\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(c
>    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(c
>    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:
>
> Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)
> +++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Thu Oct 22 13:38:17 2015
> @@ -1089,7 +1089,7 @@ static bool HasFeature(const Preprocesso
>        // 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)
>
> Modified: cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp (original)
> +++ cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp Thu Oct 22 13:38:17 2015
> @@ -2050,7 +2050,7 @@ AnalysisBasedWarnings::IssueWarnings(sem
>      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());
>
>
> Modified: cfe/trunk/lib/Sema/SemaCast.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCast.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaCast.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaCast.cpp Thu Oct 22 13:38:17 2015
> @@ -489,9 +489,9 @@ CastsAwayConstness(Sema &Self, QualType
>                     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
>
> Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Thu Oct 22 13:38:17 2015
> @@ -4912,7 +4912,7 @@ void Sema::CodeCompleteObjCPropertyFlags
>      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"));
>
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Oct 22 13:38:17 2015
> @@ -9815,9 +9815,9 @@ Sema::ActOnCXXForRangeIdentifier(Scope *
>  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:
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Oct 22 13:38:17 2015
> @@ -1702,7 +1702,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, Qua
>
>    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);
>
> Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Thu Oct 22 13:38:17 2015
> @@ -663,8 +663,10 @@ static void checkARCPropertyImpl(Sema &S
>    // 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
>      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
>      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
>            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
>          }
>        }
>
> -      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
>          // Fall thru - see previous comment
>        }
>      }
> -    if (getLangOpts().ObjCAutoRefCount)
> +    if (getLangOpts().ObjCAutoRefCount || isARCWeak ||
> +        Ivar->getType().getObjCLifetime())
>        checkARCPropertyImpl(*this, PropertyLoc, property, Ivar);
>    } else if (PropertyIvar)
>      // @dynamic
>
> Modified: cfe/trunk/lib/Sema/SemaType.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaType.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaType.cpp Thu Oct 22 13:38:17 2015
> @@ -4408,7 +4408,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarat
>    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(
>      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(
>      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(
>      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(
>            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);
>          }
>        }
>      }
>
> Modified: cfe/trunk/test/ARCMT/GC-no-arc-runtime.m
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/GC-no-arc-runtime.m?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/ARCMT/GC-no-arc-runtime.m (original)
> +++ cfe/trunk/test/ARCMT/GC-no-arc-runtime.m Thu Oct 22 13:38:17 2015
> @@ -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"
>
>
> Modified: cfe/trunk/test/CodeGenObjC/blocks.m
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/blocks.m?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjC/blocks.m (original)
> +++ cfe/trunk/test/CodeGenObjC/blocks.m Thu Oct 22 13:38:17 2015
> @@ -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]; });
>  }
>
>
> Added: cfe/trunk/test/CodeGenObjC/mrc-weak.m
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/mrc-weak.m?rev=251041&view=auto
>
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjC/mrc-weak.m (added)
> +++ cfe/trunk/test/CodeGenObjC/mrc-weak.m Thu Oct 22 13:38:17 2015
> @@ -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
> +
> + at interface Object
> +- (instancetype) retain;
> +- (void) run;
> + at 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
> + at interface Foo : Object {
> +  __weak id ivar;
> +}
> + at end
> +
> + at implementation Foo
> +// CHECK-LABEL: define internal void @"\01-[Foo .cxx_destruct]"
> +// CHECK: call void @objc_destroyWeak
> + at 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
>
> Modified:
> cfe/trunk/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m
> (original)
> +++ cfe/trunk/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m Thu
> Oct 22 13:38:17 2015
> @@ -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
>
> Modified: cfe/trunk/test/Index/complete-property-flags.m
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-property-flags.m?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/Index/complete-property-flags.m (original)
> +++ cfe/trunk/test/Index/complete-property-flags.m Thu Oct 22 13:38:17 2015
> @@ -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}
>
> Modified: cfe/trunk/test/SemaObjC/attr-objc-gc.m
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/attr-objc-gc.m?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/attr-objc-gc.m (original)
> +++ cfe/trunk/test/SemaObjC/attr-objc-gc.m Thu Oct 22 13:38:17 2015
> @@ -9,13 +9,13 @@ static id __attribute((objc_gc(hello)))
>
>  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
>
> Added: cfe/trunk/test/SemaObjC/mrc-weak.m
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/mrc-weak.m?rev=251041&view=auto
>
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/mrc-weak.m (added)
> +++ cfe/trunk/test/SemaObjC/mrc-weak.m Thu Oct 22 13:38:17 2015
> @@ -0,0 +1,67 @@
> +// RUN: %clang_cc1 -fobjc-runtime-has-weak -fobjc-weak -fsyntax-only
> -verify %s
> +
> +__attribute__((objc_root_class))
> + at interface A
> + at property (weak) id wa; // expected-note {{property declared here}}
> + at property (weak) id wb;
> + at property (weak) id wc; // expected-note {{property declared here}}
> + at property (weak) id wd;
> + at property (unsafe_unretained) id ua;
> + at property (unsafe_unretained) id ub; // expected-note {{property declared
> here}}
> + at property (unsafe_unretained) id uc;
> + at property (unsafe_unretained) id ud;
> + at property (strong) id sa;
> + at property (strong) id sb; // expected-note {{property declared here}}
> + at property (strong) id sc; // expected-note {{property declared here}}
> + at property (strong) id sd;
> + at end
> +
> + at 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}}
> +}
> + at synthesize wa = _wa; // expected-note {{property synthesized here}}
> + at synthesize wb = _wb;
> + at synthesize wc = _wc; // expected-note {{property synthesized here}}
> + at synthesize wd = _wd;
> + at synthesize ua = _ua;
> + at synthesize ub = _ub; // expected-note {{property synthesized here}}
> + at synthesize uc = _uc;
> + at synthesize ud = _ud;
> + at synthesize sa = _sa;
> + at synthesize sb = _sb; // expected-note {{property synthesized here}}
> + at synthesize sc = _sc; // expected-note {{property synthesized here}}
> + at synthesize sd = _sd;
> + at 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}}
> +}
> +
>
> Modified: cfe/trunk/test/SemaObjC/no-gc-weak-test.m
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/no-gc-weak-test.m?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/no-gc-weak-test.m (original)
> +++ cfe/trunk/test/SemaObjC/no-gc-weak-test.m Thu Oct 22 13:38:17 2015
> @@ -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;
>  }
> - at property(nonatomic,readwrite,assign)   id __weak       delegate;
> + at 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}}
>  }
>
> - at property(assign) id selectionRect;
> + at property(assign) id selectionRect; // expected-note {{property declared
> here}}
>
>  @end
>
>  @implementation PVSelectionOverlayView2
>
> - at synthesize selectionRect = _selectionRect;
> + at synthesize selectionRect = _selectionRect; // expected-note {{property
> synthesized here}}
>  @end
>
>
> Removed: cfe/trunk/test/SemaObjC/nonarc-weak.m
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/nonarc-weak.m?rev=251040&view=auto
>
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/nonarc-weak.m (original)
> +++ cfe/trunk/test/SemaObjC/nonarc-weak.m (removed)
> @@ -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
>
> Modified: cfe/trunk/test/SemaObjC/property-in-class-extension-1.m
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/property-in-class-extension-1.m?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/property-in-class-extension-1.m (original)
> +++ cfe/trunk/test/SemaObjC/property-in-class-extension-1.m Thu Oct 22
> 13:38:17 2015
> @@ -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;
>
> Modified: cfe/trunk/test/SemaObjC/synthesized-ivar.m
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/synthesized-ivar.m?rev=251041&r1=251040&r2=251041&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/synthesized-ivar.m (original)
> +++ cfe/trunk/test/SemaObjC/synthesized-ivar.m Thu Oct 22 13:38:17 2015
> @@ -57,5 +57,5 @@ int f0(I *a) { return a->IP; } // expect
>
>  @implementation A
>  // rdar://9605088
> - at synthesize testObjectWeakProperty; // expected-error {{@synthesize of
> 'weak' property is only allowed in ARC or GC mode}}
> + at synthesize testObjectWeakProperty; // expected-error {{the current
> deployment target does not support automated __weak references}}
>  @end
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20151030/0da51765/attachment-0001.html>


More information about the cfe-commits mailing list