Define weak and __weak to mean ARC-style weak references, even in MRC.
authorJohn McCall <rjmccall@apple.com>
Thu, 22 Oct 2015 18:38:17 +0000 (18:38 +0000)
committerJohn McCall <rjmccall@apple.com>
Thu, 22 Oct 2015 18:38:17 +0000 (18:38 +0000)
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

llvm-svn: 251041

35 files changed:
clang/include/clang/Basic/DiagnosticDriverKinds.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Basic/LangOptions.def
clang/include/clang/Driver/CC1Options.td
clang/lib/ARCMigrate/ARCMT.cpp
clang/lib/ARCMigrate/Transforms.cpp
clang/lib/AST/ASTContext.cpp
clang/lib/Basic/Targets.cpp
clang/lib/CodeGen/CGBlocks.cpp
clang/lib/CodeGen/CGExpr.cpp
clang/lib/CodeGen/CGExprCXX.cpp
clang/lib/CodeGen/CGObjC.cpp
clang/lib/CodeGen/CGObjCMac.cpp
clang/lib/Driver/Tools.cpp
clang/lib/Frontend/CompilerInvocation.cpp
clang/lib/Frontend/InitPreprocessor.cpp
clang/lib/Lex/PPMacroExpansion.cpp
clang/lib/Sema/AnalysisBasedWarnings.cpp
clang/lib/Sema/SemaCast.cpp
clang/lib/Sema/SemaCodeComplete.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaObjCProperty.cpp
clang/lib/Sema/SemaType.cpp
clang/test/ARCMT/GC-no-arc-runtime.m
clang/test/CodeGenObjC/blocks.m
clang/test/CodeGenObjC/mrc-weak.m [new file with mode: 0644]
clang/test/CodeGenObjC/mrr-captured-block-var-inlined-layout.m
clang/test/Index/complete-property-flags.m
clang/test/SemaObjC/attr-objc-gc.m
clang/test/SemaObjC/mrc-weak.m [new file with mode: 0644]
clang/test/SemaObjC/no-gc-weak-test.m
clang/test/SemaObjC/nonarc-weak.m [deleted file]
clang/test/SemaObjC/property-in-class-extension-1.m
clang/test/SemaObjC/synthesized-ivar.m

index 6d8187b..7c1f0cd 100644 (file)
@@ -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<
index 20a9226..5781e59 100644 (file)
@@ -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<
index a465f28..b29ec84 100644 (file)
@@ -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")
index dcd724d..e643db6 100644 (file)
@@ -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">,
index 7eb01fb..82d8acd 100644 (file)
@@ -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();
 }
index 56d3af7..99cfacb 100644 (file)
@@ -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;
index 94e3e7c..e774e11 100644 (file)
@@ -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;
 }
 
index 01b1008..e3d8602 100644 (file)
@@ -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", "");
   }
 
index cfb09e7..3f7256b 100644 (file)
@@ -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();
-
-        // 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;
-        }
+      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;
 
       // 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.
+      } else if (qs.getObjCLifetime() == Qualifiers::OCL_Weak) {
+        useARCWeakDestroy = true;
 
-        // Support __weak direct captures.
-        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
 
-        // 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::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");
 
index f61f634..cc35161 100644 (file)
@@ -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:
index ae4e02d..71e4b98 100644 (file)
@@ -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:
index 5890e7f..fce7409 100644 (file)
@@ -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.
index a44cdf8..44c9a90 100644 (file)
@@ -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);
   }
index 74a4958..4c23a29 100644 (file)
@@ -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
index 71ee7e4..99963ba 100644 (file)
@@ -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))
index dc07579..3d62d88 100644 (file)
@@ -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:
index 3e83428..98b7963 100644 (file)
@@ -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)
index e2136ac..94ec796 100644 (file)
@@ -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());
 
index 5099867..4aecd08 100644 (file)
@@ -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
index 8493674..06d9e37 100644 (file)
@@ -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"));
 
index 047ff15..f9e7589 100644 (file)
@@ -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:
index 1b43f92..badb2ef 100644 (file)
@@ -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);
index 374e5cc..0446595 100644 (file)
@@ -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
index d1bf6cc..e53c779 100644 (file)
@@ -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);
         }
       }
     }
index 376134e..99ba2eb 100644 (file)
@@ -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"
 
index 091331e..d485bb4 100644 (file)
@@ -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]; });
 }
 
diff --git a/clang/test/CodeGenObjC/mrc-weak.m b/clang/test/CodeGenObjC/mrc-weak.m
new file mode 100644 (file)
index 0000000..f9c4ff1
--- /dev/null
@@ -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
index c87140a..76b7cfd 100644 (file)
@@ -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
index 9e3fc1a..8e35767 100644 (file)
@@ -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}
index 827945c..303dce0 100644 (file)
@@ -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
diff --git a/clang/test/SemaObjC/mrc-weak.m b/clang/test/SemaObjC/mrc-weak.m
new file mode 100644 (file)
index 0000000..ec03cf7
--- /dev/null
@@ -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}}
+}
+
index 6539a9b..287b4db 100644 (file)
@@ -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
  
 @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
 
diff --git a/clang/test/SemaObjC/nonarc-weak.m b/clang/test/SemaObjC/nonarc-weak.m
deleted file mode 100644 (file)
index ab51875..0000000
+++ /dev/null
@@ -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
index ab461ef..6e9d476 100644 (file)
@@ -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;
index 884a3ca..cc7b309 100644 (file)
@@ -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