소스 검색

Automatic Reference Counting.

Language-design credit goes to a lot of people, but I particularly want
to single out Blaine Garst and Patrick Beard for their contributions.

Compiler implementation credit goes to Argyrios, Doug, Fariborz, and myself,
in no particular order.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133103 91177308-0d34-0410-b5e6-96231b3b80d8
John McCall 14 년 전
부모
커밋
f85e193739
100개의 변경된 파일5540개의 추가작업 그리고 664개의 파일을 삭제
  1. 7 0
      docs/LanguageExtensions.html
  2. 15 1
      include/clang/AST/ASTContext.h
  3. 1 1
      include/clang/AST/CanonicalType.h
  4. 14 5
      include/clang/AST/DeclObjC.h
  5. 2 0
      include/clang/AST/Expr.h
  6. 128 2
      include/clang/AST/ExprObjC.h
  7. 24 1
      include/clang/AST/OperationKinds.h
  8. 1 0
      include/clang/AST/ParentMap.h
  9. 5 1
      include/clang/AST/PrettyPrinter.h
  10. 5 0
      include/clang/AST/RecursiveASTVisitor.h
  11. 8 0
      include/clang/AST/Stmt.h
  12. 33 0
      include/clang/AST/StmtObjC.h
  13. 201 37
      include/clang/AST/Type.h
  14. 5 0
      include/clang/Basic/Attr.td
  15. 1 0
      include/clang/Basic/DiagnosticCommonKinds.td
  16. 4 0
      include/clang/Basic/DiagnosticDriverKinds.td
  17. 3 0
      include/clang/Basic/DiagnosticFrontendKinds.td
  18. 2 0
      include/clang/Basic/DiagnosticGroups.td
  19. 185 3
      include/clang/Basic/DiagnosticSemaKinds.td
  20. 6 0
      include/clang/Basic/LangOptions.h
  21. 5 0
      include/clang/Basic/StmtNodes.td
  22. 6 0
      include/clang/Basic/TokenKinds.def
  23. 15 0
      include/clang/Driver/CC1Options.td
  24. 15 0
      include/clang/Driver/Options.td
  25. 5 1
      include/clang/Driver/ToolChain.h
  26. 2 0
      include/clang/Frontend/CodeGenOptions.h
  27. 8 0
      include/clang/Frontend/FrontendOptions.h
  28. 16 1
      include/clang/Frontend/PreprocessorOptions.h
  29. 1 0
      include/clang/Frontend/Utils.h
  30. 3 1
      include/clang/Parse/Parser.h
  31. 4 1
      include/clang/Rewrite/Rewriter.h
  32. 3 0
      include/clang/Sema/AttributeList.h
  33. 13 3
      include/clang/Sema/DeclSpec.h
  34. 40 1
      include/clang/Sema/DelayedDiagnostic.h
  35. 78 23
      include/clang/Sema/Initialization.h
  36. 14 4
      include/clang/Sema/Overload.h
  37. 106 22
      include/clang/Sema/Sema.h
  38. 9 3
      include/clang/Serialization/ASTBitCodes.h
  39. 20 32
      lib/AST/ASTContext.cpp
  40. 35 1
      lib/AST/DeclCXX.cpp
  41. 22 2
      lib/AST/DeclObjC.cpp
  42. 5 0
      lib/AST/DeclPrinter.cpp
  43. 33 3
      lib/AST/Expr.cpp
  44. 2 0
      lib/AST/ExprClassification.cpp
  45. 18 1
      lib/AST/ExprConstant.cpp
  46. 40 2
      lib/AST/ItaniumMangle.cpp
  47. 9 0
      lib/AST/ParentMap.cpp
  48. 17 0
      lib/AST/StmtPrinter.cpp
  49. 15 0
      lib/AST/StmtProfile.cpp
  50. 320 87
      lib/AST/Type.cpp
  51. 98 19
      lib/AST/TypePrinter.cpp
  52. 6 0
      lib/Analysis/ReachableCode.cpp
  53. 5 0
      lib/Basic/DiagnosticIDs.cpp
  54. 5 2
      lib/Basic/IdentifierTable.cpp
  55. 28 8
      lib/Basic/Targets.cpp
  56. 195 29
      lib/CodeGen/CGBlocks.cpp
  57. 1 1
      lib/CodeGen/CGBlocks.h
  58. 264 10
      lib/CodeGen/CGCall.cpp
  59. 46 1
      lib/CodeGen/CGCall.h
  60. 56 37
      lib/CodeGen/CGClass.cpp
  61. 1 0
      lib/CodeGen/CGDebugInfo.cpp
  62. 240 16
      lib/CodeGen/CGDecl.cpp
  63. 20 7
      lib/CodeGen/CGDeclCXX.cpp
  64. 4 2
      lib/CodeGen/CGException.cpp
  65. 190 26
      lib/CodeGen/CGExpr.cpp
  66. 16 8
      lib/CodeGen/CGExprAgg.cpp
  67. 85 5
      lib/CodeGen/CGExprCXX.cpp
  68. 2 0
      lib/CodeGen/CGExprConstant.cpp
  69. 42 15
      lib/CodeGen/CGExprScalar.cpp
  70. 1362 17
      lib/CodeGen/CGObjC.cpp
  71. 2 2
      lib/CodeGen/CGObjCGNU.cpp
  72. 92 37
      lib/CodeGen/CGObjCMac.cpp
  73. 7 1
      lib/CodeGen/CGObjCRuntime.h
  74. 4 1
      lib/CodeGen/CGStmt.cpp
  75. 20 8
      lib/CodeGen/CGValue.h
  76. 18 1
      lib/CodeGen/CodeGenFunction.cpp
  77. 79 4
      lib/CodeGen/CodeGenFunction.h
  78. 17 4
      lib/CodeGen/CodeGenModule.cpp
  79. 84 3
      lib/CodeGen/CodeGenModule.h
  80. 34 1
      lib/CodeGen/ItaniumCXXABI.cpp
  81. 4 2
      lib/CodeGen/TargetInfo.cpp
  82. 14 0
      lib/CodeGen/TargetInfo.h
  83. 8 1
      lib/Driver/ToolChain.cpp
  84. 96 1
      lib/Driver/ToolChains.cpp
  85. 18 0
      lib/Driver/ToolChains.h
  86. 41 3
      lib/Driver/Tools.cpp
  87. 37 8
      lib/Frontend/CompilerInvocation.cpp
  88. 141 4
      lib/Frontend/InitPreprocessor.cpp
  89. 5 0
      lib/Lex/PPMacroExpansion.cpp
  90. 3 1
      lib/Parse/ParseDecl.cpp
  91. 30 2
      lib/Parse/ParseExpr.cpp
  92. 40 2
      lib/Parse/ParseObjc.cpp
  93. 1 2
      lib/Rewrite/FixItRewriter.cpp
  94. 47 26
      lib/Rewrite/Rewriter.cpp
  95. 5 0
      lib/Sema/AttributeList.cpp
  96. 3 0
      lib/Sema/DelayedDiagnostic.cpp
  97. 88 56
      lib/Sema/JumpDiagnostics.cpp
  98. 35 5
      lib/Sema/Sema.cpp
  99. 104 33
      lib/Sema/SemaCXXCast.cpp
  100. 268 14
      lib/Sema/SemaChecking.cpp

+ 7 - 0
docs/LanguageExtensions.html

@@ -65,6 +65,7 @@ td {
 <li><a href="#objc_features">Objective-C Features</a>
   <ul>
     <li><a href="#objc_instancetype">Related result types</a></li>
+    <li><a href="#objc_arc">Automatic reference counting</a></li>
   </ul>
 </li>
 <li><a href="#overloading-in-c">Function Overloading in C</a></li>
@@ -669,6 +670,12 @@ property access via the given method. In all other respects, a method
 with a related result type is treated the same way as method without a
 related result type.</p>
 
+<!-- ======================================================================= -->
+<h2 id="objc_arc">Automatic reference counting </h2>
+<!-- ======================================================================= -->
+
+<p>Clang provides support for <a href="AutomaticReferenceCounting.html">automated reference counting</a> in Objective-C, which eliminates the need for manual retain/release/autorelease message sends. There are two feature macros associated with automatic reference counting: <code>__has_feature(objc_arc)</code> indicates the availability of automated reference counting in general, while <code>__has_feature(objc_arc_weak)</code> indicates that automated reference counting also includes support for <code>__weak</code> pointers to Objective-C objects.</p>
+
 <!-- ======================================================================= -->
 <h2 id="overloading-in-c">Function Overloading in C</h2>
 <!-- ======================================================================= -->

+ 15 - 1
include/clang/AST/ASTContext.h

@@ -993,6 +993,18 @@ public:
     return getExtQualType(T, Qs);
   }
 
+  /// getLifetimeQualifiedType - Returns a type with the given
+  /// lifetime qualifier.
+  QualType getLifetimeQualifiedType(QualType type,
+                                    Qualifiers::ObjCLifetime lifetime) {
+    assert(type.getObjCLifetime() == Qualifiers::OCL_None);
+    assert(lifetime != Qualifiers::OCL_None);
+
+    Qualifiers qs;
+    qs.addObjCLifetime(lifetime);
+    return getQualifiedType(type, qs);
+  }
+
   DeclarationNameInfo getNameForTemplate(TemplateName Name,
                                          SourceLocation NameLoc) const;
 
@@ -1044,7 +1056,9 @@ public:
 
   /// isObjCNSObjectType - Return true if this is an NSObject object with
   /// its NSObject attribute set.
-  bool isObjCNSObjectType(QualType Ty) const;
+  static bool isObjCNSObjectType(QualType Ty) {
+    return Ty->isObjCNSObjectType();
+  }
 
   //===--------------------------------------------------------------------===//
   //                         Type Sizing and Analysis

+ 1 - 1
include/clang/AST/CanonicalType.h

@@ -250,7 +250,6 @@ public:
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType)
-  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPODType)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isEnumeralType)
@@ -295,6 +294,7 @@ public:
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerOrEnumerationType)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType)
   LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType)
+  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CXXRecordDecl*, getAsCXXRecordDecl)
 
   /// \brief Retrieve the proxy-adaptor type.
   ///

+ 14 - 5
include/clang/AST/DeclObjC.h

@@ -1240,6 +1240,9 @@ class ObjCImplementationDecl : public ObjCImplDecl {
   /// IvarInitializers - The arguments used to initialize the ivars
   CXXCtorInitializer **IvarInitializers;
   unsigned NumIvarInitializers;
+
+  /// true if class has a .cxx_[construct,destruct] method.
+  bool HasCXXStructors : 1;
   
   /// true of class extension has at least one bitfield ivar.
   bool HasSynthBitfield : 1;
@@ -1249,7 +1252,7 @@ class ObjCImplementationDecl : public ObjCImplDecl {
                          ObjCInterfaceDecl *superDecl)
     : ObjCImplDecl(ObjCImplementation, DC, L, classInterface),
        SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0),
-       HasSynthBitfield(false) {}
+       HasCXXStructors(false), HasSynthBitfield(false) {}
 public:
   static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
                                         SourceLocation L,
@@ -1287,6 +1290,9 @@ public:
   void setIvarInitializers(ASTContext &C,
                            CXXCtorInitializer ** initializers,
                            unsigned numInitializers);
+
+  bool hasCXXStructors() const { return HasCXXStructors; }
+  void setHasCXXStructors(bool val) { HasCXXStructors = val; }
   
   bool hasSynthBitfield() const { return HasSynthBitfield; }
   void setHasSynthBitfield (bool val) { HasSynthBitfield = val; }
@@ -1393,7 +1399,10 @@ public:
     OBJC_PR_copy      = 0x20,
     OBJC_PR_nonatomic = 0x40,
     OBJC_PR_setter    = 0x80,
-    OBJC_PR_atomic    = 0x100
+    OBJC_PR_atomic    = 0x100,
+    OBJC_PR_weak      = 0x200,
+    OBJC_PR_strong    = 0x400,
+    OBJC_PR_unsafe_unretained = 0x800
   };
 
   enum SetterKind { Assign, Retain, Copy };
@@ -1401,8 +1410,8 @@ public:
 private:
   SourceLocation AtLoc;   // location of @property
   TypeSourceInfo *DeclType;
-  unsigned PropertyAttributes : 9;
-  unsigned PropertyAttributesAsWritten : 9;
+  unsigned PropertyAttributes : 11;
+  unsigned PropertyAttributesAsWritten : 11;
   // @required/@optional
   unsigned PropertyImplementation : 2;
 
@@ -1466,7 +1475,7 @@ public:
   /// the property setter. This is only valid if the property has been
   /// defined to have a setter.
   SetterKind getSetterKind() const {
-    if (PropertyAttributes & OBJC_PR_retain)
+    if (PropertyAttributes & (OBJC_PR_retain|OBJC_PR_strong))
       return Retain;
     if (PropertyAttributes & OBJC_PR_copy)
       return Copy;

+ 2 - 0
include/clang/AST/Expr.h

@@ -2276,6 +2276,8 @@ private:
     case CK_IntegralComplexToReal:
     case CK_IntegralComplexCast:
     case CK_IntegralComplexToFloatingComplex:
+    case CK_ObjCProduceObject:
+    case CK_ObjCConsumeObject:
       assert(!getType()->isBooleanType() && "unheralded conversion to bool");
       // fallthrough to check for null base path
 

+ 128 - 2
include/clang/AST/ExprObjC.h

@@ -456,7 +456,11 @@ class ObjCMessageExpr : public Expr {
   ///
   /// When non-zero, we have a method declaration; otherwise, we just
   /// have a selector.
-  unsigned HasMethod : 8;
+  unsigned HasMethod : 1;
+
+  /// \brief Whether this message send is a "delegate init call",
+  /// i.e. a call of an init method on self from within an init method.
+  unsigned IsDelegateInitCall : 1;
 
   /// \brief When the message expression is a send to 'super', this is
   /// the location of the 'super' keyword.
@@ -476,7 +480,7 @@ class ObjCMessageExpr : public Expr {
 
   ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs)
     : Expr(ObjCMessageExprClass, Empty), NumArgs(NumArgs), Kind(0), 
-      HasMethod(0), SelectorOrMethod(0) { }
+      HasMethod(0), IsDelegateInitCall(0), SelectorOrMethod(0) { }
 
   ObjCMessageExpr(QualType T, ExprValueKind VK,
                   SourceLocation LBracLoc,
@@ -807,6 +811,12 @@ public:
     getArgs()[Arg] = ArgExpr;
   }
 
+  /// isDelegateInitCall - Answers whether this message send has been
+  /// tagged as a "delegate init call", i.e. a call to a method in the
+  /// -init family on self from within an -init method implementation.
+  bool isDelegateInitCall() const { return IsDelegateInitCall; }
+  void setDelegateInitCall(bool isDelegate) { IsDelegateInitCall = isDelegate; }
+
   SourceLocation getLeftLoc() const { return LBracLoc; }
   SourceLocation getRightLoc() const { return RBracLoc; }
   SourceLocation getSelectorLoc() const { return SelectorLoc; }
@@ -892,6 +902,122 @@ public:
   child_range children() { return child_range(&Base, &Base+1); }
 };
 
+
+/// ObjCIndirectCopyRestoreExpr - Represents the passing of a function
+/// argument by indirect copy-restore in ARC.  This is used to support
+/// passing indirect arguments with the wrong lifetime, e.g. when
+/// passing the address of a __strong local variable to an 'out'
+/// parameter.  This expression kind is only valid in an "argument"
+/// position to some sort of call expression.
+///
+/// The parameter must have type 'pointer to T', and the argument must
+/// have type 'pointer to U', where T and U agree except possibly in
+/// qualification.  If the argument value is null, then a null pointer
+/// is passed;  otherwise it points to an object A, and:
+/// 1. A temporary object B of type T is initialized, either by
+///    zero-initialization (used when initializing an 'out' parameter)
+///    or copy-initialization (used when initializing an 'inout'
+///    parameter).
+/// 2. The address of the temporary is passed to the function.
+/// 3. If the call completes normally, A is move-assigned from B.
+/// 4. Finally, A is destroyed immediately.
+///
+/// Currently 'T' must be a retainable object lifetime and must be
+/// __autoreleasing;  this qualifier is ignored when initializing
+/// the value.
+class ObjCIndirectCopyRestoreExpr : public Expr {
+  Stmt *Operand;
+
+  // unsigned ObjCIndirectCopyRestoreBits.ShouldCopy : 1;
+
+  friend class ASTReader;
+  friend class ASTStmtReader;
+
+  void setShouldCopy(bool shouldCopy) {
+    ObjCIndirectCopyRestoreExprBits.ShouldCopy = shouldCopy;
+  }
+
+  explicit ObjCIndirectCopyRestoreExpr(EmptyShell Empty)
+    : Expr(ObjCIndirectCopyRestoreExprClass, Empty) { }
+
+public:
+  ObjCIndirectCopyRestoreExpr(Expr *operand, QualType type, bool shouldCopy)
+    : Expr(ObjCIndirectCopyRestoreExprClass, type, VK_LValue, OK_Ordinary,
+           operand->isTypeDependent(), operand->isValueDependent(),
+           operand->containsUnexpandedParameterPack()),
+      Operand(operand) {
+    setShouldCopy(shouldCopy);
+  }
+
+  Expr *getSubExpr() { return cast<Expr>(Operand); }
+  const Expr *getSubExpr() const { return cast<Expr>(Operand); }
+
+  /// shouldCopy - True if we should do the 'copy' part of the
+  /// copy-restore.  If false, the temporary will be zero-initialized.
+  bool shouldCopy() const { return ObjCIndirectCopyRestoreExprBits.ShouldCopy; }
+
+  child_range children() { return child_range(&Operand, &Operand+1); }  
+
+  // Source locations are determined by the subexpression.
+  SourceRange getSourceRange() const { return Operand->getSourceRange(); }
+  SourceLocation getExprLoc() const { return getSubExpr()->getExprLoc(); }
+
+  static bool classof(const Stmt *s) {
+    return s->getStmtClass() == ObjCIndirectCopyRestoreExprClass;
+  }
+  static bool classof(const ObjCIndirectCopyRestoreExpr *) { return true; }
+};
+
+/// \brief An Objective-C "bridged" cast expression, which casts between
+/// Objective-C pointers and C pointers, transferring ownership in the process.
+///
+/// \code
+/// NSString *str = (__bridge_transfer NSString *)CFCreateString();
+/// \endcode
+class ObjCBridgedCastExpr : public ExplicitCastExpr {
+  SourceLocation LParenLoc;
+  SourceLocation BridgeKeywordLoc;
+  unsigned Kind : 2;
+  
+  friend class ASTStmtReader;
+  friend class ASTStmtWriter;
+  
+public:
+  ObjCBridgedCastExpr(SourceLocation LParenLoc, ObjCBridgeCastKind Kind,
+                      SourceLocation BridgeKeywordLoc, TypeSourceInfo *TSInfo,
+                      Expr *Operand)
+    : ExplicitCastExpr(ObjCBridgedCastExprClass, TSInfo->getType(), VK_RValue,
+                       CK_BitCast, Operand, 0, TSInfo),
+      LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) { }
+  
+  /// \brief Construct an empty Objective-C bridged cast.
+  explicit ObjCBridgedCastExpr(EmptyShell Shell)
+    : ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0) { }
+
+  SourceLocation getLParenLoc() const { return LParenLoc; }
+
+  /// \brief Determine which kind of bridge is being performed via this cast.
+  ObjCBridgeCastKind getBridgeKind() const { 
+    return static_cast<ObjCBridgeCastKind>(Kind); 
+  }
+  
+  /// \brief Retrieve the kind of bridge being performed as a string.
+  llvm::StringRef getBridgeKindName() const;
+  
+  /// \brief The location of the bridge keyword.
+  SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; }
+  
+  SourceRange getSourceRange() const {
+    return SourceRange(LParenLoc, getSubExpr()->getLocEnd());
+  }
+  
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == ObjCBridgedCastExprClass;
+  }
+  static bool classof(const ObjCBridgedCastExpr *) { return true; }
+ 
+};
+  
 }  // end namespace clang
 
 #endif

+ 24 - 1
include/clang/AST/OperationKinds.h

@@ -245,7 +245,17 @@ enum CastKind {
 
   /// \brief Converts from an integral complex to a floating complex.
   ///   _Complex unsigned -> _Complex float
-  CK_IntegralComplexToFloatingComplex
+  CK_IntegralComplexToFloatingComplex,
+
+  /// \brief Produces an Objective-C object so that it may be
+  /// consumed, e.g. by being passed to a consuming parameter.  Calls
+  /// objc_retain.
+  CK_ObjCProduceObject,
+
+  /// \brief Consumes an Objective-C object that has just been
+  /// produced, e.g. as the return value of a retaining call.  Enters
+  /// a cleanup to call objc_release at some indefinite time.
+  CK_ObjCConsumeObject
 };
 
 #define CK_Invalid ((CastKind) -1)
@@ -284,6 +294,19 @@ enum UnaryOperatorKind {
   UO_Extension            // __extension__ marker.
 };
 
+/// \brief The kind of bridging performed by the Objective-C bridge cast.
+enum ObjCBridgeCastKind {
+  /// \brief Bridging via __bridge, which does nothing but reinterpret
+  /// the bits.
+  OBC_Bridge,
+  /// \brief Bridging via __bridge_transfer, which transfers ownership of an
+  /// Objective-C pointer into ARC.
+  OBC_BridgeTransfer,
+  /// \brief Bridging via __bridge_retain, which makes an ARC object available
+  /// as a +1 C pointer.
+  OBC_BridgeRetained
+};
+
 }
 
 #endif

+ 1 - 0
include/clang/AST/ParentMap.h

@@ -32,6 +32,7 @@ public:
   Stmt *getParent(Stmt*) const;
   Stmt *getParentIgnoreParens(Stmt *) const;
   Stmt *getParentIgnoreParenCasts(Stmt *) const;
+  Stmt *getOuterParenParent(Stmt *) const;
 
   const Stmt *getParent(const Stmt* S) const {
     return getParent(const_cast<Stmt*>(S));

+ 5 - 1
include/clang/AST/PrettyPrinter.h

@@ -41,7 +41,7 @@ struct PrintingPolicy {
       SuppressTagKeyword(false), SuppressTag(false), SuppressScope(false),
       SuppressInitializers(false),
       Dump(false), ConstantArraySizeAsWritten(false),
-      AnonymousTagLocations(true) { }
+      AnonymousTagLocations(true), SuppressStrongLifetime(false) { }
 
   /// \brief The number of spaces to use to indent each line.
   unsigned Indentation : 8;
@@ -129,6 +129,10 @@ struct PrintingPolicy {
   /// that entity (e.g., "enum <anonymous at t.h:10:5>"). Otherwise, just 
   /// prints "<anonymous>" for the name.
   bool AnonymousTagLocations : 1;
+  
+  /// \brief When true, suppress printing of the __strong lifetime qualifier in
+  /// ARC.
+  unsigned SuppressStrongLifetime : 1;
 };
 
 } // end namespace clang

+ 5 - 0
include/clang/AST/RecursiveASTVisitor.h

@@ -1721,6 +1721,7 @@ DEF_TRAVERSE_STMT(ObjCAtSynchronizedStmt, { })
 DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { })
 DEF_TRAVERSE_STMT(ObjCAtTryStmt, { })
 DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { })
+DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, { })
 DEF_TRAVERSE_STMT(CXXForRangeStmt, { })
 DEF_TRAVERSE_STMT(ReturnStmt, { })
 DEF_TRAVERSE_STMT(SwitchStmt, { })
@@ -1933,6 +1934,10 @@ DEF_TRAVERSE_STMT(ObjCMessageExpr, { })
 DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { })
 DEF_TRAVERSE_STMT(ObjCProtocolExpr, { })
 DEF_TRAVERSE_STMT(ObjCSelectorExpr, { })
+DEF_TRAVERSE_STMT(ObjCIndirectCopyRestoreExpr, { })
+DEF_TRAVERSE_STMT(ObjCBridgedCastExpr, {
+  TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+})
 DEF_TRAVERSE_STMT(ParenExpr, { })
 DEF_TRAVERSE_STMT(ParenListExpr, { })
 DEF_TRAVERSE_STMT(PredefinedExpr, { })

+ 8 - 0
include/clang/AST/Stmt.h

@@ -183,6 +183,13 @@ protected:
     unsigned NumPreArgs : 1;
   };
 
+  class ObjCIndirectCopyRestoreExprBitfields {
+    friend class ObjCIndirectCopyRestoreExpr;
+    unsigned : NumExprBits;
+
+    unsigned ShouldCopy : 1;
+  };
+
   union {
     // FIXME: this is wasteful on 64-bit platforms.
     void *Aligner;
@@ -193,6 +200,7 @@ protected:
     DeclRefExprBitfields DeclRefExprBits;
     CastExprBitfields CastExprBits;
     CallExprBitfields CallExprBits;
+    ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits;
   };
 
   friend class ASTStmtReader;

+ 33 - 0
include/clang/AST/StmtObjC.h

@@ -342,6 +342,39 @@ public:
   child_range children() { return child_range(&Throw, &Throw+1); }
 };
 
+/// ObjCAutoreleasePoolStmt - This represent objective-c's 
+/// @autoreleasepool Statement
+class ObjCAutoreleasePoolStmt : public Stmt {
+  Stmt *SubStmt;
+  SourceLocation AtLoc;
+public:
+  ObjCAutoreleasePoolStmt(SourceLocation atLoc, 
+                            Stmt *subStmt)
+  : Stmt(ObjCAutoreleasePoolStmtClass),
+    SubStmt(subStmt), AtLoc(atLoc) {}
+
+  explicit ObjCAutoreleasePoolStmt(EmptyShell Empty) :
+    Stmt(ObjCAutoreleasePoolStmtClass, Empty) { }
+
+  const Stmt *getSubStmt() const { return SubStmt; }
+  Stmt *getSubStmt() { return SubStmt; }
+  void setSubStmt(Stmt *S) { SubStmt = S; }
+
+  SourceRange getSourceRange() const {
+    return SourceRange(AtLoc, SubStmt->getLocEnd());
+  }
+
+  SourceLocation getAtLoc() const { return AtLoc; }
+  void setAtLoc(SourceLocation Loc) { AtLoc = Loc; }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == ObjCAutoreleasePoolStmtClass;
+  }
+  static bool classof(const ObjCAutoreleasePoolStmt *) { return true; }
+
+  child_range children() { return child_range(&SubStmt, &SubStmt + 1); }
+};
+
 }  // end namespace clang
 
 #endif

+ 201 - 37
include/clang/AST/Type.h

@@ -126,6 +126,28 @@ public:
     Strong
   };
 
+  enum ObjCLifetime {
+    /// There is no lifetime qualification on this type.
+    OCL_None,
+
+    /// This object can be modified without requiring retains or
+    /// releases.
+    OCL_ExplicitNone,
+
+    /// Assigning into this object requires the old value to be
+    /// released and the new value to be retained.  The timing of the
+    /// release of the old value is inexact: it may be moved to
+    /// immediately after the last known point where the value is
+    /// live.
+    OCL_Strong,
+
+    /// Reading or writing from this object requires a barrier call.
+    OCL_Weak,
+
+    /// Assigning into this object requires a lifetime extension.
+    OCL_Autoreleasing
+  };
+
   enum {
     /// The maximum supported address space number.
     /// 24 bits should be enough for anyone.
@@ -218,7 +240,37 @@ public:
     qs.removeObjCGCAttr();
     return qs;
   }
+  Qualifiers withoutObjCGLifetime() const {
+    Qualifiers qs = *this;
+    qs.removeObjCLifetime();
+    return qs;
+  }
 
+  bool hasObjCLifetime() const { return Mask & LifetimeMask; }
+  ObjCLifetime getObjCLifetime() const {
+    return ObjCLifetime((Mask & LifetimeMask) >> LifetimeShift);
+  }
+  void setObjCLifetime(ObjCLifetime type) {
+    Mask = (Mask & ~LifetimeMask) | (type << LifetimeShift);
+  }
+  void removeObjCLifetime() { setObjCLifetime(OCL_None); }
+  void addObjCLifetime(ObjCLifetime type) {
+    assert(type);
+    setObjCLifetime(type);
+  }
+
+  /// True if the lifetime is neither None or ExplicitNone.
+  bool hasNonTrivialObjCLifetime() const {
+    ObjCLifetime lifetime = getObjCLifetime();
+    return (lifetime > OCL_ExplicitNone);
+  }
+
+  /// True if the lifetime is either strong or weak.
+  bool hasStrongOrWeakObjCLifetime() const {
+    ObjCLifetime lifetime = getObjCLifetime();
+    return (lifetime == OCL_Strong || lifetime == OCL_Weak);
+  }
+  
   bool hasAddressSpace() const { return Mask & AddressSpaceMask; }
   unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; }
   void setAddressSpace(unsigned space) {
@@ -277,6 +329,8 @@ public:
         addAddressSpace(Q.getAddressSpace());
       if (Q.hasObjCGCAttr())
         addObjCGCAttr(Q.getObjCGCAttr());
+      if (Q.hasObjCLifetime())
+        addObjCLifetime(Q.getObjCLifetime());
     }
   }
 
@@ -287,6 +341,8 @@ public:
            !hasAddressSpace() || !qs.hasAddressSpace());
     assert(getObjCGCAttr() == qs.getObjCGCAttr() ||
            !hasObjCGCAttr() || !qs.hasObjCGCAttr());
+    assert(getObjCLifetime() == qs.getObjCLifetime() ||
+           !hasObjCLifetime() || !qs.hasObjCLifetime());
     Mask |= qs.Mask;
   }
 
@@ -301,10 +357,30 @@ public:
       // changed.
       (getObjCGCAttr() == other.getObjCGCAttr() ||
        !hasObjCGCAttr() || !other.hasObjCGCAttr()) &&
+      // ObjC lifetime qualifiers must match exactly.
+      getObjCLifetime() == other.getObjCLifetime() &&
       // CVR qualifiers may subset.
       (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask));
   }
 
+  /// \brief Determines if these qualifiers compatibly include another set of
+  /// qualifiers from the narrow perspective of Objective-C ARC lifetime.
+  ///
+  /// One set of Objective-C lifetime qualifiers compatibly includes the other
+  /// if the lifetime qualifiers match, or if both are non-__weak and the 
+  /// including set also contains the 'const' qualifier.
+  bool compatiblyIncludesObjCLifetime(Qualifiers other) const {
+    if (getObjCLifetime() == other.getObjCLifetime())
+      return true;
+    
+    if (getObjCLifetime() == OCL_Weak || other.getObjCLifetime() == OCL_Weak)
+      return false;
+    
+    return hasConst();
+  }
+  
+  bool isSupersetOf(Qualifiers Other) const;
+
   /// \brief Determine whether this set of qualifiers is a strict superset of
   /// another set of qualifiers, not considering qualifier compatibility.
   bool isStrictSupersetOf(Qualifiers Other) const;
@@ -351,14 +427,16 @@ public:
 
 private:
 
-  // bits:     |0 1 2|3 .. 4|5  ..  31|
-  //           |C R V|GCAttr|AddrSpace|
+  // bits:     |0 1 2|3 .. 4|5  ..  7|8   ...   31|
+  //           |C R V|GCAttr|Lifetime|AddressSpace|
   uint32_t Mask;
 
   static const uint32_t GCAttrMask = 0x18;
   static const uint32_t GCAttrShift = 3;
-  static const uint32_t AddressSpaceMask = ~(CVRMask | GCAttrMask);
-  static const uint32_t AddressSpaceShift = 5;
+  static const uint32_t LifetimeMask = 0xE0;
+  static const uint32_t LifetimeShift = 5;
+  static const uint32_t AddressSpaceMask = ~(CVRMask|GCAttrMask|LifetimeMask);
+  static const uint32_t AddressSpaceShift = 8;
 };
 
 /// CallingConv - Specifies the calling convention that a function uses.
@@ -527,6 +605,23 @@ public:
     return QualType::isConstant(*this, Ctx);
   }
 
+  /// \brief Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
+  bool isPODType(ASTContext &Context) const;
+
+  /// isCXX11PODType() - Return true if this is a POD type according to the
+  /// more relaxed rules of the C++11 standard, regardless of the current
+  /// compilation's language.
+  /// (C++0x [basic.types]p9)
+  bool isCXX11PODType(ASTContext &Context) const;
+  
+  /// isTrivialType - Return true if this is a trivial type
+  /// (C++0x [basic.types]p9)
+  bool isTrivialType(ASTContext &Context) const;  
+
+  /// isTriviallyCopyableType - Return true if this is a trivially
+  /// copyable type (C++0x [basic.types]p9)
+  bool isTriviallyCopyableType(ASTContext &Context) const;
+
   // Don't promise in the API that anything besides 'const' can be
   // easily added.
 
@@ -709,7 +804,7 @@ public:
   /// getAddressSpace - Return the address space of this type.
   inline unsigned getAddressSpace() const;
 
-  /// GCAttrTypesAttr - Returns gc attribute of this type.
+  /// getObjCGCAttr - Returns gc attribute of this type.
   inline Qualifiers::GC getObjCGCAttr() const;
 
   /// isObjCGCWeak true when Type is objc's weak.
@@ -722,9 +817,24 @@ public:
     return getObjCGCAttr() == Qualifiers::Strong;
   }
 
+  /// getObjCLifetime - Returns lifetime attribute of this type.
+  Qualifiers::ObjCLifetime getObjCLifetime() const {
+    return getQualifiers().getObjCLifetime();
+  }
+
+  bool hasNonTrivialObjCLifetime() const {
+    return getQualifiers().hasNonTrivialObjCLifetime();
+  }
+
+  bool hasStrongOrWeakObjCLifetime() const {
+    return getQualifiers().hasStrongOrWeakObjCLifetime();
+  }
+
   enum DestructionKind {
     DK_none,
-    DK_cxx_destructor
+    DK_cxx_destructor,
+    DK_objc_strong_lifetime,
+    DK_objc_weak_lifetime
   };
 
   /// isDestructedType - nonzero if objects of this type require
@@ -735,6 +845,9 @@ public:
     return isDestructedTypeImpl(*this);
   }
 
+  /// \brief Determine whether this type has trivial copy-assignment semantics.
+  bool hasTrivialCopyAssignment(ASTContext &Context) const;
+  
 private:
   // These methods are implemented in a separate translation unit;
   // "static"-ize them to avoid creating temporary QualTypes in the
@@ -849,6 +962,11 @@ public:
   bool hasObjCGCAttr() const { return Quals.hasObjCGCAttr(); }
   Qualifiers::GC getObjCGCAttr() const { return Quals.getObjCGCAttr(); }
 
+  bool hasObjCLifetime() const { return Quals.hasObjCLifetime(); }
+  Qualifiers::ObjCLifetime getObjCLifetime() const {
+    return Quals.getObjCLifetime();
+  }
+
   bool hasAddressSpace() const { return Quals.hasAddressSpace(); }
   unsigned getAddressSpace() const { return Quals.getAddressSpace(); }
 
@@ -1005,7 +1123,7 @@ protected:
 
     /// Extra information which affects how the function is called, like
     /// regparm and the calling convention.
-    unsigned ExtInfo : 8;
+    unsigned ExtInfo : 9;
 
     /// Whether the function is variadic.  Only used by FunctionProtoType.
     unsigned Variadic : 1;
@@ -1186,31 +1304,14 @@ public:
     return !isReferenceType() && !isFunctionType() && !isVoidType();
   }
 
-  /// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10).
-  bool isPODType() const;
-
   /// isLiteralType - Return true if this is a literal type
   /// (C++0x [basic.types]p10)
   bool isLiteralType() const;
 
-  /// isTrivialType - Return true if this is a trivial type
-  /// (C++0x [basic.types]p9)
-  bool isTrivialType() const;
-
-  /// isTriviallyCopyableType - Return true if this is a trivially copyable type
-  /// (C++0x [basic.types]p9
-  bool isTriviallyCopyableType() const;
-
   /// \brief Test if this type is a standard-layout type.
   /// (C++0x [basic.type]p9)
   bool isStandardLayoutType() const;
 
-  /// isCXX11PODType() - Return true if this is a POD type according to the
-  /// more relaxed rules of the C++11 standard, regardless of the current
-  /// compilation's language.
-  /// (C++0x [basic.types]p9)
-  bool isCXX11PODType() const;
-
   /// Helper methods to distinguish type categories. All type predicates
   /// operate on the canonical type, ignoring typedefs and qualifiers.
 
@@ -1290,7 +1391,11 @@ public:
   bool isComplexIntegerType() const;            // GCC _Complex integer type.
   bool isVectorType() const;                    // GCC vector type.
   bool isExtVectorType() const;                 // Extended vector type.
-  bool isObjCObjectPointerType() const;         // Pointer to *any* ObjC object.
+  bool isObjCObjectPointerType() const;         // pointer to ObjC object
+  bool isObjCRetainableType() const;            // ObjC object or block pointer
+  bool isObjCLifetimeType() const;              // (array of)* retainable type
+  bool isObjCIndirectLifetimeType() const;      // (pointer to)* lifetime type
+  bool isObjCNSObjectType() const;              // __attribute__((NSObject))
   // FIXME: change this to 'raw' interface type, so we can used 'interface' type
   // for the common case.
   bool isObjCObjectType() const;                // NSString or typeof(*(id)0)
@@ -1302,9 +1407,19 @@ public:
   bool isObjCClassType() const;                 // Class
   bool isObjCSelType() const;                 // Class
   bool isObjCBuiltinType() const;               // 'id' or 'Class'
+  bool isObjCARCBridgableType() const;
+  bool isCARCBridgableType() const;
   bool isTemplateTypeParmType() const;          // C++ template type parameter
   bool isNullPtrType() const;                   // C++0x nullptr_t
 
+  /// Determines if this type, which must satisfy
+  /// isObjCLifetimeType(), is implicitly __unsafe_unretained rather
+  /// than implicitly __strong.
+  bool isObjCARCImplicitlyUnretainedType() const;
+
+  /// Return the implicit lifetime for this type, which must not be dependent.
+  Qualifiers::ObjCLifetime getObjCARCImplicitLifetime() const;
+
   enum ScalarTypeKind {
     STK_Pointer,
     STK_MemberPointer,
@@ -1480,6 +1595,7 @@ public:
   }
   CanQualType getCanonicalTypeUnqualified() const; // in CanonicalType.h
   void dump() const;
+
   static bool classof(const Type *) { return true; }
 
   friend class ASTReader;
@@ -2340,30 +2456,33 @@ class FunctionType : public Type {
   // * AST read and write
   // * Codegen
   class ExtInfo {
-    // Feel free to rearrange or add bits, but if you go over 8,
+    // Feel free to rearrange or add bits, but if you go over 9,
     // you'll need to adjust both the Bits field below and
     // Type::FunctionTypeBitfields.
 
-    //   |  CC  |noreturn|hasregparm|regparm
-    //   |0 .. 2|   3    |    4     |5 ..  7
+    //   |  CC  |noreturn|produces|hasregparm|regparm
+    //   |0 .. 2|   3    |    4   |    5     |6 ..  8
     enum { CallConvMask = 0x7 };
     enum { NoReturnMask = 0x8 };
-    enum { HasRegParmMask = 0x10 };
-    enum { RegParmMask = ~(CallConvMask | NoReturnMask),
-           RegParmOffset = 5 };
+    enum { ProducesResultMask = 0x10 };
+    enum { HasRegParmMask = 0x20 };
+    enum { RegParmMask = ~(CallConvMask | NoReturnMask | ProducesResultMask),
+           RegParmOffset = 6 }; // Assumed to be the last field
 
-    unsigned char Bits;
+    uint16_t Bits;
 
-    ExtInfo(unsigned Bits) : Bits(static_cast<unsigned char>(Bits)) {}
+    ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {}
 
     friend class FunctionType;
 
    public:
     // Constructor with no defaults. Use this when you know that you
     // have all the elements (when reading an AST file for example).
-    ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc) {
+    ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc,
+            bool producesResult) {
       Bits = ((unsigned) cc) |
              (noReturn ? NoReturnMask : 0) |
+             (producesResult ? ProducesResultMask : 0) |
              (hasRegParm ? HasRegParmMask : 0) |
              (regParm << RegParmOffset);
     }
@@ -2373,6 +2492,7 @@ class FunctionType : public Type {
     ExtInfo() : Bits(0) {}
 
     bool getNoReturn() const { return Bits & NoReturnMask; }
+    bool getProducesResult() const { return Bits & ProducesResultMask; }
     bool getHasRegParm() const { return Bits & HasRegParmMask; }
     unsigned getRegParm() const { return Bits >> RegParmOffset; }
     CallingConv getCC() const { return CallingConv(Bits & CallConvMask); }
@@ -2394,8 +2514,17 @@ class FunctionType : public Type {
         return ExtInfo(Bits & ~NoReturnMask);
     }
 
+    ExtInfo withProducesResult(bool producesResult) const {
+      if (producesResult)
+        return ExtInfo(Bits | ProducesResultMask);
+      else
+        return ExtInfo(Bits & ~ProducesResultMask);
+    }
+
     ExtInfo withRegParm(unsigned RegParm) const {
-      return ExtInfo(HasRegParmMask | (Bits & ~RegParmMask) | (RegParm << RegParmOffset));
+      return ExtInfo((Bits & ~RegParmMask) |
+                     (HasRegParmMask) |
+                     (RegParm << RegParmOffset));
     }
 
     ExtInfo withCallingConv(CallingConv cc) const {
@@ -2495,7 +2624,8 @@ public:
   struct ExtProtoInfo {
     ExtProtoInfo() :
       Variadic(false), ExceptionSpecType(EST_None), TypeQuals(0),
-      RefQualifier(RQ_None), NumExceptions(0), Exceptions(0), NoexceptExpr(0) {}
+      RefQualifier(RQ_None), NumExceptions(0), Exceptions(0), NoexceptExpr(0),
+      ConsumedArguments(0) {}
 
     FunctionType::ExtInfo ExtInfo;
     bool Variadic;
@@ -2505,6 +2635,7 @@ public:
     unsigned NumExceptions;
     const QualType *Exceptions;
     Expr *NoexceptExpr;
+    const bool *ConsumedArguments;
   };
 
 private:
@@ -2523,7 +2654,7 @@ private:
                     QualType canonical, const ExtProtoInfo &epi);
 
   /// NumArgs - The number of arguments this function has, not counting '...'.
-  unsigned NumArgs : 20;
+  unsigned NumArgs : 19;
 
   /// NumExceptions - The number of types in the exception spec, if any.
   unsigned NumExceptions : 9;
@@ -2531,6 +2662,9 @@ private:
   /// ExceptionSpecType - The type of exception specification this function has.
   unsigned ExceptionSpecType : 3;
 
+  /// HasAnyConsumedArgs - Whether this function has any consumed arguments.
+  unsigned HasAnyConsumedArgs : 1;
+
   /// ArgInfo - There is an variable size array after the class in memory that
   /// holds the argument types.
 
@@ -2540,8 +2674,25 @@ private:
   /// NoexceptExpr - Instead of Exceptions, there may be a single Expr* pointing
   /// to the expression in the noexcept() specifier.
 
+  /// ConsumedArgs - A variable size array, following Exceptions
+  /// and of length NumArgs, holding flags indicating which arguments
+  /// are consumed.  This only appears if HasAnyConsumedArgs is true.
+
   friend class ASTContext;  // ASTContext creates these.
 
+  const bool *getConsumedArgsBuffer() const {
+    assert(hasAnyConsumedArgs());
+
+    // Find the end of the exceptions.
+    Expr * const *eh_end = reinterpret_cast<Expr * const *>(arg_type_end());
+    if (getExceptionSpecType() != EST_ComputedNoexcept)
+      eh_end += NumExceptions;
+    else
+      eh_end += 1; // NoexceptExpr
+
+    return reinterpret_cast<const bool*>(eh_end);
+  }
+
 public:
   unsigned getNumArgs() const { return NumArgs; }
   QualType getArgType(unsigned i) const {
@@ -2562,6 +2713,8 @@ public:
     } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
       EPI.NoexceptExpr = getNoexceptExpr();
     }
+    if (hasAnyConsumedArgs())
+      EPI.ConsumedArguments = getConsumedArgsBuffer();
     return EPI;
   }
 
@@ -2647,6 +2800,16 @@ public:
     return exception_begin() + NumExceptions;
   }
 
+  bool hasAnyConsumedArgs() const {
+    return HasAnyConsumedArgs;
+  }
+  bool isArgConsumed(unsigned I) const {
+    assert(I < getNumArgs() && "argument index out of range!");
+    if (hasAnyConsumedArgs())
+      return getConsumedArgsBuffer()[I];
+    return false;
+  }
+
   bool isSugared() const { return false; }
   QualType desugar() const { return QualType(this, 0); }
 
@@ -2971,6 +3134,7 @@ public:
 
     // Enumerated operand (string or keyword).
     attr_objc_gc,
+    attr_objc_lifetime,
     attr_pcs,
 
     FirstEnumOperandKind = attr_objc_gc,

+ 5 - 0
include/clang/Basic/Attr.td

@@ -400,6 +400,11 @@ def ObjCNSObject : InheritableAttr {
   let Spellings = ["NSObject"];
 }
 
+def ObjCPreciseLifetime : Attr {
+  let Spellings = ["objc_precise_lifetime"];
+  let Subjects = [Var];
+}
+
 def Overloadable : Attr {
   let Spellings = ["overloadable"];
 }

+ 1 - 0
include/clang/Basic/DiagnosticCommonKinds.td

@@ -32,6 +32,7 @@ def note_type_being_defined : Note<
 def note_matching : Note<"to match this '%0'">;
 
 def note_using : Note<"using">;
+def note_possibility : Note<"one possibility">;
 def note_also_found : Note<"also found">;
 
 // Parse && Lex

+ 4 - 0
include/clang/Basic/DiagnosticDriverKinds.td

@@ -82,6 +82,10 @@ def err_drv_conflicting_deployment_targets : Error<
   "conflicting deployment targets, both '%0' and '%1' are present in environment">;
 def err_drv_invalid_arch_for_deployment_target : Error<
   "invalid architecture '%0' for deployment target '%1'">;
+def err_drv_objc_gc_arr : Error<
+  "cannot specify both '-fobjc-arc' and '%0'">;
+def err_arc_nonfragile_abi : Error<
+  "-fobjc-arc is not supported with fragile abi">;
 
 def warn_c_kext : Warning<
   "ignoring -fapple-kext which is valid for c++ and objective-c++ only">;

+ 3 - 0
include/clang/Basic/DiagnosticFrontendKinds.td

@@ -137,6 +137,9 @@ def warn_pch_nonfragile_abi2 : Error<
     "PCH file was compiled with the %select{32-bit|enhanced non-fragile}0 "
     "Objective-C ABI but the %select{32-bit|enhanced non-fragile}1 "
     "Objective-C ABI is selected">;
+def warn_pch_auto_ref_count : Error<
+    "PCH file was compiled %select{without|with} automated reference counting,"
+    "which is currently %select{disabled|enabled}">;
 def warn_pch_apple_kext : Error<
     "PCH file was compiled %select{with|without}0 support for Apple's kernel "
     "extensions ABI but it is currently %select{disabled|enabled}1">;

+ 2 - 0
include/clang/Basic/DiagnosticGroups.td

@@ -169,6 +169,8 @@ def ImplicitAtomic : DiagGroup<"implicit-atomic-properties">;
 def CustomAtomic : DiagGroup<"custom-atomic-properties">;
 def AtomicProperties : DiagGroup<"atomic-properties",
                                  [ImplicitAtomic, CustomAtomic]>;
+def AutomaticReferenceCountingABI : DiagGroup<"arc-abi">;
+def AutomaticReferenceCounting : DiagGroup<"arc", [AutomaticReferenceCountingABI]>;
 def Selector : DiagGroup<"selector">;
 def NonfragileAbi2 : DiagGroup<"nonfragile-abi2">;
 def Protocol : DiagGroup<"protocol">;

+ 185 - 3
include/clang/Basic/DiagnosticSemaKinds.td

@@ -430,6 +430,12 @@ def warn_objc_property_copy_missing_on_block : Warning<
 def warn_atomic_property_rule : Warning<
   "writable atomic property %0 cannot pair a synthesized setter/getter "
   "with a user defined setter/getter">;
+def warn_ownin_getter_rule : Warning<
+  "property's synthesized getter follows Cocoa naming"
+  " convention for returning 'owned' objects">;
+def err_ownin_getter_rule : Error<
+  "property's synthesized getter follows Cocoa naming"
+  " convention for returning 'owned' objects">;
 def warn_default_atomic_custom_getter_setter : Warning<
   "atomic by default property %0 has a user defined %select{getter|setter}1 "
   "(property should be marked 'atomic' if this is intended)">,
@@ -465,6 +471,8 @@ 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"
   " ivar or must explicitly name an ivar">;
+def error_synthesize_weak_non_arc_or_gc : Error<
+  "@synthesize of 'weak' property is only allowed in ARC or GC mode">;
 
 def error_synthesized_ivar_yet_not_supported : Error<
   "instance variable synthesis not yet supported"
@@ -477,7 +485,7 @@ def error_ivar_in_superclass_use : Error<
 def error_weak_property : Error<
   "existing ivar %1 for __weak property %0 must be __weak">;
 def error_strong_property : Error<
-  "property %0 must be declared __weak to match existing ivar %1 with __weak attribute">;
+  "existing ivar %1 for strong property %0 may not be __weak">;
 def error_dynamic_property_ivar_decl : Error<
   "dynamic property can not have ivar specification">;
 def error_duplicate_ivar_use : Error<
@@ -1138,6 +1146,8 @@ def err_format_attribute_implicit_this_format_string : Error<
   "format attribute cannot specify the implicit this argument as the format "
   "string">;
 def warn_unknown_method_family : Warning<"unrecognized method family">;
+def err_init_method_bad_return_type : Error<
+  "init methods must return an object pointer type, not %0">;
 def err_attribute_invalid_size : Error<
   "vector size not an integral multiple of component size">;
 def err_attribute_zero_size : Error<"zero vector size">;
@@ -1163,6 +1173,10 @@ def err_as_qualified_auto_decl : Error<
   "automatic variable qualified with an address space">;
 def err_arg_with_address_space : Error<
   "parameter may not be qualified with an address space">;
+def err_attr_objc_lifetime_bad_type : Error<
+  "the type %0 cannot be retained">;
+def err_attr_objc_lifetime_redundant : Error<
+  "the type %0 already has retainment attributes set on it">;
 def err_attribute_not_string : Error<
   "argument to %0 attribute was not a string literal">;
 def err_attribute_section_invalid_for_target : Error<
@@ -1235,6 +1249,13 @@ def err_cconv_varargs : Error<
 def err_regparm_mismatch : Error<"function declared with with regparm(%0) "
   "attribute was previously declared "
   "%plural{0:without the regparm|:with the regparm(%1)}1 attribute">;
+def err_objc_precise_lifetime_bad_type : Error<
+  "objc_precise_lifetime only applies to retainable types; type here is %0">;
+def warn_objc_precise_lifetime_meaningless : Error<
+  "objc_precise_lifetime is not meaningful for "
+  "%select{__unsafe_unretained|__autoreleasing}0 objects">;
+def warn_label_attribute_not_unused : Warning<
+  "The only valid attribute for labels is 'unused'">;
 def err_invalid_pcs : Error<"Invalid PCS type">;
 
 // Availability attribute
@@ -1569,6 +1590,17 @@ def note_ovl_candidate_bad_gc : Note<"candidate "
     "constructor (inherited)}0%1 not viable: "
     "%select{%ordinal6|'this'}5 argument (%2) has %select{no|__weak|__strong}3 "
     "lifetime, but parameter has %select{no|__weak|__strong}4 lifetime">;
+def note_ovl_candidate_bad_lifetime : Note<"candidate "
+    "%select{function|function|constructor|"
+    "function |function |constructor |"
+    "constructor (the implicit default constructor)|"
+    "constructor (the implicit copy constructor)|"
+    "function (the implicit copy assignment operator)|"
+    "constructor (inherited)}0%1 not viable: "
+    "%select{%ordinal6|'this'}5 argument (%2) has "
+    "%select{no|__unsafe_unretained|__strong|__weak|__autoreleasing}3 lifetime,"
+    " but parameter has %select{no|__unsafe_unretained|__strong|__weak|"
+    "__autoreleasing}4 lifetime">;
 def note_ovl_candidate_bad_cvr_this : Note<"candidate "
     "%select{|function|||function||||"
     "function (the implicit copy assignment operator)|}0 not viable: "
@@ -2202,8 +2234,8 @@ def err_unavailable_message : Error<"%0 is unavailable: %1">;
 def warn_unavailable_fwdclass_message : Warning<
     "%0 maybe unavailable because receiver type is unknown">;
 def note_unavailable_here : Note<
-  "function has been explicitly marked "
-  "%select{unavailable|deleted|deprecated}0 here">;
+  "%select{declaration|function}0 has been explicitly marked "
+  "%select{unavailable|deleted|deprecated}1 here">;
 def warn_not_enough_argument : Warning<
   "not enough variable arguments in %0 declaration to fit a sentinel">;
 def warn_missing_sentinel : Warning <
@@ -2439,12 +2471,16 @@ def note_protected_by_objc_finally : Note<
   "jump bypasses initialization of @finally block">;
 def note_protected_by_objc_synchronized : Note<
   "jump bypasses initialization of @synchronized block">;
+def note_protected_by_objc_autoreleasepool : Note<
+  "jump bypasses auto release push of @autoreleasepool block">;
 def note_protected_by_cxx_try : Note<
   "jump bypasses initialization of try block">;
 def note_protected_by_cxx_catch : Note<
   "jump bypasses initialization of catch block">;
 def note_protected_by___block : Note<
   "jump bypasses setup of __block variable">;
+def note_protected_by_objc_lifetime : Note<
+  "jump bypasses initialization of retaining variable">;
 
 def note_exits_cleanup : Note<
   "jump exits scope of variable with __attribute__((cleanup))">;
@@ -2464,6 +2500,10 @@ def note_exits_cxx_try : Note<
   "jump exits try block">;
 def note_exits_cxx_catch : Note<
   "jump exits catch block">;
+def note_exits_objc_autoreleasepool : Note<
+  "jump exits autoreleasepool block">;
+def note_exits_objc_lifetime : Note<
+  "jump exits scope of retaining variable">;
 
 def err_func_returning_array_function : Error<
   "function cannot return %select{array|function}0 type %1">;
@@ -2495,6 +2535,139 @@ def ext_flexible_array_empty_aggregate_gnu : Extension<
 def ext_flexible_array_union_gnu : Extension<
   "flexible array member %0 in a union is a GNU extension">, InGroup<GNU>;
 
+let CategoryName = "Automatic Reference Counting Issue" in {
+
+// ARC-mode diagnostics.
+def err_arc_weak_no_runtime : Error<
+  "the current deployment target does not support automated __weak references">;
+def err_arc_illegal_explicit_message : Error<
+  "ARC forbids explicit message send of %0">;
+def err_arc_unused_init_message : Error<
+  "the result of a delegate init call must be immediately returned "
+  "or assigned to 'self'">;
+def err_arc_mismatched_cast : Error<
+  "%select{implicit conversion|cast}0 of "
+  "%select{%2|a non-Objective-C pointer type %2|a block pointer|"
+  "an Objective-C pointer|an indirect pointer to an Objective-C pointer}1"
+  " to %3 is disallowed with ARC">;
+def err_arc_objc_object_in_struct : Error<
+  "ARC forbids Objective-C objects in structs or unions">;
+def err_arc_objc_property_default_assign_on_object : Error<
+  "ARC forbids properties of Objective-C objects "
+  "with unspecified storage attribute">;
+def err_arc_illegal_selector : Error<
+  "ARC forbids use of %0 in a @selector">;
+def err_arc_illegal_method_def : Error<
+  "ARC forbids implementation of %0">;
+def err_arc_lost_method_convention : Error<
+  "method was declared as %select{an 'alloc'|a 'copy'|an 'init'|a 'new'}0 "
+  "method, but its implementation doesn't match because %select{"
+  "its result type is not an object pointer|"
+  "its result type is unrelated to its receiver type}1">;
+def note_arc_lost_method_convention : Note<"declaration in interface">;
+def err_arc_gained_method_convention : Error<
+  "method implementation does not match its declaration">;
+def note_arc_gained_method_convention : Note<
+  "declaration in interface is not in the '%select{alloc|copy|init|new}0' "
+  "family because %select{its result type is not an object pointer|"
+  "its result type is unrelated to its receiver type}1">;
+def err_typecheck_arr_assign_self : Error<
+  "cannot assign to 'self' outside of a method in the init family">;
+def err_typecheck_arr_assign_enumeration : Error<
+  "fast enumeration variables can't be modified in ARC by default; "
+  "declare the variable __strong to allow this">;
+def warn_arc_non_pod_class_with_object_member : Warning<
+  "%0 cannot be shared between ARC and non-ARC "
+  "code; add a copy constructor, a copy assignment operator, and a destructor "
+  "to make it ABI-compatible">, InGroup<AutomaticReferenceCountingABI>,
+  DefaultIgnore;
+def warn_arc_retained_assign : Warning<
+  "cannot assign retained object to %select{weak|unsafe_unretained}0 variable">;
+def warn_arc_trivial_member_function_with_object_member : Warning<
+  "%0 cannot be shared between ARC and non-ARC "
+  "code; add a non-trivial %select{copy constructor|copy assignment operator|"
+  "destructor}1 to make it ABI-compatible">, 
+  InGroup<AutomaticReferenceCountingABI>, DefaultIgnore;
+def err_arc_new_array_without_lifetime : Error<
+  "'new' cannot allocate an array of %0 with no explicit lifetime">;
+def warn_err_new_delete_object_array : Warning<
+  "%select{allocating|destroying}0 an array of %1; this array must not "
+  "%select{be deleted in|have been allocated from}0 non-ARC code">,
+  InGroup<AutomaticReferenceCountingABI>, DefaultIgnore;
+def err_arc_autoreleasing_var : Error<
+  "%select{__block variables|global variables|fields|ivars}0 cannot have "
+  "__autoreleasing lifetime">;
+def err_arc_thread_lifetime : Error<
+  "thread-local variable has non-trivial lifetime: type is %0">;
+def err_arc_indirect_no_lifetime : Error<
+  "%select{pointer|reference}1 to non-const type %0 with no explicit lifetime">,
+  InGroup<AutomaticReferenceCounting>;
+def err_arc_array_param_no_lifetime : Error<
+  "must explicitly describe intended lifetime of an object array parameter">;
+def err_arc_pseudo_dtor_inconstant_quals : Error<
+  "pseudo-destructor destroys object of type %0 with inconsistently-qualified "
+  "type %1">;
+def err_arc_init_method_unrelated_result_type : Error<
+  "init methods must return a type related to the receiver type">;
+def err_arc_nonlocal_writeback : Error<
+  "passing address of %select{non-local|non-scalar}0 object to "
+  "__autoreleasing parameter for write-back">;
+def err_arc_method_not_found : Error<
+  "no known %select{instance|class}1 method for selector %0">;
+def err_arc_receiver_forward_class : Error<
+  "receiver %0 for class message is a forward declaration">;
+def err_arc_may_not_respond : Error<
+  "receiver type %0 for instance message does not declare a method with "
+  "selector %1">;
+def err_arc_receiver_forward_instance : Error<
+  "receiver type %0 for instance message is a forward declaration">;
+def err_arc_multiple_method_decl : Error< 
+  "multiple methods named %0 found with mismatched result, "
+  "parameter type or attributes">;
+def warn_arc_retain_cycle : Warning<
+  "capturing %0 strongly in this block is likely to lead to a retain cycle">,
+  InGroup<DiagGroup<"retain-cycles">>;
+def note_arc_retain_cycle_owner : Note<
+  "block will be retained by %select{the captured object|an object strongly "
+  "retained by the captured object}0">;
+def note_nontrivial_objc_lifetime : Note<
+  "because type %0 has %select{no|no|__strong|__weak|__autoreleasing}1 "
+  "lifetime">;
+def warn_arc_object_memaccess : Warning<
+  "%select{destination for|source of}0 this %1 call is a pointer to "
+  "lifetime-qualified type %2">, InGroup<DiagGroup<"non-pod-memaccess">>;
+
+def err_arc_strong_property_lifetime : Error<
+  "existing ivar %1 for strong property %0 may not be "
+  "%select{|__unsafe_unretained||__weak}2">;
+def err_arc_assign_property_lifetime : Error<
+  "existing ivar %1 for unsafe_unretained property %0 must be __unsafe_unretained">;
+def err_arc_inconsistent_property_lifetime : Error<
+  "%select{strong|weak|unsafe_unretained}1 property %0 may not also be "
+  "declared %select{|__unsafe_unretained|__strong|__weak|__autoreleasing}2">;
+def err_arc_atomic_lifetime : Error<
+  "cannot perform atomic operation on a pointer to type %0: type has "
+  "non-trivial lifetime">;
+
+def err_arc_bridge_cast_incompatible : Error<
+  "incompatible types casting %0 to %1 with a %select{__bridge|"
+  "__bridge_transfer|__bridge_retained}2 cast">;
+def err_arc_bridge_cast_wrong_kind : Error<
+  "cast of %select{Objective-C|block|C}0 pointer type %1 to "
+  "%select{Objective-C|block|C}2 pointer type %3 cannot use %select{__bridge|"
+  "__bridge_transfer|__bridge_retained}4">;
+def err_arc_cast_requires_bridge : Error<
+  "cast of %select{Objective-C|block|C}0 pointer type %1 to "
+  "%select{Objective-C|block|C}2 pointer type %3 requires a bridged cast">;
+def note_arc_bridge : Note<
+  "use __bridge to convert directly (no change in ownership)">;
+def note_arc_bridge_transfer : Note<
+  "use __bridge_transfer to transfer ownership of a +1 %0 into ARC">;
+def note_arc_bridge_retained : Note<
+  "use __bridge_retained to make an ARC object available as a +1 %0">;
+
+} // ARC category name
+
 def err_flexible_array_init_needs_braces : Error<
   "flexible array requires brace-enclosed initializer">;
 def err_illegal_decl_array_of_functions : Error<
@@ -3337,6 +3510,15 @@ def err_typecheck_incompatible_address_space : Error<
   "|sending %0 to parameter of type %1"
   "|casting %0 to type %1}2"
   " changes address space of pointer">;
+def err_typecheck_incompatible_lifetime : Error<
+  "%select{assigning %1 to %0"
+  "|passing %0 to parameter of type %1"
+  "|returning %0 from a function with result type %1"
+  "|converting %0 to type %1"
+  "|initializing %0 with an expression of type %1"
+  "|sending %0 to parameter of type %1"
+  "|casting %0 to type %1}2"
+  " changes retain/release properties of pointer">;
 def err_typecheck_convert_ambiguous : Error<
   "ambiguity in initializing value of type %0 with initializer of type %1">;
 def err_typecheck_comparison_of_distinct_blocks : Error<

+ 6 - 0
include/clang/Basic/LangOptions.h

@@ -130,6 +130,10 @@ public:
   unsigned DefaultFPContract : 1; // Default setting for FP_CONTRACT
   // FIXME: This is just a temporary option, for testing purposes.
   unsigned NoBitFieldTypeAlign : 1;
+  unsigned ObjCAutoRefCount : 1; // Objective C automated reference counting
+  unsigned ObjCNoAutoRefCountRuntime : 1; // ARC w/o extra runtime support
+  unsigned ObjCInferRelatedReturnType : 1; // Infer Objective-C related return
+                                           // types
   unsigned FakeAddressSpaceMap : 1; // Use a fake address space map, for
                                     // testing languages such as OpenCL.
 
@@ -172,6 +176,8 @@ public:
     Trigraphs = BCPLComment = Bool = DollarIdents = AsmPreprocessor = 0;
     GNUMode = GNUKeywords = ImplicitInt = Digraphs = 0;
     HexFloats = 0;
+    ObjCAutoRefCount = ObjCNoAutoRefCountRuntime = 0;
+    ObjCInferRelatedReturnType = 0;
     GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0;
     AppleKext = 0;
     ObjCDefaultSynthProperties = 0;

+ 5 - 0
include/clang/Basic/StmtNodes.td

@@ -37,6 +37,7 @@ def ObjCAtFinallyStmt : Stmt;
 def ObjCAtThrowStmt : Stmt;
 def ObjCAtSynchronizedStmt : Stmt;
 def ObjCForCollectionStmt : Stmt;
+def ObjCAutoreleasePoolStmt : Stmt;
 
 // C++ statments
 def CXXCatchStmt : Stmt;
@@ -130,6 +131,10 @@ def ObjCProtocolExpr : DStmt<Expr>;
 def ObjCIvarRefExpr : DStmt<Expr>;
 def ObjCPropertyRefExpr : DStmt<Expr>;
 def ObjCIsaExpr : DStmt<Expr>;
+def ObjCIndirectCopyRestoreExpr : DStmt<Expr>;
+
+// Obj-C ARC Expressions.
+def ObjCBridgedCastExpr : DStmt<ExplicitCastExpr>;
 
 // CUDA Expressions.
 def CUDAKernelCallExpr : DStmt<CallExpr>;

+ 6 - 0
include/clang/Basic/TokenKinds.def

@@ -422,6 +422,11 @@ KEYWORD(__pascal                    , KEYALL)
 KEYWORD(__vector                    , KEYALTIVEC)
 KEYWORD(__pixel                     , KEYALTIVEC)
 
+// Objective-C ARC keywords.
+KEYWORD(__bridge                     , KEYARC)
+KEYWORD(__bridge_transfer            , KEYARC)
+KEYWORD(__bridge_retained            , KEYARC)
+
 // Alternate spelling for various tokens.  There are GCC extensions in all
 // languages, but should not be disabled in strict conformance mode.
 ALIAS("__alignof__"  , __alignof  , KEYALL)
@@ -507,6 +512,7 @@ OBJC1_AT_KEYWORD(try)
 OBJC1_AT_KEYWORD(catch)
 OBJC1_AT_KEYWORD(finally)
 OBJC1_AT_KEYWORD(synchronized)
+OBJC1_AT_KEYWORD(autoreleasepool)
 
 OBJC2_AT_KEYWORD(property)
 OBJC2_AT_KEYWORD(package)

+ 15 - 0
include/clang/Driver/CC1Options.td

@@ -383,6 +383,13 @@ def create_module : Flag<"-create-module">,
   HelpText<"Create a module definition file">;
 }
 
+def arcmt_check : Flag<"-arcmt-check">,
+  HelpText<"Check for ARC migration issues that need manual handling">;
+def arcmt_modify : Flag<"-arcmt-modify">,
+  HelpText<"Apply modifications to files to conform to ARC">;
+def arcmt_modify_in_memory : Flag<"-arcmt-modify-in-memory">,
+  HelpText<"Apply ARC conforming modifications & compile using memory buffers">;
+
 def import_module : Separate<"-import-module">,
   HelpText<"Import a module definition file">;
 
@@ -479,6 +486,14 @@ def fconstant_string_class : Separate<"-fconstant-string-class">,
   HelpText<"Specify the class to use for constant Objective-C string objects.">;
 def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">,
   HelpText<"Enable creation of CodeFoundation-type constant strings">;
+def fobjc_arc : Flag<"-fobjc-arc">,
+  HelpText<"Synthesize retain and release calls for Objective-C pointers">;
+def fobjc_arc_cxxlib_EQ : Joined<"-fobjc-arc-cxxlib=">,
+  HelpText<"Objective-C++ Automatic Reference Counting standard library kind">;
+def fobjc_no_arc_runtime : Flag<"-fobjc-no-arc-runtime">,
+  HelpText<"Implement -fobjc-arc without any extra runtime support">;
+def fobjc_arc_exceptions : Flag<"-fobjc-arc-exceptions">,
+  HelpText<"Use EH-safe code when synthesizing retains and releases in -fobjc-arc">;
 def fobjc_gc : Flag<"-fobjc-gc">,
   HelpText<"Enable Objective-C garbage collection">;
 def fobjc_gc_only : Flag<"-fobjc-gc-only">,

+ 15 - 0
include/clang/Driver/Options.td

@@ -112,6 +112,13 @@ def ccc_print_phases : Flag<"-ccc-print-phases">, CCCDebugOpt,
 def ccc_print_bindings : Flag<"-ccc-print-bindings">, CCCDebugOpt,
   HelpText<"Show bindings of tools to actions">;
 
+def ccc_arrmt_check : Flag<"-ccc-arrmt-check">, CCCDriverOpt,
+  HelpText<"Check for ARC migration issues that need manual handling">;
+def ccc_arrmt_modify : Flag<"-ccc-arrmt-modify">, CCCDriverOpt,
+  HelpText<"Apply modifications to files to conform to ARC">;
+def ccc_arrmt_modify_in_memory : Flag<"-ccc-arrmt-modify-in-memory">,
+  HelpText<"Apply ARC conforming modifications & compile using memory buffers">;
+
 // Make sure all other -ccc- options are rejected.
 def ccc_ : Joined<"-ccc-">, Group<ccc_Group>, Flags<[Unsupported]>;
 
@@ -382,6 +389,10 @@ def fno_verbose_asm : Flag<"-fno-verbose-asm">, Group<f_Group>;
 def fno_working_directory : Flag<"-fno-working-directory">, Group<f_Group>;
 def fno_wrapv : Flag<"-fno-wrapv">, Group<f_Group>;
 def fno_zero_initialized_in_bss : Flag<"-fno-zero-initialized-in-bss">, Group<f_Group>;
+def fobjc_arc : Flag<"-fobjc-arc">, Group<f_Group>;
+def fno_objc_arc : Flag<"-fno-objc-arc">, Group<f_Group>;
+def fobjc_arc_exceptions : Flag<"-fobjc-arc-exceptions">, Group<f_Group>;
+def fno_objc_arc_exceptions : Flag<"-fno-objc-arc-exceptions">, Group<f_Group>;
 def fobjc_atdefs : Flag<"-fobjc-atdefs">, Group<clang_ignored_f_Group>;
 def fobjc_call_cxx_cdtors : Flag<"-fobjc-call-cxx-cdtors">, Group<clang_ignored_f_Group>;
 def fobjc_default_synthesize_properties : 
@@ -392,6 +403,10 @@ def fobjc_gc_only : Flag<"-fobjc-gc-only">, Group<f_Group>;
 def fobjc_gc : Flag<"-fobjc-gc">, Group<f_Group>;
 def fobjc_legacy_dispatch : Flag<"-fobjc-legacy-dispatch">, Group<f_Group>;
 def fobjc_new_property : Flag<"-fobjc-new-property">, Group<clang_ignored_f_Group>;
+def fobjc_infer_related_result_type : Flag<"-fobjc-infer-related-result-type">, 
+                                      Group<f_Group>;
+def fno_objc_infer_related_result_type : Flag<
+  "-fno-objc-infer-related-result-type">, Group<f_Group>;
 
 // Objective-C ABI options.
 def fobjc_abi_version_EQ : Joined<"-fobjc-abi-version=">, Group<f_Group>;

+ 5 - 1
include/clang/Driver/ToolChain.h

@@ -166,6 +166,9 @@ public:
   /// UseSjLjExceptions - Does this tool chain use SjLj exceptions.
   virtual bool UseSjLjExceptions() const { return false; }
 
+  /// HasARCRuntime - Does this tool chain provide a specialized ARC runtime.
+  virtual bool HasARCRuntime() const { return false; }
+
   /// ComputeLLVMTriple - Return the LLVM target triple to use, after taking
   /// command line arguments into account.
   virtual std::string ComputeLLVMTriple(const ArgList &Args) const;
@@ -184,7 +187,8 @@ public:
   /// AddClangCXXStdlibIncludeArgs - Add the clang -cc1 level arguments to set
   /// the include paths to use for the given C++ standard library type.
   virtual void AddClangCXXStdlibIncludeArgs(const ArgList &Args,
-                                            ArgStringList &CmdArgs) const;
+                                            ArgStringList &CmdArgs,
+                                            bool ObjCXXAutoRefCount) const;
 
   /// AddCXXStdlibLibArgs - Add the system specific linker arguments to use
   /// for the given C++ standard library type.

+ 2 - 0
include/clang/Frontend/CodeGenOptions.h

@@ -36,6 +36,7 @@ public:
   };
 
   unsigned AsmVerbose        : 1; /// -dA, -fverbose-asm.
+  unsigned ObjCAutoRefCountExceptions : 1; /// Whether ARC should be EH-safe.
   unsigned CXAAtExit         : 1; /// Use __cxa_atexit for calling destructors.
   unsigned CXXCtorDtorAliases: 1; /// Emit complete ctors/dtors as linker
                                   /// aliases to base ctors when possible.
@@ -133,6 +134,7 @@ public:
 public:
   CodeGenOptions() {
     AsmVerbose = 0;
+    ObjCAutoRefCountExceptions = 0;
     CXAAtExit = 1;
     CXXCtorDtorAliases = 0;
     DataSections = 0;

+ 8 - 0
include/clang/Frontend/FrontendOptions.h

@@ -77,6 +77,13 @@ public:
   unsigned FixWhatYouCan : 1;              ///< Apply fixes even if there are
                                            /// unfixable errors.
 
+  enum {
+    ARCMT_None,
+    ARCMT_Check,
+    ARCMT_Modify,
+    ARCMT_ModifyInMemory
+  } ARCMTAction;
+
   /// The input files and their types.
   std::vector<std::pair<InputKind, std::string> > Inputs;
 
@@ -131,6 +138,7 @@ public:
     ShowStats = 0;
     ShowTimers = 0;
     ShowVersion = 0;
+    ARCMTAction = ARCMT_None;
   }
 
   /// getInputKindForExtension - Return the appropriate input kind for a file

+ 16 - 1
include/clang/Frontend/PreprocessorOptions.h

@@ -26,6 +26,15 @@ namespace clang {
 class Preprocessor;
 class LangOptions;
 
+/// \brief Enumerate the kinds of standard library that 
+enum ObjCXXARCStandardLibraryKind {
+  ARCXX_nolib,
+  /// \brief libc++
+  ARCXX_libcxx,
+  /// \brief libstdc++
+  ARCXX_libstdcxx
+};
+  
 /// PreprocessorOptions - This class is used for passing the various options
 /// used in preprocessor initialization to InitializePreprocessor().
 class PreprocessorOptions {
@@ -104,6 +113,11 @@ public:
   /// compiler invocation and its buffers will be reused.
   bool RetainRemappedFileBuffers;
   
+  /// \brief The Objective-C++ ARC standard library that we should support,
+  /// by providing appropriate definitions to retrofit the standard library
+  /// with support for lifetime-qualified pointers.
+  ObjCXXARCStandardLibraryKind ObjCXXARCStandardLibrary;
+  
   typedef std::vector<std::pair<std::string, std::string> >::iterator
     remapped_file_iterator;
   typedef std::vector<std::pair<std::string, std::string> >::const_iterator
@@ -145,7 +159,8 @@ public:
                           DumpDeserializedPCHDecls(false),
                           PrecompiledPreambleBytes(0, true),
                           RemappedFilesKeepOriginalName(true),
-                          RetainRemappedFileBuffers(false) { }
+                          RetainRemappedFileBuffers(false),
+                          ObjCXXARCStandardLibrary(ARCXX_nolib) { }
 
   void addMacroDef(llvm::StringRef Name) {
     Macros.push_back(std::make_pair(Name, false));

+ 1 - 0
include/clang/Frontend/Utils.h

@@ -19,6 +19,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/Support/raw_ostream.h"
+#include "clang/Basic/Diagnostic.h"
 
 namespace llvm {
 class Triple;

+ 3 - 1
include/clang/Parse/Parser.h

@@ -1375,6 +1375,7 @@ bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
   StmtResult ParseObjCTryStmt(SourceLocation atLoc);
   StmtResult ParseObjCThrowStmt(SourceLocation atLoc);
   StmtResult ParseObjCSynchronizedStmt(SourceLocation atLoc);
+  StmtResult ParseObjCAutoreleasePoolStmt(SourceLocation atLoc);
 
 
   //===--------------------------------------------------------------------===//
@@ -1616,7 +1617,8 @@ bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
 
   TypeResult ParseTypeName(SourceRange *Range = 0,
                            Declarator::TheContext Context
-                             = Declarator::TypeNameContext);
+                             = Declarator::TypeNameContext,
+                           ObjCDeclSpec *objcQuals = 0);
   void ParseBlockId();
 
   void ProhibitAttributes(ParsedAttributesWithRange &attrs) {

+ 4 - 1
include/clang/Rewrite/Rewriter.h

@@ -183,8 +183,11 @@ public:
   /// InsertText - Insert the specified string at the specified location in the
   /// original buffer.  This method returns true (and does nothing) if the input
   /// location was not rewritable, false otherwise.
+  ///
+  /// \param indentNewLines if true new lines in the string are indented
+  /// using the indentation of the source line in position \arg Loc.
   bool InsertText(SourceLocation Loc, llvm::StringRef Str,
-                  bool InsertAfter = true);
+                  bool InsertAfter = true, bool indentNewLines = false);
 
   /// InsertTextAfter - Insert the specified string at the specified location in
   ///  the original buffer.  This method returns true (and does nothing) if

+ 3 - 0
include/clang/Sema/AttributeList.h

@@ -198,6 +198,7 @@ public:
     AT_objc_method_family,
     AT_cf_returns_not_retained, // Clang-specific.
     AT_cf_returns_retained,     // Clang-specific.
+    AT_cf_returns_autoreleased, // Clang-specific.
     AT_ns_returns_not_retained, // Clang-specific.
     AT_ns_returns_retained,     // Clang-specific.
     AT_ns_returns_autoreleased, // Clang-specific.
@@ -205,6 +206,8 @@ public:
     AT_ns_consumed,             // Clang-specific.
     AT_ns_consumes_self,        // Clang-specific.
     AT_objc_gc,
+    AT_objc_lifetime,           // Clang-specific.
+    AT_objc_precise_lifetime,   // Clang-specific.
     AT_opencl_image_access,     // OpenCL-specific.
     AT_opencl_kernel_function,  // OpenCL-specific.
     AT_overloadable,       // Clang-specific.

+ 13 - 3
include/clang/Sema/DeclSpec.h

@@ -40,6 +40,7 @@ namespace clang {
   class NamespaceDecl;
   class NestedNameSpecifier;
   class NestedNameSpecifierLoc;
+  class ObjCDeclSpec;
   class Preprocessor;
   class Declarator;
   struct TemplateIdAnnotation;
@@ -344,6 +345,8 @@ private:
   void SaveWrittenBuiltinSpecs();
   void SaveStorageSpecifierAsWritten();
 
+  ObjCDeclSpec *ObjCQualifiers;
+
   static bool isTypeRep(TST T) {
     return (T == TST_typename || T == TST_typeofType ||
             T == TST_underlyingType);
@@ -383,7 +386,8 @@ public:
       ProtocolQualifiers(0),
       NumProtocolQualifiers(0),
       ProtocolLocs(0),
-      writtenBS() {
+      writtenBS(),
+      ObjCQualifiers(0) {
   }
   ~DeclSpec() {
     delete [] ProtocolQualifiers;
@@ -653,6 +657,9 @@ public:
     return writtenBS;
   }
 
+  ObjCDeclSpec *getObjCQualifiers() const { return ObjCQualifiers; }
+  void setObjCQualifiers(ObjCDeclSpec *quals) { ObjCQualifiers = quals; }
+
   /// isMissingDeclaratorOk - This checks if this DeclSpec can stand alone,
   /// without a Declarator. Only tag declspecs can stand alone.
   bool isMissingDeclaratorOk();
@@ -689,7 +696,10 @@ public:
     DQ_PR_copy = 0x20,
     DQ_PR_nonatomic = 0x40,
     DQ_PR_setter = 0x80,
-    DQ_PR_atomic = 0x100
+    DQ_PR_atomic = 0x100,
+    DQ_PR_weak =   0x200,
+    DQ_PR_strong = 0x400,
+    DQ_PR_unsafe_unretained = 0x800
   };
 
 
@@ -723,7 +733,7 @@ private:
   ObjCDeclQualifier objcDeclQualifier : 6;
 
   // NOTE: VC++ treats enums as signed, avoid using ObjCPropertyAttributeKind
-  unsigned PropertyAttributes : 9;
+  unsigned PropertyAttributes : 12;
   IdentifierInfo *GetterName;    // getter name of NULL if no getter
   IdentifierInfo *SetterName;    // setter name of NULL if no setter
 };

+ 40 - 1
include/clang/Sema/DelayedDiagnostic.h

@@ -112,7 +112,7 @@ private:
 /// the complete parsing of the current declaration.
 class DelayedDiagnostic {
 public:
-  enum DDKind { Deprecation, Access };
+  enum DDKind { Deprecation, Access, ForbiddenType };
 
   unsigned char Kind; // actually a DDKind
   bool Triggered;
@@ -135,6 +135,20 @@ public:
     return DD;
   }
 
+  static DelayedDiagnostic makeForbiddenType(SourceLocation loc,
+                                             unsigned diagnostic,
+                                             QualType type,
+                                             unsigned argument) {
+    DelayedDiagnostic DD;
+    DD.Kind = ForbiddenType;
+    DD.Triggered = false;
+    DD.Loc = loc;
+    DD.ForbiddenTypeData.Diagnostic = diagnostic;
+    DD.ForbiddenTypeData.OperandType = type.getAsOpaquePtr();
+    DD.ForbiddenTypeData.Argument = argument;
+    return DD;
+  }
+
   AccessedEntity &getAccessData() {
     assert(Kind == Access && "Not an access diagnostic.");
     return *reinterpret_cast<AccessedEntity*>(AccessData);
@@ -155,6 +169,25 @@ public:
                            DeprecationData.MessageLen);
   }
 
+  /// The diagnostic ID to emit.  Used like so:
+  ///   Diag(diag.Loc, diag.getForbiddenTypeDiagnostic())
+  ///     << diag.getForbiddenTypeOperand()
+  ///     << diag.getForbiddenTypeArgument();
+  unsigned getForbiddenTypeDiagnostic() const {
+    assert(Kind == ForbiddenType && "not a forbidden-type diagnostic");
+    return ForbiddenTypeData.Diagnostic;
+  }
+
+  unsigned getForbiddenTypeArgument() const {
+    assert(Kind == ForbiddenType && "not a forbidden-type diagnostic");
+    return ForbiddenTypeData.Argument;
+  }
+
+  QualType getForbiddenTypeOperand() const {
+    assert(Kind == ForbiddenType && "not a forbidden-type diagnostic");
+    return QualType::getFromOpaquePtr(ForbiddenTypeData.OperandType);
+  }
+
 private:
   union {
     /// Deprecation.
@@ -164,6 +197,12 @@ private:
       size_t MessageLen;
     } DeprecationData;
 
+    struct {
+      unsigned Diagnostic;
+      unsigned Argument;
+      void *OperandType;
+    } ForbiddenTypeData;
+
     /// Access control.
     char AccessData[sizeof(AccessedEntity)];
   };

+ 78 - 23
include/clang/Sema/Initialization.h

@@ -86,9 +86,13 @@ private:
   QualType Type;
   
   union {
-    /// \brief When Kind == EK_Variable, EK_Parameter, or EK_Member, 
-    /// the VarDecl, ParmVarDecl, or FieldDecl, respectively.
+    /// \brief When Kind == EK_Variable or EK_Member, the VarDecl or
+    /// FieldDecl, respectively.
     DeclaratorDecl *VariableOrMember;
+
+    /// \brief When Kind == EK_Parameter, the ParmVarDecl, with the
+    /// low bit indicating whether the parameter is "consumed".
+    uintptr_t Parameter;
     
     /// \brief When Kind == EK_Temporary, the type source information for
     /// the temporary.
@@ -123,11 +127,6 @@ private:
     : Kind(EK_Variable), Parent(0), Type(Var->getType()),
       VariableOrMember(Var) { }
   
-  /// \brief Create the initialization entity for a parameter.
-  InitializedEntity(ParmVarDecl *Parm)
-    : Kind(EK_Parameter), Parent(0), Type(Parm->getType().getUnqualifiedType()),
-      VariableOrMember(Parm) { }
-  
   /// \brief Create the initialization entity for the result of a
   /// function, throwing an object, performing an explicit cast, or
   /// initializing a parameter for which there is no declaration.
@@ -157,20 +156,28 @@ public:
   /// \brief Create the initialization entity for a parameter.
   static InitializedEntity InitializeParameter(ASTContext &Context,
                                                ParmVarDecl *Parm) {
-    InitializedEntity Res(Parm);
-    Res.Type = Context.getVariableArrayDecayedType(Res.Type);
-    return Res;
+    bool Consumed = (Context.getLangOptions().ObjCAutoRefCount &&
+                     Parm->hasAttr<NSConsumedAttr>());
+
+    InitializedEntity Entity;
+    Entity.Kind = EK_Parameter;
+    Entity.Type = Context.getVariableArrayDecayedType(
+                                       Parm->getType().getUnqualifiedType());
+    Entity.Parent = 0;
+    Entity.Parameter = (Consumed | reinterpret_cast<uintptr_t>(Parm));
+    return Entity;
   }
 
   /// \brief Create the initialization entity for a parameter that is
   /// only known by its type.
   static InitializedEntity InitializeParameter(ASTContext &Context,
-                                               QualType Type) {
+                                               QualType Type,
+                                               bool Consumed) {
     InitializedEntity Entity;
     Entity.Kind = EK_Parameter;
     Entity.Type = Context.getVariableArrayDecayedType(Type);
     Entity.Parent = 0;
-    Entity.VariableOrMember = 0;
+    Entity.Parameter = (Consumed);
     return Entity;
   }
 
@@ -268,6 +275,13 @@ public:
   /// \brief Determine whether this initialization allows the named return 
   /// value optimization, which also applies to thrown objects.
   bool allowsNRVO() const;
+
+  /// \brief Determine whether this initialization consumes the
+  /// parameter.
+  bool isParameterConsumed() const {
+    assert(getKind() == EK_Parameter && "Not a parameter");
+    return (Parameter & 1);
+  }
                                   
   /// \brief Retrieve the base specifier.
   CXXBaseSpecifier *getBaseSpecifier() const {
@@ -287,7 +301,7 @@ public:
     assert(getKind() == EK_Result && "No 'return' location!");
     return SourceLocation::getFromRawEncoding(LocAndNRVO.Location);
   }
-  
+
   /// \brief Determine the location of the 'throw' keyword when initializing
   /// an exception object.
   SourceLocation getThrowLoc() const {
@@ -325,8 +339,10 @@ private:
     SIK_Value = IK_Value,     ///< Value initialization
     SIK_ImplicitValue,        ///< Implicit value initialization
     SIK_DirectCast,  ///< Direct initialization due to a cast
-    /// \brief Direct initialization due to a C-style or functional cast.
-    SIK_DirectCStyleOrFunctionalCast
+    /// \brief Direct initialization due to a C-style cast.
+    SIK_DirectCStyleCast,
+    /// \brief Direct initialization due to a functional-style cast.
+    SIK_DirectFunctionalCast
   };
   
   /// \brief The kind of initialization being performed.
@@ -352,15 +368,29 @@ public:
     return InitializationKind(SIK_Direct, InitLoc, LParenLoc, RParenLoc);
   }
 
-  /// \brief Create a direct initialization due to a cast.
-  static InitializationKind CreateCast(SourceRange TypeRange,
-                                       bool IsCStyleCast) {
-    return InitializationKind(IsCStyleCast? SIK_DirectCStyleOrFunctionalCast
-                                          : SIK_DirectCast,
+  /// \brief Create a direct initialization due to a cast that isn't a C-style 
+  /// or functional cast.
+  static InitializationKind CreateCast(SourceRange TypeRange) {
+    return InitializationKind(SIK_DirectCast,
                               TypeRange.getBegin(), TypeRange.getBegin(), 
                               TypeRange.getEnd());
   }
   
+  /// \brief Create a direct initialization for a C-style cast.
+  static InitializationKind CreateCStyleCast(SourceLocation StartLoc,
+                                             SourceRange TypeRange) {
+    return InitializationKind(SIK_DirectCStyleCast,
+                              StartLoc, TypeRange.getBegin(), 
+                              TypeRange.getEnd());
+  }
+
+  /// \brief Create a direct initialization for a functional cast.
+  static InitializationKind CreateFunctionalCast(SourceRange TypeRange) {
+    return InitializationKind(SIK_DirectFunctionalCast,
+                              TypeRange.getBegin(), TypeRange.getBegin(), 
+                              TypeRange.getEnd());
+  }
+
   /// \brief Create a copy initialization.
   static InitializationKind CreateCopy(SourceLocation InitLoc,
                                        SourceLocation EqualLoc) {
@@ -393,12 +423,24 @@ public:
   
   /// \brief Determine whether this initialization is an explicit cast.
   bool isExplicitCast() const {
-    return Kind == SIK_DirectCast || Kind == SIK_DirectCStyleOrFunctionalCast;
+    return Kind == SIK_DirectCast || 
+           Kind == SIK_DirectCStyleCast ||
+           Kind == SIK_DirectFunctionalCast;
   }
   
   /// \brief Determine whether this initialization is a C-style cast.
   bool isCStyleOrFunctionalCast() const { 
-    return Kind == SIK_DirectCStyleOrFunctionalCast; 
+    return Kind == SIK_DirectCStyleCast || Kind == SIK_DirectFunctionalCast; 
+  }
+
+  /// brief Determine whether this is a C-style cast.
+  bool isCStyleCast() const {
+    return Kind == SIK_DirectCStyleCast;
+  }
+
+  /// brief Determine whether this is a functional-style cast.
+  bool isFunctionalCast() const {
+    return Kind == SIK_DirectFunctionalCast;
   }
 
   /// \brief Determine whether this initialization is an implicit
@@ -500,7 +542,13 @@ public:
     SK_ObjCObjectConversion,
     /// \brief Array initialization (from an array rvalue).
     /// This is a GNU C extension.
-    SK_ArrayInit
+    SK_ArrayInit,
+    /// \brief Pass an object by indirect copy-and-restore.
+    SK_PassByIndirectCopyRestore,
+    /// \brief Pass an object by indirect restore.
+    SK_PassByIndirectRestore,
+    /// \brief Produce an Objective-C object pointer.
+    SK_ProduceObjCObject
   };
   
   /// \brief A single step in the initialization sequence.
@@ -774,6 +822,13 @@ public:
   /// \brief Add an array initialization step.
   void AddArrayInitStep(QualType T);
 
+  /// \brief Add a step to pass an object by indirect copy-restore.
+  void AddPassByIndirectCopyRestoreStep(QualType T, bool shouldCopy);
+
+  /// \brief Add a step to "produce" an Objective-C object (by
+  /// retaining it).
+  void AddProduceObjCObjectStep(QualType T);
+
   /// \brief Note that this initialization sequence failed.
   void SetFailed(FailureKind Failure) {
     SequenceKind = FailedSequence;

+ 14 - 4
include/clang/Sema/Overload.h

@@ -77,6 +77,7 @@ namespace clang {
     ICK_Complex_Real,          ///< Complex-real conversions (C99 6.3.1.7)
     ICK_Block_Pointer_Conversion,    ///< Block Pointer conversions 
     ICK_TransparentUnionConversion, /// Transparent Union Conversions
+    ICK_Writeback_Conversion,  ///< Objective-C ARC writeback conversion
     ICK_Num_Conversion_Kinds   ///< The number of conversion kinds
   };
 
@@ -100,10 +101,11 @@ namespace clang {
   /// 13.3.3.1.1) and are listed such that better conversion ranks
   /// have smaller values.
   enum ImplicitConversionRank {
-    ICR_Exact_Match = 0,        ///< Exact Match
-    ICR_Promotion,              ///< Promotion
-    ICR_Conversion,             ///< Conversion
-    ICR_Complex_Real_Conversion ///< Complex <-> Real conversion
+    ICR_Exact_Match = 0,         ///< Exact Match
+    ICR_Promotion,               ///< Promotion
+    ICR_Conversion,              ///< Conversion
+    ICR_Complex_Real_Conversion, ///< Complex <-> Real conversion
+    ICR_Writeback_Conversion     ///< ObjC ARC writeback conversion
   };
 
   ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind);
@@ -137,6 +139,10 @@ namespace clang {
     /// (C++ 4.2p2).
     unsigned DeprecatedStringLiteralToCharPtr : 1;
 
+    /// \brief Whether the qualification conversion involves a change in the
+    /// Objective-C lifetime (for automatic reference counting).
+    unsigned QualificationIncludesObjCLifetime : 1;
+    
     /// IncompatibleObjC - Whether this is an Objective-C conversion
     /// that we should warn about (if we actually use it).
     unsigned IncompatibleObjC : 1;
@@ -163,6 +169,10 @@ namespace clang {
     /// non-static member function without a ref-qualifier.
     unsigned BindsImplicitObjectArgumentWithoutRefQualifier : 1;
     
+    /// \brief Whether this binds a reference to an object with a different
+    /// Objective-C lifetime qualifier.
+    unsigned ObjCLifetimeConversionBinding : 1;
+    
     /// FromType - The type that this conversion is converting
     /// from. This is an opaque pointer that can be translated into a
     /// QualType.

+ 106 - 22
include/clang/Sema/Sema.h

@@ -108,6 +108,7 @@ namespace clang {
   class ObjCInterfaceDecl;
   class ObjCIvarDecl;
   template <class T> class ObjCList;
+  class ObjCMessageExpr;
   class ObjCMethodDecl;
   class ObjCPropertyDecl;
   class ObjCProtocolDecl;
@@ -247,6 +248,10 @@ public:
   /// VisContext - Manages the stack for #pragma GCC visibility.
   void *VisContext; // Really a "PragmaVisStack*"
 
+  /// ExprNeedsCleanups - True if the current evaluation context
+  /// requires cleanups to be run at its conclusion.
+  bool ExprNeedsCleanups;
+
   /// \brief Stack containing information about each of the nested
   /// function, block, and method scopes that are currently active.
   ///
@@ -555,6 +560,9 @@ public:
     /// \brief The expression evaluation context.
     ExpressionEvaluationContext Context;
 
+    /// \brief Whether the enclosing context needed a cleanup.
+    bool ParentNeedsCleanups;
+
     /// \brief The number of temporaries that were active when we
     /// entered this expression evaluation context.
     unsigned NumTemporaries;
@@ -573,8 +581,10 @@ public:
     PotentiallyEmittedDiagnostics *PotentiallyDiagnosed;
 
     ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
-                                      unsigned NumTemporaries)
-      : Context(Context), NumTemporaries(NumTemporaries),
+                                      unsigned NumTemporaries,
+                                      bool ParentNeedsCleanups)
+      : Context(Context), ParentNeedsCleanups(ParentNeedsCleanups),
+        NumTemporaries(NumTemporaries),
         PotentiallyReferenced(0), PotentiallyDiagnosed(0) { }
 
     void addReferencedDecl(SourceLocation Loc, Decl *Decl) {
@@ -766,7 +776,7 @@ public:
     return FunctionScopes.back();
   }
 
-  bool hasAnyErrorsInThisFunction() const;
+  bool hasAnyUnrecoverableErrorsInThisFunction() const;
 
   /// \brief Retrieve the current block, if any.
   sema::BlockScopeInfo *getCurBlock();
@@ -838,7 +848,7 @@ public:
       const FunctionProtoType *Source, SourceLocation SourceLoc);
 
   TypeResult ActOnTypeName(Scope *S, Declarator &D);
-
+  
   bool RequireCompleteType(SourceLocation Loc, QualType T,
                            const PartialDiagnostic &PD,
                            std::pair<SourceLocation, PartialDiagnostic> Note);
@@ -1305,13 +1315,13 @@ public:
                              bool IsForUsingDecl);
   bool IsOverload(FunctionDecl *New, FunctionDecl *Old, bool IsForUsingDecl);
 
-  bool TryImplicitConversion(InitializationSequence &Sequence,
-                             const InitializedEntity &Entity,
-                             Expr *From,
-                             bool SuppressUserConversions,
-                             bool AllowExplicit,
-                             bool InOverloadResolution,
-                             bool CStyle);
+  ImplicitConversionSequence
+  TryImplicitConversion(Expr *From, QualType ToType,
+                        bool SuppressUserConversions,
+                        bool AllowExplicit,
+                        bool InOverloadResolution,
+                        bool CStyle,
+                        bool AllowObjCWritebackConversion);
 
   bool IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType);
   bool IsFloatingPointPromotion(QualType FromType, QualType ToType);
@@ -1321,6 +1331,8 @@ public:
                            QualType& ConvertedType, bool &IncompatibleObjC);
   bool isObjCPointerConversion(QualType FromType, QualType ToType,
                                QualType& ConvertedType, bool &IncompatibleObjC);
+  bool isObjCWritebackConversion(QualType FromType, QualType ToType,
+                                 QualType &ConvertedType);
   bool IsBlockPointerConversion(QualType FromType, QualType ToType,
                                 QualType& ConvertedType);
   bool FunctionArgTypesAreEqual(const FunctionProtoType *OldType, 
@@ -1338,7 +1350,7 @@ public:
                                     CXXCastPath &BasePath,
                                     bool IgnoreBaseAccess);
   bool IsQualificationConversion(QualType FromType, QualType ToType,
-                                 bool CStyle);
+                                 bool CStyle, bool &ObjCLifetimeConversion);
   bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType);
 
 
@@ -1853,14 +1865,20 @@ public:
   void AtomicPropertySetterGetterRules(ObjCImplDecl* IMPDecl,
                                        ObjCContainerDecl* IDecl);
 
+  void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D);
+
   void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID);
 
+  enum MethodMatchStrategy {
+    MMS_loose,
+    MMS_strict
+  };
+
   /// MatchTwoMethodDeclarations - Checks if two methods' type match and returns
   /// true, or false, accordingly.
   bool MatchTwoMethodDeclarations(const ObjCMethodDecl *Method,
                                   const ObjCMethodDecl *PrevMethod,
-                                  bool matchBasedOnSizeAndAlignment = false,
-                                  bool matchBasedOnStrictEqulity = false);
+                                  MethodMatchStrategy strategy = MMS_strict);
 
   /// MatchAllMethodDeclarations - Check methods declaraed in interface or
   /// or protocol against those declared in their implementations.
@@ -2073,10 +2091,13 @@ public:
                                          Expr *SynchExpr,
                                          Stmt *SynchBody);
 
+  StmtResult ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body);
+
   VarDecl *BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo,
                                      SourceLocation StartLoc,
                                      SourceLocation IdLoc,
                                      IdentifierInfo *Id);
+
   Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D);
 
   StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
@@ -2130,6 +2151,9 @@ public:
 
   void HandleDelayedDeprecationCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
 
+  bool makeUnavailableInSystemHeader(SourceLocation loc,
+                                     llvm::StringRef message);
+
   //===--------------------------------------------------------------------===//
   // Expression Parsing Callbacks: SemaExpr.cpp.
 
@@ -2146,6 +2170,8 @@ public:
 
   void PopExpressionEvaluationContext();
 
+  void DiscardCleanupsInEvaluationContext();
+
   void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
   void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);
   void MarkDeclarationsReferencedInExpr(Expr *E);
@@ -4982,6 +5008,15 @@ public:
                               IdentifierInfo *PropertyIvar,
                               SourceLocation PropertyIvarLoc);
 
+  enum ObjCSpecialMethodKind {
+    OSMK_None,
+    OSMK_Alloc,
+    OSMK_New,
+    OSMK_Copy,
+    OSMK_RetainingInit,
+    OSMK_NonRetainingInit
+  };
+
   struct ObjCArgInfo {
     IdentifierInfo *Name;
     SourceLocation NameLoc;
@@ -5020,6 +5055,8 @@ public:
                                               const ObjCObjectPointerType *OPT,
                                               bool IsInstance);
 
+  bool inferObjCARCLifetime(ValueDecl *decl);
+    
   ExprResult
   HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
                             Expr *BaseExpr,
@@ -5098,6 +5135,22 @@ public:
                                   SourceLocation RBracLoc,
                                   MultiExprArg Args);
 
+  ExprResult BuildObjCBridgedCast(SourceLocation LParenLoc,
+                                  ObjCBridgeCastKind Kind,
+                                  SourceLocation BridgeKeywordLoc,
+                                  TypeSourceInfo *TSInfo,
+                                  Expr *SubExpr);
+  
+  ExprResult ActOnObjCBridgedCast(Scope *S,
+                                  SourceLocation LParenLoc,
+                                  ObjCBridgeCastKind Kind,
+                                  SourceLocation BridgeKeywordLoc,
+                                  ParsedType Type,
+                                  SourceLocation RParenLoc,
+                                  Expr *SubExpr);
+  
+  bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall);
+  
   /// \brief Check whether the given new method is a valid override of the
   /// given overridden method, and set any properties that should be inherited.
   ///
@@ -5105,7 +5158,7 @@ public:
   bool CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, 
                                const ObjCMethodDecl *Overridden,
                                bool IsImplementation);
-    
+
   /// \brief Check whether the given method overrides any methods in its class,
   /// calling \c CheckObjCMethodOverride for each overridden method.
   bool CheckObjCMethodOverrides(ObjCMethodDecl *NewMethod, DeclContext *DC);
@@ -5208,12 +5261,26 @@ public:
   /// from the inner expression.
   ExprValueKind CastCategory(Expr *E);
 
+  /// \brief The kind of conversion being performed.
+  enum CheckedConversionKind {
+    /// \brief An implicit conversion.
+    CCK_ImplicitConversion,
+    /// \brief A C-style cast.
+    CCK_CStyleCast,
+    /// \brief A functional-style cast.
+    CCK_FunctionalCast,
+    /// \brief A cast other than a C-style cast.
+    CCK_OtherCast
+  };
+
   /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit
   /// cast.  If there is already an implicit cast, merge into the existing one.
   /// If isLvalue, the result of the cast is an lvalue.
   ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK,
                                ExprValueKind VK = VK_RValue,
-                               const CXXCastPath *BasePath = 0);
+                               const CXXCastPath *BasePath = 0,
+                               CheckedConversionKind CCK 
+                                  = CCK_ImplicitConversion);
 
   /// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding
   /// to the conversion from scalar type ScalarTy to the Boolean type.
@@ -5393,11 +5460,12 @@ public:
   ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
                                        const ImplicitConversionSequence& ICS,
                                        AssignmentAction Action,
-                                       bool CStyle = false);
+                                       CheckedConversionKind CCK
+                                          = CCK_ImplicitConversion);
   ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
                                        const StandardConversionSequence& SCS,
                                        AssignmentAction Action,
-                                       bool CStyle);
+                                       CheckedConversionKind CCK);
 
   /// the following "Check" methods will return a valid/converted QualType
   /// or a null QualType (indicating an error diagnostic was issued).
@@ -5494,12 +5562,14 @@ public:
   ReferenceCompareResult CompareReferenceRelationship(SourceLocation Loc,
                                                       QualType T1, QualType T2,
                                                       bool &DerivedToBase,
-                                                      bool &ObjCConversion);
+                                                      bool &ObjCConversion,
+                                                bool &ObjCLifetimeConversion);
 
   /// CheckCastTypes - Check type constraints for casting between types under
   /// C semantics, or forward to CXXCheckCStyleCast in C++.
-  ExprResult CheckCastTypes(SourceRange TyRange, QualType CastTy, Expr *CastExpr,
-                            CastKind &Kind, ExprValueKind &VK, CXXCastPath &BasePath,
+  ExprResult CheckCastTypes(SourceLocation CastStartLoc, SourceRange TyRange, 
+                            QualType CastTy, Expr *CastExpr, CastKind &Kind, 
+                            ExprValueKind &VK, CXXCastPath &BasePath,
                             bool FunctionalStyle = false);
 
   ExprResult checkUnknownAnyCast(SourceRange TyRange, QualType castType,
@@ -5526,6 +5596,20 @@ public:
   ExprResult CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
                                 Expr *CastExpr, CastKind &Kind,
                                 CXXCastPath &BasePath, bool FunctionalStyle);
+  
+  /// \brief Checks for invalid conversions and casts between
+  /// retainable pointers and other pointer kinds.
+  void CheckObjCARCConversion(SourceRange castRange, QualType castType, 
+                              Expr *op, CheckedConversionKind CCK);
+
+  /// checkRetainCycles - Check whether an Objective-C message send
+  /// might create an obvious retain cycle.
+  void checkRetainCycles(ObjCMessageExpr *msg);
+  void checkRetainCycles(Expr *receiver, Expr *argument);
+
+  /// checkWeakUnsafeAssigns - Check whether +1 expr is being assigned
+  /// to weak/__unsafe_unretained.
+  void checkUnsafeAssigns(SourceLocation Loc, QualType LHS, Expr *RHS);
 
   /// CheckMessageArgumentTypes - Check types in an Obj-C message send.
   /// \param Method - May be null.
@@ -5544,7 +5628,7 @@ public:
   QualType getMessageSendResultType(QualType ReceiverType,
                                     ObjCMethodDecl *Method,
                                     bool isClassMessage, bool isSuperMessage);
-    
+
   /// \brief If the given expression involves a message send to a method
   /// with a related result type, emit a note describing what happened.
   void EmitRelatedResultTypeNote(const Expr *E);

+ 9 - 3
include/clang/Serialization/ASTBitCodes.h

@@ -922,6 +922,8 @@ namespace clang {
       EXPR_OBJC_MESSAGE_EXPR,
       /// \brief An ObjCIsa Expr record.
       EXPR_OBJC_ISA,
+      /// \breif An ObjCIndirectCopyRestoreExpr record.
+      EXPR_OBJC_INDIRECT_COPY_RESTORE,
 
       /// \brief An ObjCForCollectionStmt record.
       STMT_OBJC_FOR_COLLECTION,
@@ -935,6 +937,8 @@ namespace clang {
       STMT_OBJC_AT_SYNCHRONIZED,
       /// \brief An ObjCAtThrowStmt record.
       STMT_OBJC_AT_THROW,
+      /// \brief An ObjCAutoreleasePoolStmt record.
+      STMT_OBJC_AUTORELEASE_POOL,
 
       // C++
       
@@ -1002,11 +1006,13 @@ namespace clang {
       EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK,// SubstNonTypeTemplateParmPackExpr
 
       // CUDA
+      EXPR_CUDA_KERNEL_CALL,       // CUDAKernelCallExpr      
 
-      EXPR_CUDA_KERNEL_CALL,       // CUDAKernelCallExpr
-      
       // OpenCL
-      EXPR_ASTYPE // An AsTypeExpr record.
+      EXPR_ASTYPE,                 // AsTypeExpr
+      
+      // ARC
+      EXPR_OBJC_BRIDGED_CAST       // ObjCBridgedCastExpr
     };
 
     /// \brief The kinds of designators that can occur in a

+ 20 - 32
lib/AST/ASTContext.cpp

@@ -221,9 +221,9 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
   DependentTemplateSpecializationTypes(this_()),
   GlobalNestedNameSpecifier(0), IsInt128Installed(false),
   CFConstantStringTypeDecl(0), NSConstantStringTypeDecl(0),
-  ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), jmp_bufDecl(0),
-  sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0),
-  cudaConfigureCallDecl(0),
+  ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), 
+  jmp_bufDecl(0), sigjmp_bufDecl(0), BlockDescriptorType(0), 
+  BlockDescriptorExtendedType(0), cudaConfigureCallDecl(0),
   NullTypeSourceInfo(QualType()),
   SourceMgr(SM), LangOpts(LOpts), ABI(createCXXABI(t)),
   AddrSpaceMap(getAddressSpaceMap(t, LOpts)), Target(t),
@@ -2040,10 +2040,13 @@ ASTContext::getFunctionType(QualType ResultTy,
     assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP;
   }
 
-  // FunctionProtoType objects are allocated with extra bytes after them
-  // for two variable size arrays (for parameter and exception types) at the
-  // end of them. Instead of the exception types, there could be a noexcept
-  // expression and a context pointer.
+  // FunctionProtoType objects are allocated with extra bytes after
+  // them for three variable size arrays at the end:
+  //  - parameter types
+  //  - exception types
+  //  - consumed-arguments flags
+  // Instead of the exception types, there could be a noexcept
+  // expression.
   size_t Size = sizeof(FunctionProtoType) +
                 NumArgs * sizeof(QualType);
   if (EPI.ExceptionSpecType == EST_Dynamic)
@@ -2051,6 +2054,9 @@ ASTContext::getFunctionType(QualType ResultTy,
   else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
     Size += sizeof(Expr*);
   }
+  if (EPI.ConsumedArguments)
+    Size += NumArgs * sizeof(bool);
+
   FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment);
   FunctionProtoType::ExtProtoInfo newEPI = EPI;
   newEPI.ExtInfo = EPI.ExtInfo.withCallingConv(CallConv);
@@ -2925,7 +2931,6 @@ CanQualType ASTContext::getCanonicalParamType(QualType T) const {
   return CanQualType::CreateUnsafe(Result);
 }
 
-
 QualType ASTContext::getUnqualifiedArrayType(QualType type,
                                              Qualifiers &quals) {
   SplitQualType splitType = type.getSplitUnqualifiedType();
@@ -3725,11 +3730,7 @@ void ASTContext::setBlockDescriptorExtendedType(QualType T) {
 }
 
 bool ASTContext::BlockRequiresCopying(QualType Ty) const {
-  if (Ty->isBlockPointerType())
-    return true;
-  if (isObjCNSObjectType(Ty))
-    return true;
-  if (Ty->isObjCObjectPointerType())
+  if (Ty->isObjCRetainableType())
     return true;
   if (getLangOptions().CPlusPlus) {
     if (const RecordType *RT = Ty->getAs<RecordType>()) {
@@ -4826,20 +4827,6 @@ CanQualType ASTContext::getFromTargetType(unsigned Type) const {
 //                        Type Predicates.
 //===----------------------------------------------------------------------===//
 
-/// isObjCNSObjectType - Return true if this is an NSObject object using
-/// NSObject attribute on a c-style pointer type.
-/// FIXME - Make it work directly on types.
-/// FIXME: Move to Type.
-///
-bool ASTContext::isObjCNSObjectType(QualType Ty) const {
-  if (const TypedefType *TDT = dyn_cast<TypedefType>(Ty)) {
-    if (TypedefNameDecl *TD = TDT->getDecl())
-      if (TD->getAttr<ObjCNSObjectAttr>())
-        return true;
-  }
-  return false;
-}
-
 /// getObjCGCAttr - Returns one of GCNone, Weak or Strong objc's
 /// garbage collection attribute.
 ///
@@ -5452,6 +5439,9 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
   if (lbaseInfo.getRegParm() != rbaseInfo.getRegParm())
     return QualType();
 
+  if (lbaseInfo.getProducesResult() != rbaseInfo.getProducesResult())
+    return QualType();
+
   // It's noreturn if either type is.
   // FIXME: some uses, e.g. conditional exprs, really want this to be 'both'.
   bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn();
@@ -5460,10 +5450,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs,
   if (NoReturn != rbaseInfo.getNoReturn())
     allRTypes = false;
 
-  FunctionType::ExtInfo einfo(NoReturn,
-                              lbaseInfo.getHasRegParm(),
-                              lbaseInfo.getRegParm(),
-                              lbaseInfo.getCC());
+  FunctionType::ExtInfo einfo = lbaseInfo.withNoReturn(NoReturn);
 
   if (lproto && rproto) { // two C99 style function prototypes
     assert(!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec() &&
@@ -5584,7 +5571,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
     // If any of these qualifiers are different, we have a type
     // mismatch.
     if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() ||
-        LQuals.getAddressSpace() != RQuals.getAddressSpace())
+        LQuals.getAddressSpace() != RQuals.getAddressSpace() ||
+        LQuals.getObjCLifetime() != RQuals.getObjCLifetime())
       return QualType();
 
     // Exactly one GC qualifier difference is allowed: __strong is

+ 35 - 1
lib/AST/DeclCXX.cpp

@@ -228,6 +228,11 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
     if (!BaseClassDecl->hasTrivialDestructor())
       data().HasTrivialDestructor = false;
     
+    // A class has an Objective-C object member if... or any of its bases
+    // has an Objective-C object member.
+    if (BaseClassDecl->hasObjectMember())
+      setHasObjectMember(true);
+
     // Keep track of the presence of mutable fields.
     if (BaseClassDecl->hasMutableFields())
       data().HasMutableFields = true;
@@ -698,10 +703,23 @@ NotASpecialMember:;
     //   A POD struct is a class that is both a trivial class and a 
     //   standard-layout class, and has no non-static data members of type 
     //   non-POD struct, non-POD union (or array of such types).
+    //
+    // Automatic Reference Counting: the presence of a member of Objective-C pointer type
+    // that does not explicitly have no lifetime makes the class a non-POD.
+    // However, we delay setting PlainOldData to false in this case so that
+    // Sema has a chance to diagnostic causes where the same class will be
+    // non-POD with Automatic Reference Counting but a POD without Instant Objects.
+    // In this case, the class will become a non-POD class when we complete
+    // the definition.
     ASTContext &Context = getASTContext();
     QualType T = Context.getBaseElementType(Field->getType());
-    if (!T->isPODType())
+    if (T->isObjCRetainableType() || T.isObjCGCStrong()) {
+      if (!Context.getLangOptions().ObjCAutoRefCount ||
+          T.getObjCLifetime() != Qualifiers::OCL_ExplicitNone)
+        setHasObjectMember(true);
+    } else if (!T.isPODType(Context))
       data().PlainOldData = false;
+    
     if (T->isReferenceType()) {
       data().HasTrivialDefaultConstructor = false;
 
@@ -768,6 +786,8 @@ NotASpecialMember:;
 
         if (!FieldRec->hasTrivialDestructor())
           data().HasTrivialDestructor = false;
+        if (FieldRec->hasObjectMember())
+          setHasObjectMember(true);
 
         // C++0x [class]p7:
         //   A standard-layout class is a class that:
@@ -1078,6 +1098,20 @@ void CXXRecordDecl::completeDefinition() {
 void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
   RecordDecl::completeDefinition();
   
+  if (hasObjectMember() && getASTContext().getLangOptions().ObjCAutoRefCount) {
+    // Objective-C Automatic Reference Counting:
+    //   If a class has a non-static data member of Objective-C pointer
+    //   type (or array thereof), it is a non-POD type and its
+    //   default constructor (if any), copy constructor, copy assignment
+    //   operator, and destructor are non-trivial.
+    struct DefinitionData &Data = data();
+    Data.PlainOldData = false;
+    Data.HasTrivialDefaultConstructor = false;
+    Data.HasTrivialCopyConstructor = false;
+    Data.HasTrivialCopyAssignment = false;
+    Data.HasTrivialDestructor = false;
+  }
+  
   // If the class may be abstract (but hasn't been marked as such), check for
   // any pure final overriders.
   if (mayBeAbstract()) {

+ 22 - 2
lib/AST/DeclObjC.cpp

@@ -474,8 +474,28 @@ void ObjCMethodDecl::createImplicitParams(ASTContext &Context,
   } else // we have a factory method.
     selfTy = Context.getObjCClassType();
 
-  setSelfDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(),
-                                        &Context.Idents.get("self"), selfTy));
+  bool selfIsConsumed = false;
+  if (isInstanceMethod() && Context.getLangOptions().ObjCAutoRefCount) {
+    selfIsConsumed = hasAttr<NSConsumesSelfAttr>();
+
+    // 'self' is always __strong, although as a special case we don't
+    // actually retain it except in init methods.
+    Qualifiers qs;
+    qs.setObjCLifetime(Qualifiers::OCL_Strong);
+    selfTy = Context.getQualifiedType(selfTy, qs);
+
+    // In addition, 'self' is const unless this is an init method.
+    if (getMethodFamily() != OMF_init)
+      selfTy = selfTy.withConst();
+  }
+
+  ImplicitParamDecl *self
+    = ImplicitParamDecl::Create(Context, this, SourceLocation(),
+                                &Context.Idents.get("self"), selfTy);
+  setSelfDecl(self);
+
+  if (selfIsConsumed)
+    self->addAttr(new (Context) NSConsumedAttr(SourceLocation(), Context));
 
   setCmdDecl(ImplicitParamDecl::Create(Context, this, SourceLocation(),
                                        &Context.Idents.get("_cmd"),

+ 5 - 0
lib/AST/DeclPrinter.cpp

@@ -933,6 +933,11 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
     first = false;
   }
 
+  if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_strong) {
+    Out << (first ? ' ' : ',') << "strong";
+    first = false;
+  }
+
   if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) {
     Out << (first ? ' ' : ',') << "copy";
     first = false;

+ 33 - 3
lib/AST/Expr.cpp

@@ -1045,6 +1045,10 @@ const char *CastExpr::getCastKindName() const {
     return "IntegralComplexCast";
   case CK_IntegralComplexToFloatingComplex:
     return "IntegralComplexToFloatingComplex";
+  case CK_ObjCConsumeObject:
+    return "ObjCConsumeObject";
+  case CK_ObjCProduceObject:
+    return "ObjCProduceObject";
   }
 
   llvm_unreachable("Unhandled cast kind!");
@@ -1490,6 +1494,17 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
 
   case ObjCMessageExprClass: {
     const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(this);
+    if (Ctx.getLangOptions().ObjCAutoRefCount &&
+        ME->isInstanceMessage() &&
+        !ME->getType()->isVoidType() &&
+        ME->getSelector().getIdentifierInfoForSlot(0) &&
+        ME->getSelector().getIdentifierInfoForSlot(0)
+                                               ->getName().startswith("init")) {
+      Loc = getExprLoc();
+      R1 = ME->getSourceRange();
+      return true;
+    }
+
     const ObjCMethodDecl *MD = ME->getMethodDecl();
     if (MD && MD->getAttr<WarnUnusedResultAttr>()) {
       Loc = getExprLoc();
@@ -2519,7 +2534,7 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
          /*TypeDependent=*/false, /*ValueDependent=*/false,
          /*ContainsUnexpandedParameterPack=*/false),
     NumArgs(NumArgs), Kind(IsInstanceSuper? SuperInstance : SuperClass),
-    HasMethod(Method != 0), SuperLoc(SuperLoc),
+    HasMethod(Method != 0), IsDelegateInitCall(false), SuperLoc(SuperLoc),
     SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
                                                        : Sel.getAsOpaquePtr())),
     SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) 
@@ -2540,7 +2555,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
                                  SourceLocation RBracLoc)
   : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, T->isDependentType(),
          T->isDependentType(), T->containsUnexpandedParameterPack()),
-    NumArgs(NumArgs), Kind(Class), HasMethod(Method != 0),
+    NumArgs(NumArgs), Kind(Class),
+    HasMethod(Method != 0), IsDelegateInitCall(false),
     SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
                                                        : Sel.getAsOpaquePtr())),
     SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) 
@@ -2571,7 +2587,8 @@ ObjCMessageExpr::ObjCMessageExpr(QualType T,
   : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, Receiver->isTypeDependent(),
          Receiver->isTypeDependent(),
          Receiver->containsUnexpandedParameterPack()),
-    NumArgs(NumArgs), Kind(Instance), HasMethod(Method != 0),
+    NumArgs(NumArgs), Kind(Instance),
+    HasMethod(Method != 0), IsDelegateInitCall(false),
     SelectorOrMethod(reinterpret_cast<uintptr_t>(Method? Method
                                                        : Sel.getAsOpaquePtr())),
     SelectorLoc(SelLoc), LBracLoc(LBracLoc), RBracLoc(RBracLoc) 
@@ -2702,6 +2719,19 @@ ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const {
   return 0;
 }
 
+llvm::StringRef ObjCBridgedCastExpr::getBridgeKindName() const {
+  switch (getBridgeKind()) {
+  case OBC_Bridge:
+    return "__bridge";
+  case OBC_BridgeTransfer:
+    return "__bridge_transfer";
+  case OBC_BridgeRetained:
+    return "__bridge_retained";
+  }
+  
+  return "__bridge";
+}
+
 bool ChooseExpr::isConditionTrue(const ASTContext &C) const {
   return getCond()->EvaluateAsInt(C) != 0;
 }

+ 2 - 0
lib/AST/ExprClassification.cpp

@@ -162,6 +162,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
   case Expr::SizeOfPackExprClass:
   case Expr::SubstNonTypeTemplateParmPackExprClass:
   case Expr::AsTypeExprClass:
+  case Expr::ObjCIndirectCopyRestoreExprClass:
     return Cl::CL_PRValue;
 
     // Next come the complicated cases.
@@ -289,6 +290,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
   case Expr::CXXDynamicCastExprClass:
   case Expr::CXXReinterpretCastExprClass:
   case Expr::CXXConstCastExprClass:
+  case Expr::ObjCBridgedCastExprClass:
     // Only in C++ can casts be interesting at all.
     if (!Lang.CPlusPlus) return Cl::CL_PRValue;
     return ClassifyUnnamed(Ctx, cast<ExplicitCastExpr>(E)->getTypeAsWritten());

+ 18 - 1
lib/AST/ExprConstant.cpp

@@ -282,6 +282,17 @@ public:
       return true;
     return false;
   }
+  bool VisitObjCIvarRefExpr(const ObjCIvarRefExpr *E) {
+    if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified())
+      return true;
+    return false;
+  }
+  bool VisitBlockDeclRefExpr (const BlockDeclRefExpr *E) {
+    if (Info.Ctx.getCanonicalType(E->getType()).isVolatileQualified())
+      return true;
+    return false;
+  }
+
   // We don't want to evaluate BlockExprs multiple times, as they generate
   // a ton of code.
   bool VisitBlockExpr(const BlockExpr *E) { return true; }
@@ -1797,6 +1808,8 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
   case CK_GetObjCProperty:
   case CK_LValueBitCast:
   case CK_UserDefinedConversion:
+  case CK_ObjCProduceObject:
+  case CK_ObjCConsumeObject:
     return false;
 
   case CK_LValueToRValue:
@@ -2301,6 +2314,8 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
   case CK_FloatingComplexToBoolean:
   case CK_IntegralComplexToReal:
   case CK_IntegralComplexToBoolean:
+  case CK_ObjCProduceObject:
+  case CK_ObjCConsumeObject:
     llvm_unreachable("invalid cast kind for complex value");
 
   case CK_LValueToRValue:
@@ -2771,6 +2786,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
   case Expr::PackExpansionExprClass:
   case Expr::SubstNonTypeTemplateParmPackExprClass:
   case Expr::AsTypeExprClass:
+  case Expr::ObjCIndirectCopyRestoreExprClass:
     return ICEDiag(2, E->getLocStart());
 
   case Expr::SizeOfPackExprClass:
@@ -2995,7 +3011,8 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
   case Expr::CXXFunctionalCastExprClass:
   case Expr::CXXStaticCastExprClass:
   case Expr::CXXReinterpretCastExprClass:
-  case Expr::CXXConstCastExprClass: {
+  case Expr::CXXConstCastExprClass: 
+  case Expr::ObjCBridgedCastExprClass: {
     const Expr *SubExpr = cast<CastExpr>(E)->getSubExpr();
     if (SubExpr->getType()->isIntegralOrEnumerationType())
       return CheckICE(SubExpr, Ctx);

+ 40 - 2
lib/AST/ItaniumMangle.cpp

@@ -21,6 +21,7 @@
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/ABI.h"
 #include "clang/Basic/SourceManager.h"
@@ -1464,7 +1465,35 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) {
     Out << 'U' << ASString.size() << ASString;
   }
   
-  // FIXME: For now, just drop all extension qualifiers on the floor.
+  llvm::StringRef LifetimeName;
+  switch (Quals.getObjCLifetime()) {
+  // Objective-C ARC Extension:
+  //
+  //   <type> ::= U "__strong"
+  //   <type> ::= U "__weak"
+  //   <type> ::= U "__autoreleasing"
+  //   <type> ::= U "__unsafe_unretained"
+  case Qualifiers::OCL_None:
+    break;
+    
+  case Qualifiers::OCL_Weak:
+    LifetimeName = "__weak";
+    break;
+    
+  case Qualifiers::OCL_Strong:
+    LifetimeName = "__strong";
+    break;
+    
+  case Qualifiers::OCL_Autoreleasing:
+    LifetimeName = "__autoreleasing";
+    break;
+    
+  case Qualifiers::OCL_ExplicitNone:
+    LifetimeName = "__unsafe_unretained";
+    break;
+  }
+  if (!LifetimeName.empty())
+    Out << 'U' << LifetimeName.size() << LifetimeName;
 }
 
 void CXXNameMangler::mangleRefQualifier(RefQualifierKind RefQualifier) {
@@ -2089,6 +2118,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
   case Expr::ObjCProtocolExprClass:
   case Expr::ObjCSelectorExprClass:
   case Expr::ObjCStringLiteralClass:
+  case Expr::ObjCIndirectCopyRestoreExprClass:
   case Expr::OffsetOfExprClass:
   case Expr::PredefinedExprClass:
   case Expr::ShuffleVectorExprClass:
@@ -2347,7 +2377,15 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
     mangleExpression(cast<ImplicitCastExpr>(E)->getSubExpr(), Arity);
     break;
   }
-
+      
+  case Expr::ObjCBridgedCastExprClass: {
+    // Mangle ownership casts as a vendor extended operator __bridge, 
+    // __bridge_transfer, or __bridge_retain.
+    llvm::StringRef Kind = cast<ObjCBridgedCastExpr>(E)->getBridgeKindName();
+    Out << "v1U" << Kind.size() << Kind;
+  }
+  // Fall through to mangle the cast itself.
+      
   case Expr::CStyleCastExprClass:
   case Expr::CXXStaticCastExprClass:
   case Expr::CXXDynamicCastExprClass:

+ 9 - 0
lib/AST/ParentMap.cpp

@@ -66,6 +66,15 @@ Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const {
   return S;  
 }
 
+Stmt *ParentMap::getOuterParenParent(Stmt *S) const {
+  Stmt *Paren = 0;
+  while (isa<ParenExpr>(S)) {
+    Paren = S;
+    S = getParent(S);
+  };
+  return Paren;
+}
+
 bool ParentMap::isConsumedExpr(Expr* E) const {
   Stmt *P = getParent(E);
   Stmt *DirectChild = E;

+ 17 - 0
lib/AST/StmtPrinter.cpp

@@ -449,6 +449,12 @@ void StmtPrinter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *Node) {
   OS << "\n";
 }
 
+void StmtPrinter::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *Node) {
+  Indent() << "@autoreleasepool";
+  PrintRawCompoundStmt(dyn_cast<CompoundStmt>(Node->getSubStmt()));
+  OS << "\n";
+}
+
 void StmtPrinter::PrintRawCXXCatchStmt(CXXCatchStmt *Node) {
   OS << "catch (";
   if (Decl *ExDecl = Node->getExceptionDecl())
@@ -1464,6 +1470,17 @@ void StmtPrinter::VisitObjCMessageExpr(ObjCMessageExpr *Mess) {
   OS << "]";
 }
 
+void
+StmtPrinter::VisitObjCIndirectCopyRestoreExpr(ObjCIndirectCopyRestoreExpr *E) {
+  PrintExpr(E->getSubExpr());
+}
+
+void
+StmtPrinter::VisitObjCBridgedCastExpr(ObjCBridgedCastExpr *E) {
+  OS << "(" << E->getBridgeKindName() << E->getType().getAsString(Policy) 
+     << ")";
+  PrintExpr(E->getSubExpr());
+}
 
 void StmtPrinter::VisitBlockExpr(BlockExpr *Node) {
   BlockDecl *BD = Node->getBlockDecl();

+ 15 - 0
lib/AST/StmtProfile.cpp

@@ -220,6 +220,10 @@ void StmtProfiler::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) {
   VisitStmt(S);
 }
 
+void StmtProfiler::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {
+  VisitStmt(S);
+}
+
 void StmtProfiler::VisitExpr(Expr *S) {
   VisitStmt(S);
 }
@@ -952,6 +956,17 @@ void StmtProfiler::VisitObjCIsaExpr(ObjCIsaExpr *S) {
   ID.AddBoolean(S->isArrow());
 }
 
+void
+StmtProfiler::VisitObjCIndirectCopyRestoreExpr(ObjCIndirectCopyRestoreExpr *S) {
+  VisitExpr(S);
+  ID.AddBoolean(S->shouldCopy());
+}
+
+void StmtProfiler::VisitObjCBridgedCastExpr(ObjCBridgedCastExpr *S) {
+  VisitExplicitCastExpr(S);
+  ID.AddBoolean(S->getBridgeKind());
+}
+
 void StmtProfiler::VisitDecl(Decl *D) {
   ID.AddInteger(D? D->getKind() : 0);
 

+ 320 - 87
lib/AST/Type.cpp

@@ -36,7 +36,10 @@ bool Qualifiers::isStrictSupersetOf(Qualifiers Other) const {
      (hasObjCGCAttr() && !Other.hasObjCGCAttr())) &&
     // Address space superset.
     ((getAddressSpace() == Other.getAddressSpace()) ||
-     (hasAddressSpace()&& !Other.hasAddressSpace()));
+     (hasAddressSpace()&& !Other.hasAddressSpace())) &&
+    // Lifetime qualifier superset.
+    ((getObjCLifetime() == Other.getObjCLifetime()) ||
+     (hasObjCLifetime() && !Other.hasObjCLifetime()));
 }
 
 bool QualType::isConstant(QualType T, ASTContext &Ctx) {
@@ -866,39 +869,59 @@ bool Type::isIncompleteType() const {
   }
 }
 
-/// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10)
-bool Type::isPODType() const {
+bool QualType::isPODType(ASTContext &Context) const {
   // The compiler shouldn't query this for incomplete types, but the user might.
   // We return false for that case. Except for incomplete arrays of PODs, which
   // are PODs according to the standard.
-  if (isIncompleteArrayType() &&
-      cast<ArrayType>(CanonicalType)->getElementType()->isPODType())
-    return true;
-  if (isIncompleteType())
+  if (isNull())
+    return 0;
+  
+  if ((*this)->isIncompleteArrayType())
+    return Context.getBaseElementType(*this).isPODType(Context);
+    
+  if ((*this)->isIncompleteType())
     return false;
 
+  if (Context.getLangOptions().ObjCAutoRefCount) {
+    switch (getObjCLifetime()) {
+    case Qualifiers::OCL_ExplicitNone:
+      return true;
+      
+    case Qualifiers::OCL_Strong:
+    case Qualifiers::OCL_Weak:
+    case Qualifiers::OCL_Autoreleasing:
+      return false;
+
+    case Qualifiers::OCL_None:
+      if ((*this)->isObjCLifetimeType())
+        return false;
+      break;
+    }        
+  }
+  
+  QualType CanonicalType = getTypePtr()->CanonicalType;
   switch (CanonicalType->getTypeClass()) {
     // Everything not explicitly mentioned is not POD.
   default: return false;
-  case VariableArray:
-  case ConstantArray:
+  case Type::VariableArray:
+  case Type::ConstantArray:
     // IncompleteArray is handled above.
-    return cast<ArrayType>(CanonicalType)->getElementType()->isPODType();
-
-  case Builtin:
-  case Complex:
-  case Pointer:
-  case MemberPointer:
-  case Vector:
-  case ExtVector:
-  case ObjCObjectPointer:
-  case BlockPointer:
+    return Context.getBaseElementType(*this).isPODType(Context);
+        
+  case Type::ObjCObjectPointer:
+  case Type::BlockPointer:
+  case Type::Builtin:
+  case Type::Complex:
+  case Type::Pointer:
+  case Type::MemberPointer:
+  case Type::Vector:
+  case Type::ExtVector:
     return true;
 
-  case Enum:
+  case Type::Enum:
     return true;
 
-  case Record:
+  case Type::Record:
     if (CXXRecordDecl *ClassDecl
           = dyn_cast<CXXRecordDecl>(cast<RecordType>(CanonicalType)->getDecl()))
       return ClassDecl->isPOD();
@@ -908,6 +931,121 @@ bool Type::isPODType() const {
   }
 }
 
+bool QualType::isTrivialType(ASTContext &Context) const {
+  // The compiler shouldn't query this for incomplete types, but the user might.
+  // We return false for that case. Except for incomplete arrays of PODs, which
+  // are PODs according to the standard.
+  if (isNull())
+    return 0;
+  
+  if ((*this)->isArrayType())
+    return Context.getBaseElementType(*this).isTrivialType(Context);
+  
+  // Return false for incomplete types after skipping any incomplete array
+  // types which are expressly allowed by the standard and thus our API.
+  if ((*this)->isIncompleteType())
+    return false;
+  
+  if (Context.getLangOptions().ObjCAutoRefCount) {
+    switch (getObjCLifetime()) {
+    case Qualifiers::OCL_ExplicitNone:
+      return true;
+      
+    case Qualifiers::OCL_Strong:
+    case Qualifiers::OCL_Weak:
+    case Qualifiers::OCL_Autoreleasing:
+      return false;
+      
+    case Qualifiers::OCL_None:
+      if ((*this)->isObjCLifetimeType())
+        return false;
+      break;
+    }        
+  }
+  
+  QualType CanonicalType = getTypePtr()->CanonicalType;
+  if (CanonicalType->isDependentType())
+    return false;
+  
+  // C++0x [basic.types]p9:
+  //   Scalar types, trivial class types, arrays of such types, and
+  //   cv-qualified versions of these types are collectively called trivial
+  //   types.
+  
+  // As an extension, Clang treats vector types as Scalar types.
+  if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
+    return true;
+  if (const RecordType *RT = CanonicalType->getAs<RecordType>()) {
+    if (const CXXRecordDecl *ClassDecl =
+        dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+      // C++0x [class]p5:
+      //   A trivial class is a class that has a trivial default constructor
+      if (!ClassDecl->hasTrivialDefaultConstructor()) return false;
+      //   and is trivially copyable.
+      if (!ClassDecl->isTriviallyCopyable()) return false;
+    }
+    
+    return true;
+  }
+  
+  // No other types can match.
+  return false;
+}
+
+bool QualType::isTriviallyCopyableType(ASTContext &Context) const {
+  if ((*this)->isArrayType())
+    return Context.getBaseElementType(*this).isTrivialType(Context);
+
+  if (Context.getLangOptions().ObjCAutoRefCount) {
+    switch (getObjCLifetime()) {
+    case Qualifiers::OCL_ExplicitNone:
+      return true;
+      
+    case Qualifiers::OCL_Strong:
+    case Qualifiers::OCL_Weak:
+    case Qualifiers::OCL_Autoreleasing:
+      return false;
+      
+    case Qualifiers::OCL_None:
+      if ((*this)->isObjCLifetimeType())
+        return false;
+      break;
+    }        
+  }
+
+  // C++0x [basic.types]p9
+  //   Scalar types, trivially copyable class types, arrays of such types, and
+  //   cv-qualified versions of these types are collectively called trivial
+  //   types.
+
+  QualType CanonicalType = getCanonicalType();
+  if (CanonicalType->isDependentType())
+    return false;
+
+  // Return false for incomplete types after skipping any incomplete array types
+  // which are expressly allowed by the standard and thus our API.
+  if (CanonicalType->isIncompleteType())
+    return false;
+ 
+  // As an extension, Clang treats vector types as Scalar types.
+  if (CanonicalType->isScalarType() || CanonicalType->isVectorType())
+    return true;
+
+  if (const RecordType *RT = CanonicalType->getAs<RecordType>()) {
+    if (const CXXRecordDecl *ClassDecl =
+          dyn_cast<CXXRecordDecl>(RT->getDecl())) {
+      if (!ClassDecl->isTriviallyCopyable()) return false;
+    }
+
+    return true;
+  }
+
+  // No other types can match.
+  return false;
+}
+
+
+
 bool Type::isLiteralType() const {
   if (isDependentType())
     return false;
@@ -928,6 +1066,10 @@ bool Type::isLiteralType() const {
   if (BaseTy->isIncompleteType())
     return false;
 
+  // Objective-C lifetime types are not literal types.
+  if (BaseTy->isObjCRetainableType())
+    return false;
+  
   // C++0x [basic.types]p10:
   //   A type is a literal type if it is:
   //    -- a scalar type; or
@@ -961,68 +1103,6 @@ bool Type::isLiteralType() const {
   return false;
 }
 
-bool Type::isTrivialType() const {
-  if (isDependentType())
-    return false;
-
-  // C++0x [basic.types]p9:
-  //   Scalar types, trivial class types, arrays of such types, and
-  //   cv-qualified versions of these types are collectively called trivial
-  //   types.
-  const Type *BaseTy = getBaseElementTypeUnsafe();
-  assert(BaseTy && "NULL element type");
-
-  // Return false for incomplete types after skipping any incomplete array
-  // types which are expressly allowed by the standard and thus our API.
-  if (BaseTy->isIncompleteType())
-    return false;
-
-  // As an extension, Clang treats vector types as Scalar types.
-  if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true;
-  if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
-    if (const CXXRecordDecl *ClassDecl =
-        dyn_cast<CXXRecordDecl>(RT->getDecl())) {
-      if (!ClassDecl->isTrivial()) return false;
-    }
-
-    return true;
-  }
-
-  // No other types can match.
-  return false;
-}
-
-bool Type::isTriviallyCopyableType() const {
-  if (isDependentType())
-    return false;
-
-  // C++0x [basic.types]p9
-  //   Scalar types, trivially copyable class types, arrays of such types, and
-  //   cv-qualified versions of these types are collectively called trivial
-  //   types.
-  const Type *BaseTy = getBaseElementTypeUnsafe();
-  assert(BaseTy && "NULL element type");
-
-  // Return false for incomplete types after skipping any incomplete array types
-  // which are expressly allowed by the standard and thus our API.
-  if (BaseTy->isIncompleteType())
-    return false;
- 
-  // As an extension, Clang treats vector types as Scalar types.
-  if (BaseTy->isScalarType() || BaseTy->isVectorType()) return true;
-  if (const RecordType *RT = BaseTy->getAs<RecordType>()) {
-    if (const CXXRecordDecl *ClassDecl =
-        dyn_cast<CXXRecordDecl>(RT->getDecl())) {
-      if (!ClassDecl->isTriviallyCopyable()) return false;
-    }
-
-    return true;
-  }
-
-  // No other types can match.
-  return false;
-}
-
 bool Type::isStandardLayoutType() const {
   if (isDependentType())
     return false;
@@ -1060,14 +1140,32 @@ bool Type::isStandardLayoutType() const {
 // This is effectively the intersection of isTrivialType and
 // isStandardLayoutType. We implement it dircetly to avoid redundant
 // conversions from a type to a CXXRecordDecl.
-bool Type::isCXX11PODType() const {
-  if (isDependentType())
+bool QualType::isCXX11PODType(ASTContext &Context) const {
+  const Type *ty = getTypePtr();
+  if (ty->isDependentType())
     return false;
 
+  if (Context.getLangOptions().ObjCAutoRefCount) {
+    switch (getObjCLifetime()) {
+    case Qualifiers::OCL_ExplicitNone:
+      return true;
+      
+    case Qualifiers::OCL_Strong:
+    case Qualifiers::OCL_Weak:
+    case Qualifiers::OCL_Autoreleasing:
+      return false;
+
+    case Qualifiers::OCL_None:
+      if (ty->isObjCLifetimeType())
+        return false;
+      break;
+    }        
+  }
+
   // C++11 [basic.types]p9:
   //   Scalar types, POD classes, arrays of such types, and cv-qualified
   //   versions of these types are collectively called trivial types.
-  const Type *BaseTy = getBaseElementTypeUnsafe();
+  const Type *BaseTy = ty->getBaseElementTypeUnsafe();
   assert(BaseTy && "NULL element type");
 
   // Return false for incomplete types after skipping any incomplete array
@@ -1392,7 +1490,8 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args,
                  result->containsUnexpandedParameterPack(),
                  epi.ExtInfo),
     NumArgs(numArgs), NumExceptions(epi.NumExceptions),
-    ExceptionSpecType(epi.ExceptionSpecType)
+    ExceptionSpecType(epi.ExceptionSpecType),
+    HasAnyConsumedArgs(epi.ConsumedArguments != 0)
 {
   // Fill in the trailing argument array.
   QualType *argSlot = reinterpret_cast<QualType*>(this+1);
@@ -1423,6 +1522,12 @@ FunctionProtoType::FunctionProtoType(QualType result, const QualType *args,
     Expr **noexSlot = reinterpret_cast<Expr**>(argSlot + numArgs);
     *noexSlot = epi.NoexceptExpr;
   }
+
+  if (epi.ConsumedArguments) {
+    bool *consumedArgs = const_cast<bool*>(getConsumedArgsBuffer());
+    for (unsigned i = 0; i != numArgs; ++i)
+      consumedArgs[i] = epi.ConsumedArguments[i];
+  }
 }
 
 FunctionProtoType::NoexceptResult
@@ -1461,6 +1566,24 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
                                 const QualType *ArgTys, unsigned NumArgs,
                                 const ExtProtoInfo &epi,
                                 const ASTContext &Context) {
+
+  // We have to be careful not to get ambiguous profile encodings.
+  // Note that valid type pointers are never ambiguous with anything else.
+  //
+  // The encoding grammar begins:
+  //      type type* bool int bool 
+  // If that final bool is true, then there is a section for the EH spec:
+  //      bool type*
+  // This is followed by an optional "consumed argument" section of the
+  // same length as the first type sequence:
+  //      bool*
+  // Finally, we have the ext info:
+  //      int
+  // 
+  // There is no ambiguity between the consumed arguments and an empty EH
+  // spec because of the leading 'bool' which unambiguously indicates
+  // whether the following bool is the EH spec or part of the arguments.
+
   ID.AddPointer(Result.getAsOpaquePtr());
   for (unsigned i = 0; i != NumArgs; ++i)
     ID.AddPointer(ArgTys[i].getAsOpaquePtr());
@@ -1474,6 +1597,10 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
   } else if (epi.ExceptionSpecType == EST_ComputedNoexcept && epi.NoexceptExpr){
     epi.NoexceptExpr->Profile(ID, Context, false);
   }
+  if (epi.ConsumedArguments) {
+    for (unsigned i = 0; i != NumArgs; ++i)
+      ID.AddBoolean(epi.ConsumedArguments[i]);
+  }
   epi.ExtInfo.Profile(ID);
 }
 
@@ -1900,6 +2027,79 @@ void Type::ClearLinkageCache() {
     CanonicalType->TypeBits.CacheValidAndVisibility = 0;
 }
 
+Qualifiers::ObjCLifetime Type::getObjCARCImplicitLifetime() const {
+  if (isObjCARCImplicitlyUnretainedType())
+    return Qualifiers::OCL_ExplicitNone;
+  return Qualifiers::OCL_Strong;
+}
+
+bool Type::isObjCARCImplicitlyUnretainedType() const {
+  assert(isObjCLifetimeType() &&
+         "cannot query implicit lifetime for non-inferrable type");
+
+  const Type *canon = getCanonicalTypeInternal().getTypePtr();
+
+  // Walk down to the base type.  We don't care about qualifiers for this.
+  while (const ArrayType *array = dyn_cast<ArrayType>(canon))
+    canon = array->getElementType().getTypePtr();
+
+  if (const ObjCObjectPointerType *opt
+        = dyn_cast<ObjCObjectPointerType>(canon)) {
+    // Class and Class<Protocol> don't require retension.
+    if (opt->getObjectType()->isObjCClass())
+      return true;
+  }
+
+  return false;
+}
+
+bool Type::isObjCNSObjectType() const {
+  if (const TypedefType *typedefType = dyn_cast<TypedefType>(this))
+    return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>();
+  return false;
+}
+bool Type::isObjCRetainableType() const {
+  return isObjCObjectPointerType() ||
+         isBlockPointerType() ||
+         isObjCNSObjectType();
+}
+bool Type::isObjCIndirectLifetimeType() const {
+  if (isObjCLifetimeType())
+    return true;
+  if (const PointerType *OPT = getAs<PointerType>())
+    return OPT->getPointeeType()->isObjCIndirectLifetimeType();
+  if (const ReferenceType *Ref = getAs<ReferenceType>())
+    return Ref->getPointeeType()->isObjCIndirectLifetimeType();
+  if (const MemberPointerType *MemPtr = getAs<MemberPointerType>())
+    return MemPtr->getPointeeType()->isObjCIndirectLifetimeType();
+  return false;
+}
+
+/// Returns true if objects of this type have lifetime semantics under
+/// ARC.
+bool Type::isObjCLifetimeType() const {
+  const Type *type = this;
+  while (const ArrayType *array = type->getAsArrayTypeUnsafe())
+    type = array->getElementType().getTypePtr();
+  return type->isObjCRetainableType();
+}
+
+/// \brief Determine whether the given type T is a "bridgable" Objective-C type,
+/// which is either an Objective-C object pointer type or an 
+bool Type::isObjCARCBridgableType() const {
+  return isObjCObjectPointerType() || isBlockPointerType();
+}
+
+/// \brief Determine whether the given type T is a "bridgeable" C type.
+bool Type::isCARCBridgableType() const {
+  const PointerType *Pointer = getAs<PointerType>();
+  if (!Pointer)
+    return false;
+  
+  QualType Pointee = Pointer->getPointeeType();
+  return Pointee->isVoidType() || Pointee->isRecordType();
+}
+
 bool Type::hasSizedVLAType() const {
   if (!isVariablyModifiedType()) return false;
 
@@ -1919,6 +2119,18 @@ bool Type::hasSizedVLAType() const {
 }
 
 QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) {
+  switch (type.getObjCLifetime()) {
+  case Qualifiers::OCL_None:
+  case Qualifiers::OCL_ExplicitNone:
+  case Qualifiers::OCL_Autoreleasing:
+    break;
+
+  case Qualifiers::OCL_Strong:
+    return DK_objc_strong_lifetime;
+  case Qualifiers::OCL_Weak:
+    return DK_objc_weak_lifetime;
+  }
+
   /// Currently, the only destruction kind we recognize is C++ objects
   /// with non-trivial destructors.
   const CXXRecordDecl *record =
@@ -1928,3 +2140,24 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) {
 
   return DK_none;
 }
+
+bool QualType::hasTrivialCopyAssignment(ASTContext &Context) const {
+  switch (getObjCLifetime()) {
+  case Qualifiers::OCL_None:
+    break;
+      
+  case Qualifiers::OCL_ExplicitNone:
+    return true;
+      
+  case Qualifiers::OCL_Autoreleasing:
+  case Qualifiers::OCL_Strong:
+  case Qualifiers::OCL_Weak:
+    return !Context.getLangOptions().ObjCAutoRefCount;
+  }
+  
+  if (const CXXRecordDecl *Record 
+            = getTypePtr()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl())
+    return Record->hasTrivialCopyAssignment();
+  
+  return true;
+}

+ 98 - 19
lib/AST/TypePrinter.cpp

@@ -24,6 +24,23 @@
 using namespace clang;
 
 namespace {
+  /// \brief RAII object that enables printing of the ARC __strong lifetime
+  /// qualifier.
+  class IncludeStrongLifetimeRAII {
+    PrintingPolicy &Policy;
+    bool Old;
+    
+  public:
+    explicit IncludeStrongLifetimeRAII(PrintingPolicy &Policy) 
+      : Policy(Policy), Old(Policy.SuppressStrongLifetime) {
+      Policy.SuppressStrongLifetime = false;
+    }
+    
+    ~IncludeStrongLifetimeRAII() {
+      Policy.SuppressStrongLifetime = Old;
+    }
+  };
+  
   class TypePrinter {
     PrintingPolicy Policy;
 
@@ -78,7 +95,7 @@ void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) {
   // "int * const", printing "const int *" is different.  Only do this when the
   // type expands to a simple string.
   bool CanPrefixQualifiers = false;
-  
+  bool NeedARCStrongQualifier = false;
   Type::TypeClass TC = T->getTypeClass();
   if (const AutoType *AT = dyn_cast<AutoType>(T))
     TC = AT->desugar()->getTypeClass();
@@ -114,15 +131,18 @@ void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) {
         T->isObjCQualifiedIdType() || T->isObjCQualifiedClassType();
       break;
       
+    case Type::ConstantArray:
+    case Type::IncompleteArray:
+    case Type::VariableArray:
+    case Type::DependentSizedArray:
+      NeedARCStrongQualifier = true;
+      // Fall through
+      
     case Type::Pointer:
     case Type::BlockPointer:
     case Type::LValueReference:
     case Type::RValueReference:
     case Type::MemberPointer:
-    case Type::ConstantArray:
-    case Type::IncompleteArray:
-    case Type::VariableArray:
-    case Type::DependentSizedArray:
     case Type::DependentSizedExtVector:
     case Type::Vector:
     case Type::ExtVector:
@@ -139,13 +159,20 @@ void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) {
   
   if (!CanPrefixQualifiers && !Quals.empty()) {
     std::string qualsBuffer;
-    Quals.getAsStringInternal(qualsBuffer, Policy);
+    if (NeedARCStrongQualifier) {
+      IncludeStrongLifetimeRAII Strong(Policy);
+      Quals.getAsStringInternal(qualsBuffer, Policy);
+    } else {
+      Quals.getAsStringInternal(qualsBuffer, Policy);
+    }
     
-    if (!buffer.empty()) {
-      qualsBuffer += ' ';
-      qualsBuffer += buffer;
+    if (!qualsBuffer.empty()) {
+      if (!buffer.empty()) {
+        qualsBuffer += ' ';
+        qualsBuffer += buffer;
+      }
+      std::swap(buffer, qualsBuffer);
     }
-    std::swap(buffer, qualsBuffer);
   }
   
   switch (T->getTypeClass()) {
@@ -159,13 +186,20 @@ void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) {
   // If we're adding the qualifiers as a prefix, do it now.
   if (CanPrefixQualifiers && !Quals.empty()) {
     std::string qualsBuffer;
-    Quals.getAsStringInternal(qualsBuffer, Policy);
-    
-    if (!buffer.empty()) {
-      qualsBuffer += ' ';
-      qualsBuffer += buffer;
+    if (NeedARCStrongQualifier) {
+      IncludeStrongLifetimeRAII Strong(Policy);
+      Quals.getAsStringInternal(qualsBuffer, Policy);
+    } else {
+      Quals.getAsStringInternal(qualsBuffer, Policy);
+    }
+
+    if (!qualsBuffer.empty()) {
+      if (!buffer.empty()) {
+        qualsBuffer += ' ';
+        qualsBuffer += buffer;
+      }
+      std::swap(buffer, qualsBuffer);
     }
-    std::swap(buffer, qualsBuffer);
   }
 }
 
@@ -192,6 +226,7 @@ void TypePrinter::printPointer(const PointerType *T, std::string &S) {
   if (isa<ArrayType>(T->getPointeeType()))
     S = '(' + S + ')';
   
+  IncludeStrongLifetimeRAII Strong(Policy);
   print(T->getPointeeType(), S);
 }
 
@@ -209,6 +244,7 @@ void TypePrinter::printLValueReference(const LValueReferenceType *T,
   if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
     S = '(' + S + ')';
   
+  IncludeStrongLifetimeRAII Strong(Policy);
   print(T->getPointeeTypeAsWritten(), S);
 }
 
@@ -221,6 +257,7 @@ void TypePrinter::printRValueReference(const RValueReferenceType *T,
   if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
     S = '(' + S + ')';
   
+  IncludeStrongLifetimeRAII Strong(Policy);
   print(T->getPointeeTypeAsWritten(), S);
 }
 
@@ -236,6 +273,7 @@ void TypePrinter::printMemberPointer(const MemberPointerType *T,
   if (isa<ArrayType>(T->getPointeeType()))
     S = '(' + S + ')';
   
+  IncludeStrongLifetimeRAII Strong(Policy);
   print(T->getPointeeType(), S);
 }
 
@@ -245,12 +283,14 @@ void TypePrinter::printConstantArray(const ConstantArrayType *T,
   S += llvm::utostr(T->getSize().getZExtValue());
   S += ']';
   
+  IncludeStrongLifetimeRAII Strong(Policy);
   print(T->getElementType(), S);
 }
 
 void TypePrinter::printIncompleteArray(const IncompleteArrayType *T, 
                                        std::string &S) {
   S += "[]";
+  IncludeStrongLifetimeRAII Strong(Policy);
   print(T->getElementType(), S);
 }
 
@@ -276,6 +316,7 @@ void TypePrinter::printVariableArray(const VariableArrayType *T,
   }
   S += ']';
   
+  IncludeStrongLifetimeRAII Strong(Policy);
   print(T->getElementType(), S);
 }
 
@@ -291,6 +332,7 @@ void TypePrinter::printDependentSizedArray(const DependentSizedArrayType *T,
   }
   S += ']';
   
+  IncludeStrongLifetimeRAII Strong(Policy);
   print(T->getElementType(), S);
 }
 
@@ -518,6 +560,7 @@ void TypePrinter::printUnaryTransform(const UnaryTransformType *T,
   if (!S.empty())
     S = ' ' + S;
   std::string Str;
+  IncludeStrongLifetimeRAII Strong(Policy);
   print(T->getBaseType(), Str);
 
   switch (T->getUTTKind()) {
@@ -552,6 +595,7 @@ void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
       Buffer += "<anonymous>";
   } else if (ClassTemplateSpecializationDecl *Spec
                = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
+    IncludeStrongLifetimeRAII Strong(Policy);
     const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
     std::string TemplateArgsStr
       = TemplateSpecializationType::PrintTemplateArgumentList(
@@ -642,6 +686,7 @@ void TypePrinter::printTag(TagDecl *D, std::string &InnerString) {
       Args = TemplateArgs.data();
       NumArgs = TemplateArgs.size();
     }
+    IncludeStrongLifetimeRAII Strong(Policy);
     Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
                                                                     NumArgs,
                                                                     Policy);
@@ -677,18 +722,21 @@ void TypePrinter::printTemplateTypeParm(const TemplateTypeParmType *T,
 
 void TypePrinter::printSubstTemplateTypeParm(const SubstTemplateTypeParmType *T, 
                                              std::string &S) { 
+  IncludeStrongLifetimeRAII Strong(Policy);
   print(T->getReplacementType(), S);
 }
 
 void TypePrinter::printSubstTemplateTypeParmPack(
                                         const SubstTemplateTypeParmPackType *T, 
                                              std::string &S) { 
+  IncludeStrongLifetimeRAII Strong(Policy);
   printTemplateTypeParm(T->getReplacedParameter(), S);
 }
 
 void TypePrinter::printTemplateSpecialization(
                                             const TemplateSpecializationType *T, 
                                               std::string &S) { 
+  IncludeStrongLifetimeRAII Strong(Policy);
   std::string SpecString;
   
   {
@@ -765,6 +813,7 @@ void TypePrinter::printDependentName(const DependentNameType *T, std::string &S)
 
 void TypePrinter::printDependentTemplateSpecialization(
         const DependentTemplateSpecializationType *T, std::string &S) { 
+  IncludeStrongLifetimeRAII Strong(Policy);
   std::string MyString;
   {
     llvm::raw_string_ostream OS(MyString);
@@ -796,8 +845,9 @@ void TypePrinter::printPackExpansion(const PackExpansionType *T,
 
 void TypePrinter::printAttributed(const AttributedType *T,
                                   std::string &S) {
-  // Prefer the macro forms of the GC qualifiers.
-  if (T->getAttrKind() == AttributedType::attr_objc_gc)
+  // Prefer the macro forms of the GC and lifetime qualifiers.
+  if (T->getAttrKind() == AttributedType::attr_objc_gc ||
+      T->getAttrKind() == AttributedType::attr_objc_lifetime)
     return print(T->getEquivalentType(), S);
 
   print(T->getModifiedType(), S);
@@ -866,6 +916,18 @@ void TypePrinter::printAttributed(const AttributedType *T,
     break;
   }
 
+  case AttributedType::attr_objc_lifetime:
+    S += "objc_lifetime(";
+    switch (T->getEquivalentType().getObjCLifetime()) {
+    case Qualifiers::OCL_None: llvm_unreachable("no lifetime!"); break;
+    case Qualifiers::OCL_ExplicitNone: S += "none"; break;
+    case Qualifiers::OCL_Strong: S += "strong"; break;
+    case Qualifiers::OCL_Weak: S += "weak"; break;
+    case Qualifiers::OCL_Autoreleasing: S += "autoreleasing"; break;
+    }
+    S += ")";
+    break;
+
   case AttributedType::attr_noreturn: S += "noreturn"; break;
   case AttributedType::attr_cdecl: S += "cdecl"; break;
   case AttributedType::attr_fastcall: S += "fastcall"; break;
@@ -1080,7 +1142,7 @@ std::string Qualifiers::getAsString() const {
 // prefix a space if the string is non-empty.  Will not append a final
 // space.
 void Qualifiers::getAsStringInternal(std::string &S,
-                                     const PrintingPolicy&) const {
+                                     const PrintingPolicy& Policy) const {
   AppendTypeQualList(S, getCVRQualifiers());
   if (unsigned addrspace = getAddressSpace()) {
     if (!S.empty()) S += ' ';
@@ -1095,6 +1157,23 @@ void Qualifiers::getAsStringInternal(std::string &S,
     else
       S += "__strong";
   }
+  if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime()) {
+    if (!S.empty() && 
+        !(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime))
+      S += ' ';
+    
+    switch (lifetime) {
+    case Qualifiers::OCL_None: llvm_unreachable("none but true");
+    case Qualifiers::OCL_ExplicitNone: S += "__unsafe_unretained"; break;
+    case Qualifiers::OCL_Strong: 
+      if (!Policy.SuppressStrongLifetime)
+        S += "__strong"; 
+      break;
+        
+    case Qualifiers::OCL_Weak: S += "__weak"; break;
+    case Qualifiers::OCL_Autoreleasing: S += "__autoreleasing"; break;
+    }
+  }
 }
 
 std::string QualType::getAsString(const Type *ty, Qualifiers qs) {

+ 6 - 0
lib/Analysis/ReachableCode.cpp

@@ -16,6 +16,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/Analysis/Analyses/ReachableCode.h"
 #include "clang/Analysis/CFG.h"
@@ -108,6 +109,11 @@ static SourceLocation GetUnreachableLoc(const CFGBlock &b, SourceRange &R1,
     case Stmt::CXXTryStmtClass: {
       return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc();
     }
+    case Expr::ObjCBridgedCastExprClass: {
+      const ObjCBridgedCastExpr *CSC = cast<ObjCBridgedCastExpr>(S);
+      R1 = CSC->getSubExpr()->getSourceRange();
+      return CSC->getLParenLoc();
+    }
     default: ;
   }
   R1 = S->getSourceRange();

+ 5 - 0
lib/Basic/DiagnosticIDs.cpp

@@ -740,5 +740,10 @@ bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
       DiagID == diag::err_unavailable_message)
     return false;
 
+  // Currently we consider all ARC errors as recoverable.
+  if (getCategoryNumberForDiag(DiagID) ==
+        diag::DiagCat_Automatic_Reference_Counting_Issue)
+    return false;
+
   return true;
 }

+ 5 - 2
lib/Basic/IdentifierTable.cpp

@@ -17,6 +17,7 @@
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cstdio>
 
@@ -92,7 +93,8 @@ namespace {
     KEYBORLAND = 0x100,
     KEYOPENCL = 0x200,
     KEYC1X = 0x400,
-    KEYALL = 0x7ff
+    KEYARC = 0x800,
+    KEYALL = 0x0fff
   };
 }
 
@@ -120,7 +122,8 @@ static void AddKeyword(llvm::StringRef Keyword,
   else if (LangOpts.OpenCL && (Flags & KEYOPENCL)) AddResult = 2;
   else if (!LangOpts.CPlusPlus && (Flags & KEYNOCXX)) AddResult = 2;
   else if (LangOpts.C1X && (Flags & KEYC1X)) AddResult = 2;
-
+  else if (LangOpts.ObjCAutoRefCount && (Flags & KEYARC)) AddResult = 2;
+           
   // Don't add this keyword if disabled in this language.
   if (AddResult == 0) return;
 

+ 28 - 8
lib/Basic/Targets.cpp

@@ -84,15 +84,35 @@ static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
   Builder.defineMacro("__MACH__");
   Builder.defineMacro("OBJC_NEW_PROPERTIES");
 
-  // __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.ObjC1 || Opts.getGCMode() == LangOptions::NonGC)
-    Builder.defineMacro("__strong", "");
-  else
-    Builder.defineMacro("__strong", "__attribute__((objc_gc(strong)))");
+  if (Opts.ObjCAutoRefCount) {
+    Builder.defineMacro("__weak", "__attribute__((objc_lifetime(weak)))");
+    Builder.defineMacro("__strong", "__attribute__((objc_lifetime(strong)))");
+    Builder.defineMacro("__autoreleasing",
+                        "__attribute__((objc_lifetime(autoreleasing)))");
+    Builder.defineMacro("__unsafe_unretained",
+                        "__attribute__((objc_lifetime(none)))");
+  } else {
+    // __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.getGCMode() != 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("__unsafe_unretained", "");
+    
+    // The Objective-C bridged cast keywords are defined to nothing in non-ARC
+    // mode; then they become normal, C-style casts.
+    Builder.defineMacro("__bridge", "");
+    Builder.defineMacro("__bridge_transfer", "");
+    Builder.defineMacro("__bridge_retained", "");
+  }
+  
   if (Opts.Static)
     Builder.defineMacro("__STATIC__");
   else

+ 195 - 29
lib/CodeGen/CGBlocks.cpp

@@ -347,13 +347,23 @@ static void computeBlockInfo(CodeGenModule &CGM, CGBlockInfo &info) {
       continue;
     }
 
-    // Block pointers require copy/dispose.
-    if (variable->getType()->isBlockPointerType()) {
-      info.NeedsCopyDispose = true;
+    // If we have a lifetime qualifier, honor it for capture purposes.
+    // That includes *not* copying it if it's __unsafe_unretained.
+    if (Qualifiers::ObjCLifetime lifetime 
+          = variable->getType().getObjCLifetime()) {
+      switch (lifetime) {
+      case Qualifiers::OCL_None: llvm_unreachable("impossible");
+      case Qualifiers::OCL_ExplicitNone:
+      case Qualifiers::OCL_Autoreleasing:
+        break;
+
+      case Qualifiers::OCL_Strong:
+      case Qualifiers::OCL_Weak:
+        info.NeedsCopyDispose = true;
+      }
 
-    // So do Objective-C pointers.
-    } else if (variable->getType()->isObjCObjectPointerType() ||
-               C.isObjCNSObjectType(variable->getType())) {
+    // Block pointers require copy/dispose.  So do Objective-C pointers.
+    } else if (variable->getType()->isObjCRetainableType()) {
       info.NeedsCopyDispose = true;
 
     // So do types that require non-trivial copy construction.
@@ -591,6 +601,11 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
 
     // Otherwise, fake up a POD copy into the block field.
     } else {
+      // Fake up a new variable so that EmitScalarInit doesn't think
+      // we're referring to the variable in its own initializer.
+      ImplicitParamDecl blockFieldPseudoVar(/*DC*/ 0, SourceLocation(),
+                                            /*name*/ 0, type);
+
       // We use one of these or the other depending on whether the
       // reference is nested.
       DeclRefExpr notNested(const_cast<VarDecl*>(variable), type, VK_LValue,
@@ -603,15 +618,29 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
 
       ImplicitCastExpr l2r(ImplicitCastExpr::OnStack, type, CK_LValueToRValue,
                            declRef, VK_RValue);
-      EmitExprAsInit(&l2r, variable, blockField,
+      EmitExprAsInit(&l2r, &blockFieldPseudoVar, blockField,
                      getContext().getDeclAlign(variable),
                      /*captured by init*/ false);
     }
 
     // Push a destructor if necessary.  The semantics for when this
     // actually gets run are really obscure.
-    if (!ci->isByRef() && CGM.getLangOptions().CPlusPlus)
-      PushDestructorCleanup(type, blockField);
+    if (!ci->isByRef()) {
+      switch (type.isDestructedType()) {
+      case QualType::DK_none:
+        break;
+      case QualType::DK_cxx_destructor:
+        PushDestructorCleanup(type, blockField);
+        break;
+      case QualType::DK_objc_strong_lifetime:
+        PushARCReleaseCleanup(getARCCleanupKind(), type, blockField, false);
+        break;
+      case QualType::DK_objc_weak_lifetime:
+        // __weak objects on the stack always get EH cleanups.
+        PushARCWeakReleaseCleanup(NormalAndEHCleanup, type, blockField);
+        break;
+      }
+    }
   }
 
   // Cast to the converted block-pointer type, which happens (somewhat
@@ -1023,8 +1052,6 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
 
 
 
-
-
 llvm::Constant *
 CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
   ASTContext &C = getContext();
@@ -1084,21 +1111,40 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
     if (capture.isConstant()) continue;
 
     const Expr *copyExpr = ci->getCopyExpr();
-    unsigned flags = 0;
+    BlockFieldFlags flags;
+
+    bool isARCWeakCapture = false;
 
     if (copyExpr) {
       assert(!ci->isByRef());
       // don't bother computing flags
+
     } else if (ci->isByRef()) {
       flags = BLOCK_FIELD_IS_BYREF;
-      if (type.isObjCGCWeak()) flags |= BLOCK_FIELD_IS_WEAK;
-    } else if (type->isBlockPointerType()) {
-      flags = BLOCK_FIELD_IS_BLOCK;
-    } else if (type->isObjCObjectPointerType() || C.isObjCNSObjectType(type)) {
+      if (type.isObjCGCWeak())
+        flags |= BLOCK_FIELD_IS_WEAK;
+
+    } else if (type->isObjCRetainableType()) {
       flags = BLOCK_FIELD_IS_OBJECT;
-    }
+      if (type->isBlockPointerType())
+        flags = BLOCK_FIELD_IS_BLOCK;
 
-    if (!copyExpr && !flags) continue;
+      // Special rules for ARC captures:
+      if (getLangOptions().ObjCAutoRefCount) {
+        Qualifiers qs = type.getQualifiers();
+
+        // Don't generate special copy 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)
+          isARCWeakCapture = true;
+      }
+    } else {
+      continue;
+    }
 
     unsigned index = capture.getIndex();
     llvm::Value *srcField = Builder.CreateStructGEP(src, index);
@@ -1107,12 +1153,14 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
     // If there's an explicit copy expression, we do that.
     if (copyExpr) {
       EmitSynthesizedCXXCopyCtor(dstField, srcField, copyExpr);
+    } else if (isARCWeakCapture) {
+      EmitARCCopyWeak(dstField, srcField);
     } else {
       llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src");
       srcValue = Builder.CreateBitCast(srcValue, VoidPtrTy);
       llvm::Value *dstAddr = Builder.CreateBitCast(dstField, VoidPtrTy);
       Builder.CreateCall3(CGM.getBlockObjectAssign(), dstAddr, srcValue,
-                          llvm::ConstantInt::get(Int32Ty, flags));
+                          llvm::ConstantInt::get(Int32Ty, flags.getBitMask()));
     }
   }
 
@@ -1176,20 +1224,37 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
     BlockFieldFlags flags;
     const CXXDestructorDecl *dtor = 0;
 
+    bool isARCWeakCapture = false;
+
     if (ci->isByRef()) {
       flags = BLOCK_FIELD_IS_BYREF;
-      if (type.isObjCGCWeak()) flags |= BLOCK_FIELD_IS_WEAK;
-    } else if (type->isBlockPointerType()) {
-      flags = BLOCK_FIELD_IS_BLOCK;
-    } else if (type->isObjCObjectPointerType() || C.isObjCNSObjectType(type)) {
+      if (type.isObjCGCWeak())
+        flags |= BLOCK_FIELD_IS_WEAK;
+    } else if (const CXXRecordDecl *record = type->getAsCXXRecordDecl()) {
+      if (record->hasTrivialDestructor())
+        continue;
+      dtor = record->getDestructor();
+    } else if (type->isObjCRetainableType()) {
       flags = BLOCK_FIELD_IS_OBJECT;
-    } else if (C.getLangOptions().CPlusPlus) {
-      if (const CXXRecordDecl *record = type->getAsCXXRecordDecl())
-        if (!record->hasTrivialDestructor())
-          dtor = record->getDestructor();
-    }
+      if (type->isBlockPointerType())
+        flags = BLOCK_FIELD_IS_BLOCK;
+
+      // Special rules for ARC captures.
+      if (getLangOptions().ObjCAutoRefCount) {
+        Qualifiers qs = type.getQualifiers();
+
+        // Don't generate special dispose logic for a captured object
+        // unless it's __strong or __weak.
+        if (!qs.hasStrongOrWeakObjCLifetime())
+          continue;
 
-    if (!dtor && flags.empty()) continue;
+        // Support __weak direct captures.
+        if (qs.getObjCLifetime() == Qualifiers::OCL_Weak)
+          isARCWeakCapture = true;
+      }
+    } else {
+      continue;
+    }
 
     unsigned index = capture.getIndex();
     llvm::Value *srcField = Builder.CreateStructGEP(src, index);
@@ -1198,6 +1263,10 @@ CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) {
     if (dtor) {
       PushDestructorCleanup(dtor, srcField);
 
+    // If this is a __weak capture, emit the release directly.
+    } else if (isARCWeakCapture) {
+      EmitARCDestroyWeak(srcField);
+
     // Otherwise we call _Block_object_dispose.  It wouldn't be too
     // hard to just emit this as a cleanup if we wanted to make sure
     // that things were done in reverse.
@@ -1251,6 +1320,55 @@ public:
   }
 };
 
+/// Emits the copy/dispose helpers for an ARC __block __weak variable.
+class ARCWeakByrefHelpers : public CodeGenModule::ByrefHelpers {
+public:
+  ARCWeakByrefHelpers(CharUnits alignment) : ByrefHelpers(alignment) {}
+
+  void emitCopy(CodeGenFunction &CGF, llvm::Value *destField,
+                llvm::Value *srcField) {
+    CGF.EmitARCMoveWeak(destField, srcField);
+  }
+
+  void emitDispose(CodeGenFunction &CGF, llvm::Value *field) {
+    CGF.EmitARCDestroyWeak(field);
+  }
+
+  void profileImpl(llvm::FoldingSetNodeID &id) const {
+    // 0 is distinguishable from all pointers and byref flags
+    id.AddInteger(0);
+  }
+};
+
+/// Emits the copy/dispose helpers for an ARC __block __strong variable
+/// that's not of block-pointer type.
+class ARCStrongByrefHelpers : public CodeGenModule::ByrefHelpers {
+public:
+  ARCStrongByrefHelpers(CharUnits alignment) : ByrefHelpers(alignment) {}
+
+  void emitCopy(CodeGenFunction &CGF, llvm::Value *destField,
+                llvm::Value *srcField) {
+    // Do a "move" by copying the value and then zeroing out the old
+    // variable.
+
+    llvm::Value *value = CGF.Builder.CreateLoad(srcField);
+    llvm::Value *null =
+      llvm::ConstantPointerNull::get(cast<llvm::PointerType>(value->getType()));
+    CGF.Builder.CreateStore(value, destField);
+    CGF.Builder.CreateStore(null, srcField);
+  }
+
+  void emitDispose(CodeGenFunction &CGF, llvm::Value *field) {
+    llvm::Value *value = CGF.Builder.CreateLoad(field);
+    CGF.EmitARCRelease(value, /*precise*/ false);
+  }
+
+  void profileImpl(llvm::FoldingSetNodeID &id) const {
+    // 1 is distinguishable from all pointers and byref flags
+    id.AddInteger(1);
+  }
+};
+
 /// Emits the copy/dispose helpers for a __block variable with a
 /// nontrivial copy constructor or destructor.
 class CXXByrefHelpers : public CodeGenModule::ByrefHelpers {
@@ -1318,6 +1436,7 @@ generateByrefCopyHelper(CodeGenFunction &CGF,
                                           SC_Static,
                                           SC_None,
                                           false, true);
+
   CGF.StartFunction(FD, R, Fn, FI, args, SourceLocation());
 
   if (byrefInfo.needsCopy()) {
@@ -1449,6 +1568,52 @@ CodeGenFunction::buildByrefHelpers(const llvm::StructType &byrefType,
     return ::buildByrefHelpers(CGM, byrefType, byrefInfo);
   }
 
+  // Otherwise, if we don't have a retainable type, there's nothing to do.
+  // that the runtime does extra copies.
+  if (!type->isObjCRetainableType()) return 0;
+
+  Qualifiers qs = type.getQualifiers();
+
+  // If we have lifetime, that dominates.
+  if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) {
+    assert(getLangOptions().ObjCAutoRefCount);
+
+    switch (lifetime) {
+    case Qualifiers::OCL_None: llvm_unreachable("impossible");
+
+    // These are just bits as far as the runtime is concerned.
+    case Qualifiers::OCL_ExplicitNone:
+    case Qualifiers::OCL_Autoreleasing:
+      return 0;
+
+    // Tell the runtime that this is ARC __weak, called by the
+    // byref routines.
+    case Qualifiers::OCL_Weak: {
+      ARCWeakByrefHelpers byrefInfo(emission.Alignment);
+      return ::buildByrefHelpers(CGM, byrefType, byrefInfo);
+    }
+
+    // ARC __strong __block variables need to be retained.
+    case Qualifiers::OCL_Strong:
+      // Block-pointers need to be _Block_copy'ed, so we let the
+      // runtime be in charge.  But we can't use the code below
+      // because we don't want to set BYREF_CALLER, which will
+      // just make the runtime ignore us.
+      if (type->isBlockPointerType()) {
+        BlockFieldFlags flags = BLOCK_FIELD_IS_BLOCK;
+        ObjectByrefHelpers byrefInfo(emission.Alignment, flags);
+        return ::buildByrefHelpers(CGM, byrefType, byrefInfo);
+
+      // Otherwise, we transfer ownership of the retain from the stack
+      // to the heap.
+      } else {
+        ARCStrongByrefHelpers byrefInfo(emission.Alignment);
+        return ::buildByrefHelpers(CGM, byrefType, byrefInfo);
+      }
+    }
+    llvm_unreachable("fell out of lifetime switch!");
+  }
+
   BlockFieldFlags flags;
   if (type->isBlockPointerType()) {
     flags |= BLOCK_FIELD_IS_BLOCK;
@@ -1639,6 +1804,7 @@ namespace {
     CallBlockRelease(llvm::Value *Addr) : Addr(Addr) {}
 
     void Emit(CodeGenFunction &CGF, bool IsForEH) {
+      // Should we be passing FIELD_IS_WEAK here?
       CGF.BuildBlockRelease(Addr, BLOCK_FIELD_IS_BYREF);
     }
   };

+ 1 - 1
lib/CodeGen/CGBlocks.h

@@ -89,7 +89,7 @@ enum BlockFieldFlag_t {
                                     variable */
   BLOCK_FIELD_IS_WEAK     = 0x10,  /* declared __weak, only used in byref copy
                                     helpers */
-
+  BLOCK_FIELD_IS_ARC      = 0x40,  /* field has ARC-specific semantics */
   BLOCK_BYREF_CALLER      = 128,   /* called from __block (byref) copy/dispose
                                       support routines */
   BLOCK_BYREF_CURRENT_MAX = 256

+ 264 - 10
lib/CodeGen/CGCall.cpp

@@ -25,6 +25,7 @@
 #include "llvm/Attributes.h"
 #include "llvm/Support/CallSite.h"
 #include "llvm/Target/TargetData.h"
+#include "llvm/InlineAsm.h"
 #include "llvm/Transforms/Utils/Local.h"
 using namespace clang;
 using namespace CodeGen;
@@ -190,13 +191,15 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(const ObjCMethodDecl *MD) {
          e = MD->param_end(); i != e; ++i) {
     ArgTys.push_back(Context.getCanonicalParamType((*i)->getType()));
   }
-  return getFunctionInfo(GetReturnType(MD->getResultType()),
-                         ArgTys,
-                         FunctionType::ExtInfo(
-                             /*NoReturn*/ false,
-                             /*HasRegParm*/ false,
-                             /*RegParm*/ 0,
-                             getCallingConventionForDecl(MD)));
+
+  FunctionType::ExtInfo einfo;
+  einfo = einfo.withCallingConv(getCallingConventionForDecl(MD));
+
+  if (getContext().getLangOptions().ObjCAutoRefCount &&
+      MD->hasAttr<NSReturnsRetainedAttr>())
+    einfo = einfo.withProducesResult(true);
+
+  return getFunctionInfo(GetReturnType(MD->getResultType()), ArgTys, einfo);
 }
 
 const CGFunctionInfo &CodeGenTypes::getFunctionInfo(GlobalDecl GD) {
@@ -262,7 +265,8 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy,
     return *FI;
 
   // Construct the function info.
-  FI = new CGFunctionInfo(CC, Info.getNoReturn(), Info.getHasRegParm(), Info.getRegParm(), ResTy,
+  FI = new CGFunctionInfo(CC, Info.getNoReturn(), Info.getProducesResult(),
+                          Info.getHasRegParm(), Info.getRegParm(), ResTy,
                           ArgTys.data(), ArgTys.size());
   FunctionInfos.InsertNode(FI, InsertPos);
 
@@ -291,13 +295,15 @@ const CGFunctionInfo &CodeGenTypes::getFunctionInfo(CanQualType ResTy,
 }
 
 CGFunctionInfo::CGFunctionInfo(unsigned _CallingConvention,
-                               bool _NoReturn, bool _HasRegParm, unsigned _RegParm,
+                               bool _NoReturn, bool returnsRetained,
+                               bool _HasRegParm, unsigned _RegParm,
                                CanQualType ResTy,
                                const CanQualType *ArgTys,
                                unsigned NumArgTys)
   : CallingConvention(_CallingConvention),
     EffectiveCallingConvention(_CallingConvention),
-    NoReturn(_NoReturn), HasRegParm(_HasRegParm), RegParm(_RegParm)
+    NoReturn(_NoReturn), ReturnsRetained(returnsRetained),
+    HasRegParm(_HasRegParm), RegParm(_RegParm)
 {
   NumArgs = NumArgTys;
 
@@ -1068,6 +1074,95 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
   assert(AI == Fn->arg_end() && "Argument mismatch!");
 }
 
+/// Try to emit a fused autorelease of a return result.
+static llvm::Value *tryEmitFusedAutoreleaseOfResult(CodeGenFunction &CGF,
+                                                    llvm::Value *result) {
+  // We must be immediately followed the cast.
+  llvm::BasicBlock *BB = CGF.Builder.GetInsertBlock();
+  if (BB->empty()) return 0;
+  if (&BB->back() != result) return 0;
+
+  const llvm::Type *resultType = result->getType();
+
+  // result is in a BasicBlock and is therefore an Instruction.
+  llvm::Instruction *generator = cast<llvm::Instruction>(result);
+
+  llvm::SmallVector<llvm::Instruction*,4> insnsToKill;
+
+  // Look for:
+  //  %generator = bitcast %type1* %generator2 to %type2*
+  while (llvm::BitCastInst *bitcast = dyn_cast<llvm::BitCastInst>(generator)) {
+    // We would have emitted this as a constant if the operand weren't
+    // an Instruction.
+    generator = cast<llvm::Instruction>(bitcast->getOperand(0));
+
+    // Require the generator to be immediately followed by the cast.
+    if (generator->getNextNode() != bitcast)
+      return 0;
+
+    insnsToKill.push_back(bitcast);
+  }
+
+  // Look for:
+  //   %generator = call i8* @objc_retain(i8* %originalResult)
+  // or
+  //   %generator = call i8* @objc_retainAutoreleasedReturnValue(i8* %originalResult)
+  llvm::CallInst *call = dyn_cast<llvm::CallInst>(generator);
+  if (!call) return 0;
+
+  bool doRetainAutorelease;
+
+  if (call->getCalledValue() == CGF.CGM.getARCEntrypoints().objc_retain) {
+    doRetainAutorelease = true;
+  } else if (call->getCalledValue() == CGF.CGM.getARCEntrypoints()
+                                          .objc_retainAutoreleasedReturnValue) {
+    doRetainAutorelease = false;
+
+    // Look for an inline asm immediately preceding the call and kill it, too.
+    llvm::Instruction *prev = call->getPrevNode();
+    if (llvm::CallInst *asmCall = dyn_cast_or_null<llvm::CallInst>(prev))
+      if (asmCall->getCalledValue()
+            == CGF.CGM.getARCEntrypoints().retainAutoreleasedReturnValueMarker)
+        insnsToKill.push_back(prev);
+  } else {
+    return 0;
+  }
+
+  result = call->getArgOperand(0);
+  insnsToKill.push_back(call);
+
+  // Keep killing bitcasts, for sanity.  Note that we no longer care
+  // about precise ordering as long as there's exactly one use.
+  while (llvm::BitCastInst *bitcast = dyn_cast<llvm::BitCastInst>(result)) {
+    if (!bitcast->hasOneUse()) break;
+    insnsToKill.push_back(bitcast);
+    result = bitcast->getOperand(0);
+  }
+
+  // Delete all the unnecessary instructions, from latest to earliest.
+  for (llvm::SmallVectorImpl<llvm::Instruction*>::iterator
+         i = insnsToKill.begin(), e = insnsToKill.end(); i != e; ++i)
+    (*i)->eraseFromParent();
+
+  // Do the fused retain/autorelease if we were asked to.
+  if (doRetainAutorelease)
+    result = CGF.EmitARCRetainAutoreleaseReturnValue(result);
+
+  // Cast back to the result type.
+  return CGF.Builder.CreateBitCast(result, resultType);
+}
+
+/// Emit an ARC autorelease of the result of a function.
+static llvm::Value *emitAutoreleaseOfResult(CodeGenFunction &CGF,
+                                            llvm::Value *result) {
+  // At -O0, try to emit a fused retain/autorelease.
+  if (CGF.shouldUseFusedARCCalls())
+    if (llvm::Value *fused = tryEmitFusedAutoreleaseOfResult(CGF, result))
+      return fused;
+
+  return CGF.EmitARCAutoreleaseReturnValue(result);
+}
+
 void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI) {
   // Functions with no result always return void.
   if (ReturnValue == 0) {
@@ -1135,6 +1230,16 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI) {
 
       RV = CreateCoercedLoad(V, RetAI.getCoerceToType(), *this);
     }
+
+    // In ARC, end functions that return a retainable type with a call
+    // to objc_autoreleaseReturnValue.
+    if (AutoreleaseResult) {
+      assert(getLangOptions().ObjCAutoRefCount &&
+             !FI.isReturnsRetained() &&
+             RetTy->isObjCRetainableType());
+      RV = emitAutoreleaseOfResult(*this, RV);
+    }
+
     break;
 
   case ABIArgInfo::Ignore:
@@ -1184,8 +1289,152 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args,
   return args.add(RValue::get(value), type);
 }
 
+static bool isProvablyNull(llvm::Value *addr) {
+  return isa<llvm::ConstantPointerNull>(addr);
+}
+
+static bool isProvablyNonNull(llvm::Value *addr) {
+  return isa<llvm::AllocaInst>(addr);
+}
+
+/// Emit the actual writing-back of a writeback.
+static void emitWriteback(CodeGenFunction &CGF,
+                          const CallArgList::Writeback &writeback) {
+  llvm::Value *srcAddr = writeback.Address;
+  assert(!isProvablyNull(srcAddr) &&
+         "shouldn't have writeback for provably null argument");
+
+  llvm::BasicBlock *contBB = 0;
+
+  // If the argument wasn't provably non-null, we need to null check
+  // before doing the store.
+  bool provablyNonNull = isProvablyNonNull(srcAddr);
+  if (!provablyNonNull) {
+    llvm::BasicBlock *writebackBB = CGF.createBasicBlock("icr.writeback");
+    contBB = CGF.createBasicBlock("icr.done");
+
+    llvm::Value *isNull = CGF.Builder.CreateIsNull(srcAddr, "icr.isnull");
+    CGF.Builder.CreateCondBr(isNull, contBB, writebackBB);
+    CGF.EmitBlock(writebackBB);
+  }
+
+  // Load the value to writeback.
+  llvm::Value *value = CGF.Builder.CreateLoad(writeback.Temporary);
+
+  // Cast it back, in case we're writing an id to a Foo* or something.
+  value = CGF.Builder.CreateBitCast(value,
+               cast<llvm::PointerType>(srcAddr->getType())->getElementType(),
+                            "icr.writeback-cast");
+  
+  // Perform the writeback.
+  QualType srcAddrType = writeback.AddressType;
+  CGF.EmitStoreThroughLValue(RValue::get(value),
+                             CGF.MakeAddrLValue(srcAddr, srcAddrType),
+                             srcAddrType);
+
+  // Jump to the continuation block.
+  if (!provablyNonNull)
+    CGF.EmitBlock(contBB);
+}
+
+static void emitWritebacks(CodeGenFunction &CGF,
+                           const CallArgList &args) {
+  for (CallArgList::writeback_iterator
+         i = args.writeback_begin(), e = args.writeback_end(); i != e; ++i)
+    emitWriteback(CGF, *i);
+}
+
+/// Emit an argument that's being passed call-by-writeback.  That is,
+/// we are passing the address of 
+static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args,
+                             const ObjCIndirectCopyRestoreExpr *CRE) {
+  llvm::Value *srcAddr = CGF.EmitScalarExpr(CRE->getSubExpr());
+
+  // The dest and src types don't necessarily match in LLVM terms
+  // because of the crazy ObjC compatibility rules.
+
+  const llvm::PointerType *destType =
+    cast<llvm::PointerType>(CGF.ConvertType(CRE->getType()));
+
+  // If the address is a constant null, just pass the appropriate null.
+  if (isProvablyNull(srcAddr)) {
+    args.add(RValue::get(llvm::ConstantPointerNull::get(destType)),
+             CRE->getType());
+    return;
+  }
+
+  QualType srcAddrType =
+    CRE->getSubExpr()->getType()->castAs<PointerType>()->getPointeeType();
+
+  // Create the temporary.
+  llvm::Value *temp = CGF.CreateTempAlloca(destType->getElementType(),
+                                           "icr.temp");
+
+  // Zero-initialize it if we're not doing a copy-initialization.
+  bool shouldCopy = CRE->shouldCopy();
+  if (!shouldCopy) {
+    llvm::Value *null =
+      llvm::ConstantPointerNull::get(
+        cast<llvm::PointerType>(destType->getElementType()));
+    CGF.Builder.CreateStore(null, temp);
+  }
+
+  llvm::BasicBlock *contBB = 0;
+
+  // If the address is *not* known to be non-null, we need to switch.
+  llvm::Value *finalArgument;
+
+  bool provablyNonNull = isProvablyNonNull(srcAddr);
+  if (provablyNonNull) {
+    finalArgument = temp;
+  } else {
+    llvm::Value *isNull = CGF.Builder.CreateIsNull(srcAddr, "icr.isnull");
+
+    finalArgument = CGF.Builder.CreateSelect(isNull, 
+                                   llvm::ConstantPointerNull::get(destType),
+                                             temp, "icr.argument");
+
+    // If we need to copy, then the load has to be conditional, which
+    // means we need control flow.
+    if (shouldCopy) {
+      contBB = CGF.createBasicBlock("icr.cont");
+      llvm::BasicBlock *copyBB = CGF.createBasicBlock("icr.copy");
+      CGF.Builder.CreateCondBr(isNull, contBB, copyBB);
+      CGF.EmitBlock(copyBB);
+    }
+  }
+
+  // Perform a copy if necessary.
+  if (shouldCopy) {
+    LValue srcLV = CGF.MakeAddrLValue(srcAddr, srcAddrType);
+    RValue srcRV = CGF.EmitLoadOfLValue(srcLV, srcAddrType);
+    assert(srcRV.isScalar());
+
+    llvm::Value *src = srcRV.getScalarVal();
+    src = CGF.Builder.CreateBitCast(src, destType->getElementType(),
+                                    "icr.cast");
+
+    // Use an ordinary store, not a store-to-lvalue.
+    CGF.Builder.CreateStore(src, temp);
+  }
+
+  // Finish the control flow if we needed it.
+  if (shouldCopy && !provablyNonNull)
+    CGF.EmitBlock(contBB);
+
+  args.addWriteback(srcAddr, srcAddrType, temp);
+  args.add(RValue::get(finalArgument), CRE->getType());
+}
+
 void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
                                   QualType type) {
+  if (const ObjCIndirectCopyRestoreExpr *CRE
+        = dyn_cast<ObjCIndirectCopyRestoreExpr>(E)) {
+    assert(getContext().getLangOptions().ObjCAutoRefCount);
+    assert(getContext().hasSameType(E->getType(), type));
+    return emitWritebackArg(*this, args, CRE);
+  }
+
   if (type->isReferenceType())
     return args.add(EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0),
                     type);
@@ -1435,6 +1684,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
   if (Builder.isNamePreserving() && !CI->getType()->isVoidTy())
     CI->setName("call");
 
+  // Emit any writebacks immediately.  Arguably this should happen
+  // after any return-value munging.
+  if (CallArgs.hasWritebacks())
+    emitWritebacks(*this, CallArgs);
+
   switch (RetAI.getKind()) {
   case ABIArgInfo::Indirect: {
     unsigned Alignment = getContext().getTypeAlignInChars(RetTy).getQuantity();

+ 46 - 1
lib/CodeGen/CGCall.h

@@ -58,9 +58,44 @@ namespace CodeGen {
   class CallArgList :
     public llvm::SmallVector<CallArg, 16> {
   public:
+    struct Writeback {
+      /// The original argument.
+      llvm::Value *Address;
+
+      /// The pointee type of the original argument.
+      QualType AddressType;
+
+      /// The temporary alloca.
+      llvm::Value *Temporary;
+    };
+
     void add(RValue rvalue, QualType type, bool needscopy = false) {
       push_back(CallArg(rvalue, type, needscopy));
     }
+
+    void addFrom(const CallArgList &other) {
+      insert(end(), other.begin(), other.end());
+      Writebacks.insert(Writebacks.end(),
+                        other.Writebacks.begin(), other.Writebacks.end());
+    }
+
+    void addWriteback(llvm::Value *address, QualType addressType,
+                      llvm::Value *temporary) {
+      Writeback writeback;
+      writeback.Address = address;
+      writeback.AddressType = addressType;
+      writeback.Temporary = temporary;
+      Writebacks.push_back(writeback);
+    }
+
+    bool hasWritebacks() const { return !Writebacks.empty(); }
+
+    typedef llvm::SmallVectorImpl<Writeback>::const_iterator writeback_iterator;
+    writeback_iterator writeback_begin() const { return Writebacks.begin(); }
+    writeback_iterator writeback_end() const { return Writebacks.end(); }
+
+  private:
+    llvm::SmallVector<Writeback, 1> Writebacks;
   };
 
   /// FunctionArgList - Type for representing both the decl and type
@@ -88,6 +123,9 @@ namespace CodeGen {
     /// Whether this function is noreturn.
     bool NoReturn;
 
+    /// Whether this function is returns-retained.
+    bool ReturnsRetained;
+
     unsigned NumArgs;
     ArgInfo *Args;
 
@@ -100,7 +138,8 @@ namespace CodeGen {
     typedef ArgInfo *arg_iterator;
 
     CGFunctionInfo(unsigned CallingConvention, bool NoReturn,
-                   bool HasRegParm, unsigned RegParm, CanQualType ResTy,
+                   bool ReturnsRetained, bool HasRegParm, unsigned RegParm,
+                   CanQualType ResTy,
                    const CanQualType *ArgTys, unsigned NumArgTys);
     ~CGFunctionInfo() { delete[] Args; }
 
@@ -113,6 +152,10 @@ namespace CodeGen {
 
     bool isNoReturn() const { return NoReturn; }
 
+    /// In ARR, whether this function retains its return value.  This
+    /// is not always reliable for call sites.
+    bool isReturnsRetained() const { return ReturnsRetained; }
+
     /// getCallingConvention - Return the user specified calling
     /// convention.
     unsigned getCallingConvention() const { return CallingConvention; }
@@ -137,6 +180,7 @@ namespace CodeGen {
     void Profile(llvm::FoldingSetNodeID &ID) {
       ID.AddInteger(getCallingConvention());
       ID.AddBoolean(NoReturn);
+      ID.AddBoolean(ReturnsRetained);
       ID.AddBoolean(HasRegParm);
       ID.AddInteger(RegParm);
       getReturnType().Profile(ID);
@@ -151,6 +195,7 @@ namespace CodeGen {
                         Iterator end) {
       ID.AddInteger(Info.getCC());
       ID.AddBoolean(Info.getNoReturn());
+      ID.AddBoolean(Info.getProducesResult());
       ID.AddBoolean(Info.getHasRegParm());
       ID.AddInteger(Info.getRegParm());
       ResTy.Profile(ID);

+ 56 - 37
lib/CodeGen/CGClass.cpp

@@ -398,7 +398,8 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
                                               BaseClassDecl,
                                               isBaseVirtual);
 
-  AggValueSlot AggSlot = AggValueSlot::forAddr(V, false, /*Lifetime*/ true);
+  AggValueSlot AggSlot = AggValueSlot::forAddr(V, Qualifiers(), 
+                                               /*Lifetime*/ true);
 
   CGF.EmitAggExpr(BaseInit->getInit(), AggSlot);
   
@@ -428,10 +429,20 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF,
       CGF.Builder.CreateStore(Next, ArrayIndexVar);      
     }
 
-    AggValueSlot Slot = AggValueSlot::forAddr(Dest, LHS.isVolatileQualified(),
-                                              /*Lifetime*/ true);
-    
-    CGF.EmitAggExpr(MemberInit->getInit(), Slot);
+    if (!CGF.hasAggregateLLVMType(T)) {
+      CGF.EmitScalarInit(MemberInit->getInit(), 0, Dest, false, 
+                         LHS.isVolatileQualified(), 
+                         CGF.getContext().getTypeAlign(T),
+                         T);
+    } else if (T->isAnyComplexType()) {
+      CGF.EmitComplexExprIntoAddr(MemberInit->getInit(), Dest, 
+                                  LHS.isVolatileQualified());
+    } else {    
+      AggValueSlot Slot = AggValueSlot::forAddr(Dest, LHS.getQuals(),
+                                                /*Lifetime*/ true);
+      
+      CGF.EmitAggExpr(MemberInit->getInit(), Slot);
+    }
     
     return;
   }
@@ -540,15 +551,16 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
 
   // FIXME: If there's no initializer and the CXXCtorInitializer
   // was implicitly generated, we shouldn't be zeroing memory.
-  RValue RHS;
-  if (FieldType->isReferenceType()) {
-    RHS = CGF.EmitReferenceBindingToExpr(MemberInit->getInit(), Field);
-    CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
-  } else if (FieldType->isArrayType() && !MemberInit->getInit()) {
+  if (FieldType->isArrayType() && !MemberInit->getInit()) {
     CGF.EmitNullInitialization(LHS.getAddress(), Field->getType());
   } else if (!CGF.hasAggregateLLVMType(Field->getType())) {
-    RHS = RValue::get(CGF.EmitScalarExpr(MemberInit->getInit()));
-    CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
+    if (LHS.isSimple()) {
+      CGF.EmitExprAsInit(MemberInit->getInit(), Field, LHS.getAddress(),
+                         CGF.getContext().getDeclAlign(Field), false);
+    } else {
+      RValue RHS = RValue::get(CGF.EmitScalarExpr(MemberInit->getInit()));
+      CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
+    }
   } else if (MemberInit->getInit()->getType()->isAnyComplexType()) {
     CGF.EmitComplexExprIntoAddr(MemberInit->getInit(), LHS.getAddress(),
                                 LHS.isVolatileQualified());
@@ -576,11 +588,11 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
       llvm::Value *Zero = llvm::Constant::getNullValue(SizeTy);
       CGF.Builder.CreateStore(Zero, ArrayIndexVar);
       
-      // If we are copying an array of scalars or classes with trivial copy 
+      // If we are copying an array of PODs or classes with trivial copy 
       // constructors, perform a single aggregate copy.
-      const RecordType *Record = BaseElementTy->getAs<RecordType>();
-      if (!Record || 
-          cast<CXXRecordDecl>(Record->getDecl())->hasTrivialCopyConstructor()) {
+      const CXXRecordDecl *Record = BaseElementTy->getAsCXXRecordDecl();
+      if (BaseElementTy.isPODType(CGF.getContext()) ||
+          (Record && Record->hasTrivialCopyConstructor())) {
         // Find the source pointer. We knows it's the last argument because
         // we know we're in a copy constructor.
         unsigned SrcArgIndex = Args.size() - 1;
@@ -925,12 +937,8 @@ namespace {
     CallArrayFieldDtor(const FieldDecl *Field) : Field(Field) {}
 
     void Emit(CodeGenFunction &CGF, bool IsForEH) {
-      QualType FieldType = Field->getType();
-      const ConstantArrayType *Array =
-        CGF.getContext().getAsConstantArrayType(FieldType);
-      
-      QualType BaseType =
-        CGF.getContext().getBaseElementType(Array->getElementType());
+      QualType FieldType = Field->getType();      
+      QualType BaseType = CGF.getContext().getBaseElementType(FieldType);
       const CXXRecordDecl *FieldClassDecl = BaseType->getAsCXXRecordDecl();
 
       llvm::Value *ThisPtr = CGF.LoadCXXThis();
@@ -938,9 +946,12 @@ namespace {
                                           // FIXME: Qualifiers?
                                           /*CVRQualifiers=*/0);
 
-      const llvm::Type *BasePtr = CGF.ConvertType(BaseType)->getPointerTo();
-      llvm::Value *BaseAddrPtr =
-        CGF.Builder.CreateBitCast(LHS.getAddress(), BasePtr);
+      const llvm::Type *BasePtr 
+        = CGF.ConvertType(BaseType)->getPointerTo();
+      llvm::Value *BaseAddrPtr
+        = CGF.Builder.CreateBitCast(LHS.getAddress(), BasePtr);
+      const ConstantArrayType *Array
+        = CGF.getContext().getAsConstantArrayType(FieldType);
       CGF.EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(),
                                     Array, BaseAddrPtr);
     }
@@ -1042,19 +1053,26 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
       getContext().getAsConstantArrayType(FieldType);
     if (Array)
       FieldType = getContext().getBaseElementType(Array->getElementType());
-    
-    const RecordType *RT = FieldType->getAs<RecordType>();
-    if (!RT)
+
+    switch (FieldType.isDestructedType()) {
+    case QualType::DK_none:
       continue;
-    
-    CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
-    if (FieldClassDecl->hasTrivialDestructor())
-        continue;
+        
+    case QualType::DK_cxx_destructor:
+      if (Array)
+        EHStack.pushCleanup<CallArrayFieldDtor>(NormalAndEHCleanup, Field);
+      else
+        EHStack.pushCleanup<CallFieldDtor>(NormalAndEHCleanup, Field);
+      break;
+        
+    case QualType::DK_objc_strong_lifetime:
+      PushARCFieldReleaseCleanup(getARCCleanupKind(), Field);
+      break;
 
-    if (Array)
-      EHStack.pushCleanup<CallArrayFieldDtor>(NormalAndEHCleanup, Field);
-    else
-      EHStack.pushCleanup<CallFieldDtor>(NormalAndEHCleanup, Field);
+    case QualType::DK_objc_weak_lifetime:
+      PushARCFieldWeakReleaseCleanup(getARCCleanupKind(), Field);
+      break;
+    }
   }
 }
 
@@ -1384,7 +1402,8 @@ CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor
 
   llvm::Value *ThisPtr = LoadCXXThis();
 
-  AggValueSlot AggSlot = AggValueSlot::forAddr(ThisPtr, false, /*Lifetime*/ true);
+  AggValueSlot AggSlot =
+    AggValueSlot::forAddr(ThisPtr, Qualifiers(), /*Lifetime*/ true);
 
   EmitAggExpr(Ctor->init_begin()[0]->getInit(), AggSlot);
 

+ 1 - 0
lib/CodeGen/CGDebugInfo.cpp

@@ -389,6 +389,7 @@ llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) {
   // Ignore these qualifiers for now.
   Qc.removeObjCGCAttr();
   Qc.removeAddressSpace();
+  Qc.removeObjCLifetime();
 
   // We will create one Derived type for one qualifier and recurse to handle any
   // additional ones.

+ 240 - 16
lib/CodeGen/CGDecl.cpp

@@ -353,9 +353,7 @@ namespace {
       if (NRVO) CGF.EmitBlock(SkipDtorBB);
     }
   };
-}
 
-namespace {
   struct CallStackRestore : EHScopeStack::Cleanup {
     llvm::Value *Stack;
     CallStackRestore(llvm::Value *Stack) : Stack(Stack) {}
@@ -400,6 +398,164 @@ namespace {
   };
 }
 
+/// EmitAutoVarWithLifetime - Does the setup required for an automatic
+/// variable with lifetime.
+static void EmitAutoVarWithLifetime(CodeGenFunction &CGF, const VarDecl &var,
+                                    llvm::Value *addr,
+                                    Qualifiers::ObjCLifetime lifetime) {
+  switch (lifetime) {
+  case Qualifiers::OCL_None:
+    llvm_unreachable("present but none");
+
+  case Qualifiers::OCL_ExplicitNone:
+    // nothing to do
+    break;
+
+  case Qualifiers::OCL_Strong: {
+    CGF.PushARCReleaseCleanup(CGF.getARCCleanupKind(),
+                              var.getType(), addr,
+                              var.hasAttr<ObjCPreciseLifetimeAttr>());
+    break;
+  }
+  case Qualifiers::OCL_Autoreleasing:
+    // nothing to do
+    break;
+ 
+  case Qualifiers::OCL_Weak:
+    // __weak objects always get EH cleanups; otherwise, exceptions
+    // could cause really nasty crashes instead of mere leaks.
+    CGF.PushARCWeakReleaseCleanup(NormalAndEHCleanup, var.getType(), addr);
+    break;
+  }
+}
+
+static bool isAccessedBy(const VarDecl &var, const Stmt *s) {
+  if (const Expr *e = dyn_cast<Expr>(s)) {
+    // Skip the most common kinds of expressions that make
+    // hierarchy-walking expensive.
+    s = e = e->IgnoreParenCasts();
+
+    if (const DeclRefExpr *ref = dyn_cast<DeclRefExpr>(e))
+      return (ref->getDecl() == &var);
+  }
+
+  for (Stmt::const_child_range children = s->children(); children; ++children)
+    if (isAccessedBy(var, *children))
+      return true;
+
+  return false;
+}
+
+static bool isAccessedBy(const ValueDecl *decl, const Expr *e) {
+  if (!decl) return false;
+  if (!isa<VarDecl>(decl)) return false;
+  const VarDecl *var = cast<VarDecl>(decl);
+  return isAccessedBy(*var, e);
+}
+
+void CodeGenFunction::EmitScalarInit(const Expr *init,
+                                     const ValueDecl *D,
+                                     llvm::Value *addr, bool capturedByInit,
+                                     bool isVolatile, unsigned alignment, 
+                                     QualType type) {
+  Qualifiers::ObjCLifetime lifetime = type.getQualifiers().getObjCLifetime();
+  if (!lifetime) {
+    llvm::Value *value = EmitScalarExpr(init);
+    if (capturedByInit) addr = BuildBlockByrefAddress(addr, cast<VarDecl>(D));
+    EmitStoreOfScalar(value, addr, isVolatile, alignment, type);
+    return;
+  }
+
+  // If we're emitting a value with lifetime, we have to do the
+  // initialization *before* we leave the cleanup scopes.
+  CodeGenFunction::RunCleanupsScope Scope(*this);
+  if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(init))
+    init = ewc->getSubExpr();
+
+  // We have to maintain the illusion that the variable is
+  // zero-initialized.  If the variable might be accessed in its
+  // initializer, zero-initialize before running the initializer, then
+  // actually perform the initialization with an assign.
+  bool accessedByInit = false;
+  if (lifetime != Qualifiers::OCL_ExplicitNone)
+    accessedByInit = isAccessedBy(D, init);
+  if (accessedByInit) {
+    // Drill down to the __block object if necessary.
+    llvm::Value *tempAddr = addr;
+    if (capturedByInit) {
+      // We can use a simple GEP for this because it can't have been
+      // moved yet.
+      tempAddr = Builder.CreateStructGEP(tempAddr,
+                                   getByRefValueLLVMField(cast<VarDecl>(D)));
+    }
+
+    const llvm::PointerType *ty = cast<llvm::PointerType>(tempAddr->getType());
+    ty = cast<llvm::PointerType>(ty->getElementType());
+
+    llvm::Value *zero = llvm::ConstantPointerNull::get(ty);
+    
+    // If __weak, we want to use a barrier under certain conditions.
+    if (lifetime == Qualifiers::OCL_Weak)
+      EmitARCInitWeak(tempAddr, zero);
+
+    // Otherwise just do a simple store.
+    else
+      EmitStoreOfScalar(zero, tempAddr, isVolatile, alignment, type);
+  }
+
+  // Emit the initializer.
+  llvm::Value *value = 0;
+
+  switch (lifetime) {
+  case Qualifiers::OCL_None:
+    llvm_unreachable("present but none");
+
+  case Qualifiers::OCL_ExplicitNone:
+    // nothing to do
+    value = EmitScalarExpr(init);
+    break;
+
+  case Qualifiers::OCL_Strong: {
+    value = EmitARCRetainScalarExpr(init);
+    break;
+  }
+
+  case Qualifiers::OCL_Weak: {
+    // No way to optimize a producing initializer into this.  It's not
+    // worth optimizing for, because the value will immediately
+    // disappear in the common case.
+    value = EmitScalarExpr(init);
+
+    if (capturedByInit) addr = BuildBlockByrefAddress(addr, cast<VarDecl>(D));
+    if (accessedByInit)
+      EmitARCStoreWeak(addr, value, /*ignored*/ true);
+    else
+      EmitARCInitWeak(addr, value);
+    return;
+  }
+
+  case Qualifiers::OCL_Autoreleasing:
+    value = EmitARCRetainAutoreleaseScalarExpr(init);
+    break;
+  }
+
+  if (capturedByInit) addr = BuildBlockByrefAddress(addr, cast<VarDecl>(D));
+
+  llvm::MDNode *tbaa = CGM.getTBAAInfo(type);
+
+  // If the variable might have been accessed by its initializer, we
+  // might have to initialize with a barrier.  We have to do this for
+  // both __weak and __strong, but __weak got filtered out above.
+  if (accessedByInit && lifetime == Qualifiers::OCL_Strong) {
+    llvm::Value *oldValue
+      = EmitLoadOfScalar(addr, isVolatile, alignment, type, tbaa);
+    EmitStoreOfScalar(value, addr, isVolatile, alignment, type, tbaa);
+    EmitARCRelease(oldValue, /*precise*/ false);
+    return;
+  }
+
+  EmitStoreOfScalar(value, addr, isVolatile, alignment, type, tbaa);  
+}
 
 /// canEmitInitWithFewStoresAfterMemset - Decide whether we can emit the
 /// non-zero parts of the specified initializer with equal or fewer than
@@ -521,7 +677,9 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) {
       // arrays as long as the initialization is trivial (e.g. if they
       // have a non-trivial destructor, but not a non-trivial constructor).
       if (D.getInit() &&
-          (Ty->isArrayType() || Ty->isRecordType()) && Ty->isPODType() &&
+          (Ty->isArrayType() || Ty->isRecordType()) && 
+          (Ty.isPODType(getContext()) ||
+           getContext().getBaseElementType(Ty)->isObjCObjectPointerType()) &&
           D.getInit()->isConstantInitializer(getContext(), false)) {
 
         // If the variable's a const type, and it's neither an NRVO
@@ -765,29 +923,30 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
 /// \param capturedByInit true if the variable is a __block variable
 ///   whose address is potentially changed by the initializer
 void CodeGenFunction::EmitExprAsInit(const Expr *init,
-                                     const VarDecl *var,
+                                     const ValueDecl *D,
                                      llvm::Value *loc,
                                      CharUnits alignment,
                                      bool capturedByInit) {
-  QualType type = var->getType();
+  QualType type = D->getType();
   bool isVolatile = type.isVolatileQualified();
 
   if (type->isReferenceType()) {
-    RValue RV = EmitReferenceBindingToExpr(init, var);
-    if (capturedByInit) loc = BuildBlockByrefAddress(loc, var);
+    RValue RV = EmitReferenceBindingToExpr(init, D);
+    if (capturedByInit) 
+      loc = BuildBlockByrefAddress(loc, cast<VarDecl>(D));
     EmitStoreOfScalar(RV.getScalarVal(), loc, false,
                       alignment.getQuantity(), type);
   } else if (!hasAggregateLLVMType(type)) {
-    llvm::Value *V = EmitScalarExpr(init);
-    if (capturedByInit) loc = BuildBlockByrefAddress(loc, var);
-    EmitStoreOfScalar(V, loc, isVolatile, alignment.getQuantity(), type);
+    EmitScalarInit(init, D, loc, capturedByInit, isVolatile,
+                   alignment.getQuantity(), type);
   } else if (type->isAnyComplexType()) {
     ComplexPairTy complex = EmitComplexExpr(init);
-    if (capturedByInit) loc = BuildBlockByrefAddress(loc, var);
+    if (capturedByInit) loc = BuildBlockByrefAddress(loc, cast<VarDecl>(D));
     StoreComplexToAddr(complex, loc, isVolatile);
   } else {
     // TODO: how can we delay here if D is captured by its initializer?
-    EmitAggExpr(init, AggValueSlot::forAddr(loc, isVolatile, true, false));
+    EmitAggExpr(init, AggValueSlot::forAddr(loc, type.getQualifiers(), true, 
+                                            false));
   }
 }
 
@@ -799,7 +958,7 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
 
   const VarDecl &D = *emission.Variable;
 
-  // Handle C++ destruction of variables.
+  // Handle C++ or ARC destruction of variables.
   if (getLangOptions().CPlusPlus) {
     QualType type = D.getType();
     QualType baseType = getContext().getBaseElementType(type);
@@ -830,6 +989,12 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
     }
   }
 
+  if (Qualifiers::ObjCLifetime lifetime
+        = D.getType().getQualifiers().getObjCLifetime()) {
+    llvm::Value *loc = emission.getObjectAddress(*this);
+    EmitAutoVarWithLifetime(*this, D, loc, lifetime);
+  }
+
   // Handle the cleanup attribute.
   if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) {
     const FunctionDecl *FD = CA->getFunctionDecl();
@@ -847,6 +1012,22 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
     enterByrefCleanup(emission);
 }
 
+namespace {
+  /// A cleanup to perform a release of an object at the end of a
+  /// function.  This is used to balance out the incoming +1 of a
+  /// ns_consumed argument when we can't reasonably do that just by
+  /// not doing the initial retain for a __block argument.
+  struct ConsumeARCParameter : EHScopeStack::Cleanup {
+    ConsumeARCParameter(llvm::Value *param) : Param(param) {}
+
+    llvm::Value *Param;
+
+    void Emit(CodeGenFunction &CGF, bool IsForEH) {
+      CGF.EmitARCRelease(Param, /*precise*/ false);
+    }
+  };
+}
+
 /// Emit an alloca (or GlobalValue depending on target)
 /// for the specified parameter and set up LocalDeclMap.
 void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg,
@@ -883,10 +1064,53 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg,
     // Otherwise, create a temporary to hold the value.
     DeclPtr = CreateMemTemp(Ty, D.getName() + ".addr");
 
+    bool doStore = true;
+
+    Qualifiers qs = Ty.getQualifiers();
+
+    if (Qualifiers::ObjCLifetime lt = qs.getObjCLifetime()) {
+      // We honor __attribute__((ns_consumed)) for types with lifetime.
+      // For __strong, it's handled by just skipping the initial retain;
+      // otherwise we have to balance out the initial +1 with an extra
+      // cleanup to do the release at the end of the function.
+      bool isConsumed = D.hasAttr<NSConsumedAttr>();
+
+      // 'self' is always formally __strong, but if this is not an
+      // init method then we don't want to retain it.
+      if (lt == Qualifiers::OCL_Strong && qs.hasConst() &&
+          isa<ImplicitParamDecl>(D)) {
+        const ObjCMethodDecl *method = cast<ObjCMethodDecl>(CurCodeDecl);
+        assert(&D == method->getSelfDecl());
+        assert(method->getMethodFamily() != OMF_init);
+        lt = Qualifiers::OCL_ExplicitNone;
+      }
+
+      if (lt == Qualifiers::OCL_Strong) {
+        if (!isConsumed)
+          // Don't use objc_retainBlock for block pointers, because we
+          // don't want to Block_copy something just because we got it
+          // as a parameter.
+          Arg = EmitARCRetainNonBlock(Arg);
+      } else {
+        // Push the cleanup for a consumed parameter.
+        if (isConsumed)
+          EHStack.pushCleanup<ConsumeARCParameter>(getARCCleanupKind(), Arg);
+
+        if (lt == Qualifiers::OCL_Weak) {
+          EmitARCInitWeak(DeclPtr, Arg);
+          doStore = false; // The weak init is a store, no need to do two
+        }
+      }
+
+      // Enter the cleanup scope.
+      EmitAutoVarWithLifetime(*this, D, DeclPtr, lt);
+    }
+
     // Store the initial value into the alloca.
-    EmitStoreOfScalar(Arg, DeclPtr, Ty.isVolatileQualified(),
-                      getContext().getDeclAlign(&D).getQuantity(), Ty,
-                      CGM.getTBAAInfo(Ty));
+    if (doStore)
+      EmitStoreOfScalar(Arg, DeclPtr, Ty.isVolatileQualified(),
+                        getContext().getDeclAlign(&D).getQuantity(), Ty,
+                        CGM.getTBAAInfo(Ty));
   }
 
   llvm::Value *&DMEntry = LocalDeclMap[&D];

+ 20 - 7
lib/CodeGen/CGDeclCXX.cpp

@@ -34,20 +34,22 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D,
 
   unsigned Alignment = Context.getDeclAlign(&D).getQuantity();
   if (!CGF.hasAggregateLLVMType(T)) {
-    llvm::Value *V = CGF.EmitScalarExpr(Init);
     CodeGenModule &CGM = CGF.CGM;
     Qualifiers::GC GCAttr = CGM.getContext().getObjCGCAttrKind(T);
     if (GCAttr == Qualifiers::Strong)
-      CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, V, DeclPtr,
-                                                D.isThreadSpecified());
+      CGM.getObjCRuntime().EmitObjCGlobalAssign(CGF, CGF.EmitScalarExpr(Init),
+                                                DeclPtr, D.isThreadSpecified());
     else if (GCAttr == Qualifiers::Weak)
-      CGM.getObjCRuntime().EmitObjCWeakAssign(CGF, V, DeclPtr);
+        CGM.getObjCRuntime().EmitObjCWeakAssign(CGF, CGF.EmitScalarExpr(Init),
+                                                DeclPtr);
     else
-      CGF.EmitStoreOfScalar(V, DeclPtr, isVolatile, Alignment, T);
+      CGF.EmitScalarInit(Init, &D, DeclPtr, false, isVolatile, Alignment,
+                         D.getType());
   } else if (T->isAnyComplexType()) {
     CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile);
   } else {
-    CGF.EmitAggExpr(Init, AggValueSlot::forAddr(DeclPtr, isVolatile, true));
+    CGF.EmitAggExpr(Init, AggValueSlot::forAddr(DeclPtr, T.getQualifiers(),
+                                                true));
   }
 }
 
@@ -291,10 +293,21 @@ void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
                 getTypes().getNullaryFunctionInfo(),
                 FunctionArgList(), SourceLocation());
 
+  RunCleanupsScope Scope(*this);
+
+  // When building in Objective-C++ ARC mode, create an autorelease pool
+  // around the global initializers.
+  if (getLangOptions().ObjCAutoRefCount && getLangOptions().CPlusPlus) {    
+    llvm::Value *token = EmitObjCAutoreleasePoolPush();
+    EmitObjCAutoreleasePoolCleanup(token);
+  }
+  
   for (unsigned i = 0; i != NumDecls; ++i)
     if (Decls[i])
-      Builder.CreateCall(Decls[i]);
+      Builder.CreateCall(Decls[i]);    
 
+  Scope.ForceCleanup();
+  
   FinishFunction();
 }
 

+ 4 - 2
lib/CodeGen/CGException.cpp

@@ -354,7 +354,8 @@ static void EmitAnyExprToExn(CodeGenFunction &CGF, const Expr *e,
   // evaluated but before the exception is caught.  But the best way
   // to handle that is to teach EmitAggExpr to do the final copy
   // differently if it can't be elided.
-  CGF.EmitAnyExprToMem(e, typedAddr, /*Volatile*/ false, /*IsInit*/ true);
+  CGF.EmitAnyExprToMem(e, typedAddr, e->getType().getQualifiers(), 
+                       /*IsInit*/ true);
 
   // Deactivate the cleanup block.
   CGF.DeactivateCleanupBlock(cleanup);
@@ -1084,7 +1085,8 @@ static void InitCatchParam(CodeGenFunction &CGF,
   CGF.EHStack.pushTerminate();
 
   // Perform the copy construction.
-  CGF.EmitAggExpr(copyExpr, AggValueSlot::forAddr(ParamAddr, false, false));
+  CGF.EmitAggExpr(copyExpr, AggValueSlot::forAddr(ParamAddr, Qualifiers(), 
+                                                  false));
 
   // Leave the terminate scope.
   CGF.EHStack.popTerminate();

+ 190 - 26
lib/CodeGen/CGExpr.cpp

@@ -131,12 +131,12 @@ RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E) {
 /// location.
 void CodeGenFunction::EmitAnyExprToMem(const Expr *E,
                                        llvm::Value *Location,
-                                       bool IsLocationVolatile,
+                                       Qualifiers Quals,
                                        bool IsInit) {
   if (E->getType()->isAnyComplexType())
-    EmitComplexExprIntoAddr(E, Location, IsLocationVolatile);
+    EmitComplexExprIntoAddr(E, Location, Quals.hasVolatile());
   else if (hasAggregateLLVMType(E->getType()))
-    EmitAggExpr(E, AggValueSlot::forAddr(Location, IsLocationVolatile, IsInit));
+    EmitAggExpr(E, AggValueSlot::forAddr(Location, Quals, IsInit));
   else {
     RValue RV = RValue::get(EmitScalarExpr(E, /*Ignore*/ false));
     LValue LV = MakeAddrLValue(Location, E->getType());
@@ -203,7 +203,10 @@ static llvm::Value *
 EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
                             llvm::Value *&ReferenceTemporary,
                             const CXXDestructorDecl *&ReferenceTemporaryDtor,
+                            QualType &ObjCARCReferenceLifetimeType,
                             const NamedDecl *InitializedDecl) {
+  ObjCARCReferenceLifetimeType = QualType();
+  
   if (const CXXDefaultArgExpr *DAE = dyn_cast<CXXDefaultArgExpr>(E))
     E = DAE->getExpr();
   
@@ -213,6 +216,7 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
     return EmitExprForReferenceBinding(CGF, TE->getSubExpr(), 
                                        ReferenceTemporary, 
                                        ReferenceTemporaryDtor,
+                                       ObjCARCReferenceLifetimeType,
                                        InitializedDecl);
   }
 
@@ -279,12 +283,10 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
         !E->getType()->isAnyComplexType()) {
       ReferenceTemporary = CreateReferenceTemporary(CGF, E->getType(), 
                                                     InitializedDecl);
-      AggSlot = AggValueSlot::forAddr(ReferenceTemporary, false,
+      AggSlot = AggValueSlot::forAddr(ReferenceTemporary, Qualifiers(),
                                       InitializedDecl != 0);
     }
-      
-    RV = CGF.EmitAnyExpr(E, AggSlot);
-
+    
     if (InitializedDecl) {
       // Get the destructor for the reference temporary.
       if (const RecordType *RT = E->getType()->getAs<RecordType>()) {
@@ -292,8 +294,37 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
         if (!ClassDecl->hasTrivialDestructor())
           ReferenceTemporaryDtor = ClassDecl->getDestructor();
       }
+      else if (CGF.getContext().getLangOptions().ObjCAutoRefCount) {
+        if (const ValueDecl *InitVD = dyn_cast<ValueDecl>(InitializedDecl)) {
+          if (const ReferenceType *RefType
+                                  = InitVD->getType()->getAs<ReferenceType>()) {
+            QualType PointeeType = RefType->getPointeeType();
+            if (PointeeType->isObjCLifetimeType() &&
+                PointeeType.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) {
+              // Objective-C++ ARC: We're binding a reference to 
+              // lifetime-qualified type to a temporary, so we need to extend 
+              // the lifetime of the temporary with appropriate retain/release/
+              // autorelease calls.
+              ObjCARCReferenceLifetimeType = PointeeType;
+              
+              // Create a temporary variable that we can bind the reference to.
+              ReferenceTemporary = CreateReferenceTemporary(CGF, PointeeType, 
+                                                            InitializedDecl);
+
+              unsigned Alignment =
+                CGF.getContext().getTypeAlignInChars(PointeeType).getQuantity();
+              CGF.EmitScalarInit(E, InitVD, ReferenceTemporary, false,
+                                 PointeeType.isVolatileQualified(), 
+                                 Alignment, PointeeType);
+              return ReferenceTemporary;
+            }
+          }
+        }
+      }
     }
 
+    RV = CGF.EmitAnyExpr(E, AggSlot);
+
     // Check if need to perform derived-to-base casts and/or field accesses, to
     // get from the temporary object we created (and, potentially, for which we
     // extended the lifetime) to the subobject we're binding the reference to.
@@ -361,26 +392,60 @@ CodeGenFunction::EmitReferenceBindingToExpr(const Expr *E,
                                             const NamedDecl *InitializedDecl) {
   llvm::Value *ReferenceTemporary = 0;
   const CXXDestructorDecl *ReferenceTemporaryDtor = 0;
+  QualType ObjCARCReferenceLifetimeType;
   llvm::Value *Value = EmitExprForReferenceBinding(*this, E, ReferenceTemporary,
                                                    ReferenceTemporaryDtor,
+                                                   ObjCARCReferenceLifetimeType,
                                                    InitializedDecl);
-  if (!ReferenceTemporaryDtor)
+  if (!ReferenceTemporaryDtor && ObjCARCReferenceLifetimeType.isNull())
     return RValue::get(Value);
   
   // Make sure to call the destructor for the reference temporary.
-  if (const VarDecl *VD = dyn_cast_or_null<VarDecl>(InitializedDecl)) {
-    if (VD->hasGlobalStorage()) {
+  const VarDecl *VD = dyn_cast_or_null<VarDecl>(InitializedDecl);
+  if (VD && VD->hasGlobalStorage()) {
+    if (ReferenceTemporaryDtor) {
       llvm::Constant *DtorFn = 
         CGM.GetAddrOfCXXDestructor(ReferenceTemporaryDtor, Dtor_Complete);
       EmitCXXGlobalDtorRegistration(DtorFn, 
                                     cast<llvm::Constant>(ReferenceTemporary));
-      
-      return RValue::get(Value);
+    } else {
+      assert(!ObjCARCReferenceLifetimeType.isNull());
+      // Note: We intentionally do not register a global "destructor" to
+      // release the object.
     }
+    
+    return RValue::get(Value);
   }
 
-  PushDestructorCleanup(ReferenceTemporaryDtor, ReferenceTemporary);
-
+  if (ReferenceTemporaryDtor)
+    PushDestructorCleanup(ReferenceTemporaryDtor, ReferenceTemporary);
+  else {
+    switch (ObjCARCReferenceLifetimeType.getObjCLifetime()) {
+    case Qualifiers::OCL_None:
+      llvm_unreachable("Not a reference temporary that needs to be deallocated");
+      break;
+        
+    case Qualifiers::OCL_ExplicitNone:
+    case Qualifiers::OCL_Autoreleasing:
+      // Nothing to do.
+      break;        
+        
+    case Qualifiers::OCL_Strong:
+      PushARCReleaseCleanup(getARCCleanupKind(), ObjCARCReferenceLifetimeType, 
+                            ReferenceTemporary,
+                            VD && VD->hasAttr<ObjCPreciseLifetimeAttr>());
+      break;
+        
+    case Qualifiers::OCL_Weak:
+      // __weak objects always get EH cleanups; otherwise, exceptions
+      // could cause really nasty crashes instead of mere leaks.
+      PushARCWeakReleaseCleanup(NormalAndEHCleanup, 
+                                ObjCARCReferenceLifetimeType, 
+                                ReferenceTemporary);
+      break;        
+    }
+  }
+  
   return RValue::get(Value);
 }
 
@@ -599,6 +664,7 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
   case Expr::CXXDynamicCastExprClass:
   case Expr::CXXReinterpretCastExprClass:
   case Expr::CXXConstCastExprClass:
+  case Expr::ObjCBridgedCastExprClass:
     return EmitCastLValue(cast<CastExpr>(E));
   }
 }
@@ -668,6 +734,8 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, QualType ExprType) {
     return RValue::get(CGM.getObjCRuntime().EmitObjCWeakRead(*this,
                                                              AddrWeakObj));
   }
+  if (LV.getQuals().getObjCLifetime() == Qualifiers::OCL_Weak)
+    return RValue::get(EmitARCLoadWeak(LV.getAddress()));
 
   if (LV.isSimple()) {
     llvm::Value *Ptr = LV.getAddress();
@@ -838,6 +906,31 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
     return EmitStoreThroughPropertyRefLValue(Src, Dst);
   }
 
+  // There's special magic for assigning into an ARC-qualified l-value.
+  if (Qualifiers::ObjCLifetime Lifetime = Dst.getQuals().getObjCLifetime()) {
+    switch (Lifetime) {
+    case Qualifiers::OCL_None:
+      llvm_unreachable("present but none");
+
+    case Qualifiers::OCL_ExplicitNone:
+      // nothing special
+      break;
+
+    case Qualifiers::OCL_Strong:
+      EmitARCStoreStrong(Dst, Ty, Src.getScalarVal(), /*ignore*/ true);
+      return;
+
+    case Qualifiers::OCL_Weak:
+      EmitARCStoreWeak(Dst.getAddress(), Src.getScalarVal(), /*ignore*/ true);
+      return;
+
+    case Qualifiers::OCL_Autoreleasing:
+      Src = RValue::get(EmitObjCExtendObjectLifetime(Ty, Src.getScalarVal()));
+      // fall into the normal path
+      break;
+    }
+  }
+
   if (Dst.isObjCWeak() && !Dst.isNonGC()) {
     // load of a __weak object.
     llvm::Value *LvalueDst = Dst.getAddress();
@@ -1113,7 +1206,12 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
     setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
     return;
   }
-  
+
+  if (const ObjCBridgedCastExpr *Exp = dyn_cast<ObjCBridgedCastExpr>(E)) {
+    setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
+    return;
+  }
+
   if (const ArraySubscriptExpr *Exp = dyn_cast<ArraySubscriptExpr>(E)) {
     setObjCGCLValueClass(Ctx, Exp->getBase(), LV);
     if (LV.isObjCIvar() && !LV.isObjCArray()) 
@@ -1734,7 +1832,8 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){
   const Expr *InitExpr = E->getInitializer();
   LValue Result = MakeAddrLValue(DeclPtr, E->getType());
 
-  EmitAnyExprToMem(InitExpr, DeclPtr, /*Volatile*/ false, /*Init*/ true);
+  EmitAnyExprToMem(InitExpr, DeclPtr, E->getType().getQualifiers(),
+                   /*Init*/ true);
 
   return Result;
 }
@@ -1863,13 +1962,15 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
   case CK_DerivedToBaseMemberPointer:
   case CK_BaseToDerivedMemberPointer:
   case CK_MemberPointerToBoolean:
-  case CK_AnyPointerToBlockPointerCast: {
+  case CK_AnyPointerToBlockPointerCast:
+  case CK_ObjCProduceObject:
+  case CK_ObjCConsumeObject: {
     // These casts only produce lvalues when we're binding a reference to a 
     // temporary realized from a (converted) pure rvalue. Emit the expression
     // as a value, copy it into a temporary, and return an lvalue referring to
     // that temporary.
     llvm::Value *V = CreateMemTemp(E->getType(), "ref.temp");
-    EmitAnyExprToMem(E, V, false, false);
+    EmitAnyExprToMem(E, V, E->getType().getQualifiers(), false);
     return MakeAddrLValue(V, E->getType());
   }
 
@@ -1988,13 +2089,60 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
     if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(TargetDecl))
       return EmitCXXOperatorMemberCallExpr(CE, MD, ReturnValue);
 
-  if (isa<CXXPseudoDestructorExpr>(E->getCallee()->IgnoreParens())) {
-    // C++ [expr.pseudo]p1:
-    //   The result shall only be used as the operand for the function call
-    //   operator (), and the result of such a call has type void. The only
-    //   effect is the evaluation of the postfix-expression before the dot or
-    //   arrow.
-    EmitScalarExpr(E->getCallee());
+  if (const CXXPseudoDestructorExpr *PseudoDtor 
+          = dyn_cast<CXXPseudoDestructorExpr>(E->getCallee()->IgnoreParens())) {
+    QualType DestroyedType = PseudoDtor->getDestroyedType();
+    if (getContext().getLangOptions().ObjCAutoRefCount &&
+        DestroyedType->isObjCLifetimeType() &&
+        (DestroyedType.getObjCLifetime() == Qualifiers::OCL_Strong ||
+         DestroyedType.getObjCLifetime() == Qualifiers::OCL_Weak)) {
+          // Automatic Reference Counting:
+          //   If the pseudo-expression names a retainable object with weak or strong
+          //   lifetime, the object shall be released.
+      bool isNonGC = false;
+      Expr *BaseExpr = PseudoDtor->getBase();
+      llvm::Value *BaseValue = NULL;
+      Qualifiers BaseQuals;
+      
+      // If this is s.x, emit s as an lvalue.  If it is s->x, emit s as a scalar.
+      if (PseudoDtor->isArrow()) {
+        BaseValue = EmitScalarExpr(BaseExpr);
+        const PointerType *PTy = BaseExpr->getType()->getAs<PointerType>();
+        BaseQuals = PTy->getPointeeType().getQualifiers();
+      } else {
+        LValue BaseLV = EmitLValue(BaseExpr);
+        if (BaseLV.isNonGC())
+          isNonGC = true;
+        BaseValue = BaseLV.getAddress();
+        QualType BaseTy = BaseExpr->getType();
+        BaseQuals = BaseTy.getQualifiers();
+      }
+          
+      switch (PseudoDtor->getDestroyedType().getObjCLifetime()) {
+      case Qualifiers::OCL_None:
+      case Qualifiers::OCL_ExplicitNone:
+      case Qualifiers::OCL_Autoreleasing:
+        break;
+        
+      case Qualifiers::OCL_Strong:
+        EmitARCRelease(Builder.CreateLoad(BaseValue, 
+                          PseudoDtor->getDestroyedType().isVolatileQualified()), 
+                       /*precise*/ true);
+        break;
+
+      case Qualifiers::OCL_Weak:
+        EmitARCDestroyWeak(BaseValue);
+        break;
+      }
+    } else {
+      // C++ [expr.pseudo]p1:
+      //   The result shall only be used as the operand for the function call
+      //   operator (), and the result of such a call has type void. The only
+      //   effect is the evaluation of the postfix-expression before the dot or
+      //   arrow.      
+      EmitScalarExpr(E->getCallee());
+    }
+    
     return RValue::get(0);
   }
 
@@ -2016,9 +2164,25 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
     return EmitPointerToDataMemberBinaryExpr(E);
 
   assert(E->getOpcode() == BO_Assign && "unexpected binary l-value");
+
+  // Note that in all of these cases, __block variables need the RHS
+  // evaluated first just in case the variable gets moved by the RHS.
   
   if (!hasAggregateLLVMType(E->getType())) {
-    // __block variables need the RHS evaluated first.
+    switch (E->getLHS()->getType().getObjCLifetime()) {
+    case Qualifiers::OCL_Strong:
+      return EmitARCStoreStrong(E, /*ignored*/ false).first;
+
+    case Qualifiers::OCL_Autoreleasing:
+      return EmitARCStoreAutoreleasing(E).first;
+
+    // No reason to do any of these differently.
+    case Qualifiers::OCL_None:
+    case Qualifiers::OCL_ExplicitNone:
+    case Qualifiers::OCL_Weak:
+      break;
+    }
+
     RValue RV = EmitAnyExpr(E->getRHS());
     LValue LV = EmitLValue(E->getLHS());
     EmitStoreThroughLValue(RV, LV, E->getType());

+ 16 - 8
lib/CodeGen/CGExprAgg.cpp

@@ -339,6 +339,8 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
   case CK_IntegralComplexToBoolean:
   case CK_IntegralComplexCast:
   case CK_IntegralComplexToFloatingComplex:
+  case CK_ObjCProduceObject:
+  case CK_ObjCConsumeObject:
     llvm_unreachable("cast kind invalid for aggregate types");
   }
 }
@@ -570,8 +572,13 @@ AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV, QualType T) {
   } else if (T->isAnyComplexType()) {
     CGF.EmitComplexExprIntoAddr(E, LV.getAddress(), false);
   } else if (CGF.hasAggregateLLVMType(T)) {
-    CGF.EmitAggExpr(E, AggValueSlot::forAddr(LV.getAddress(), false, true,
+    CGF.EmitAggExpr(E, AggValueSlot::forAddr(LV.getAddress(), 
+                                             T.getQualifiers(), true,
                                              false, Dest.isZeroed()));
+  } else if (LV.isSimple()) {
+    CGF.EmitScalarInit(E, /*D=*/0, LV.getAddress(), /*Captured=*/false, 
+                       LV.isVolatileQualified(), LV.getAlignment(),
+                       T);
   } else {
     CGF.EmitStoreThroughLValue(RValue::get(CGF.EmitScalarExpr(E)), LV, T);
   }
@@ -636,6 +643,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
     uint64_t NumArrayElements = AType->getNumElements();
     QualType ElementType = CGF.getContext().getCanonicalType(E->getType());
     ElementType = CGF.getContext().getAsArrayType(ElementType)->getElementType();
+    ElementType = CGF.getContext().getQualifiedType(ElementType, 
+                                                    Dest.getQualifiers());
 
     bool hasNonTrivialCXXConstructor = false;
     if (CGF.getContext().getLangOptions().CPlusPlus)
@@ -645,8 +654,6 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
         hasNonTrivialCXXConstructor = !RD->hasTrivialDefaultConstructor();
       }
 
-    // FIXME: were we intentionally ignoring address spaces and GC attributes?
-
     for (uint64_t i = 0; i != NumArrayElements; ++i) {
       // If we're done emitting initializers and the destination is known-zeroed
       // then we're done.
@@ -873,8 +880,6 @@ static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E,
 ///
 /// \param IsInitializer - true if this evaluation is initializing an
 /// object whose lifetime is already being managed.
-//
-// FIXME: Take Qualifiers object.
 void CodeGenFunction::EmitAggExpr(const Expr *E, AggValueSlot Slot,
                                   bool IgnoreResult) {
   assert(E && hasAggregateLLVMType(E->getType()) &&
@@ -892,7 +897,7 @@ LValue CodeGenFunction::EmitAggExprToLValue(const Expr *E) {
   assert(hasAggregateLLVMType(E->getType()) && "Invalid argument!");
   llvm::Value *Temp = CreateMemTemp(E->getType());
   LValue LV = MakeAddrLValue(Temp, E->getType());
-  EmitAggExpr(E, AggValueSlot::forAddr(Temp, LV.isVolatileQualified(), false));
+  EmitAggExpr(E, AggValueSlot::forLValue(LV, false));
   return LV;
 }
 
@@ -954,7 +959,10 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
     llvm::Type::getInt8PtrTy(getLLVMContext(), SPT->getAddressSpace());
   SrcPtr = Builder.CreateBitCast(SrcPtr, SBP, "tmp");
 
-  if (const RecordType *RecordTy = Ty->getAs<RecordType>()) {
+  // Don't do any of the memmove_collectable tests if GC isn't set.
+  if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC) {
+    // fall through
+  } else if (const RecordType *RecordTy = Ty->getAs<RecordType>()) {
     RecordDecl *Record = RecordTy->getDecl();
     if (Record->hasObjectMember()) {
       CharUnits size = TypeInfo.first;
@@ -964,7 +972,7 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
                                                     SizeVal);
       return;
     }
-  } else if (getContext().getAsArrayType(Ty)) {
+  } else if (Ty->isArrayType()) {
     QualType BaseType = getContext().getBaseElementType(Ty);
     if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) {
       if (RecordTy->getDecl()->hasObjectMember()) {

+ 85 - 5
lib/CodeGen/CGExprCXX.cpp

@@ -708,15 +708,14 @@ static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const CXXNewExpr *E,
   unsigned Alignment =
     CGF.getContext().getTypeAlignInChars(AllocType).getQuantity();
   if (!CGF.hasAggregateLLVMType(AllocType)) 
-    CGF.EmitStoreOfScalar(CGF.EmitScalarExpr(Init), NewPtr,
-                          AllocType.isVolatileQualified(), Alignment,
-                          AllocType);
+    CGF.EmitScalarInit(Init, 0, NewPtr, false, AllocType.isVolatileQualified(),
+                       Alignment, AllocType);
   else if (AllocType->isAnyComplexType())
     CGF.EmitComplexExprIntoAddr(Init, NewPtr, 
                                 AllocType.isVolatileQualified());
   else {
     AggValueSlot Slot
-      = AggValueSlot::forAddr(NewPtr, AllocType.isVolatileQualified(), true);
+      = AggValueSlot::forAddr(NewPtr, AllocType.getQualifiers(), true);
     CGF.EmitAggExpr(Init, Slot);
   }
 }
@@ -1075,7 +1074,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
   // CXXNewExpr::shouldNullCheckAllocation()) and we have an
   // interesting initializer.
   bool nullCheck = allocatorType->isNothrow(getContext()) &&
-    !(allocType->isPODType() && !E->hasInitializer());
+    !(allocType.isPODType(getContext()) && !E->hasInitializer());
 
   llvm::BasicBlock *nullCheckBB = 0;
   llvm::BasicBlock *contBB = 0;
@@ -1247,7 +1246,29 @@ static void EmitObjectDelete(CodeGenFunction &CGF,
   if (Dtor)
     CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
                               /*ForVirtualBase=*/false, Ptr);
+  else if (CGF.getLangOptions().ObjCAutoRefCount &&
+           ElementType->isObjCLifetimeType()) {
+    switch (ElementType.getObjCLifetime()) {
+    case Qualifiers::OCL_None:
+    case Qualifiers::OCL_ExplicitNone:
+    case Qualifiers::OCL_Autoreleasing:
+      break;
 
+    case Qualifiers::OCL_Strong: {
+      // Load the pointer value.
+      llvm::Value *PtrValue = CGF.Builder.CreateLoad(Ptr, 
+                                             ElementType.isVolatileQualified());
+        
+      CGF.EmitARCRelease(PtrValue, /*precise*/ true);
+      break;
+    }
+        
+    case Qualifiers::OCL_Weak:
+      CGF.EmitARCDestroyWeak(Ptr);
+      break;
+    }
+  }
+           
   CGF.PopCleanupBlock();
 }
 
@@ -1339,6 +1360,65 @@ static void EmitArrayDelete(CodeGenFunction &CGF,
                             " for a class with destructor");
       CGF.EmitCXXAggrDestructorCall(RD->getDestructor(), NumElements, Ptr);
     }
+  } else if (CGF.getLangOptions().ObjCAutoRefCount &&
+             ElementType->isObjCLifetimeType() &&
+             (ElementType.getObjCLifetime() == Qualifiers::OCL_Strong ||
+              ElementType.getObjCLifetime() == Qualifiers::OCL_Weak)) {
+    bool IsStrong = ElementType.getObjCLifetime() == Qualifiers::OCL_Strong;
+    const llvm::Type *SizeLTy = CGF.ConvertType(CGF.getContext().getSizeType());
+    llvm::Value *One = llvm::ConstantInt::get(SizeLTy, 1);
+    
+    // Create a temporary for the loop index and initialize it with count of
+    // array elements.
+    llvm::Value *IndexPtr = CGF.CreateTempAlloca(SizeLTy, "loop.index");
+    
+    // Store the number of elements in the index pointer.
+    CGF.Builder.CreateStore(NumElements, IndexPtr);
+    
+    // Start the loop with a block that tests the condition.
+    llvm::BasicBlock *CondBlock = CGF.createBasicBlock("for.cond");
+    llvm::BasicBlock *AfterFor = CGF.createBasicBlock("for.end");
+    
+    CGF.EmitBlock(CondBlock);
+    
+    llvm::BasicBlock *ForBody = CGF.createBasicBlock("for.body");
+    
+    // Generate: if (loop-index != 0 fall to the loop body,
+    // otherwise, go to the block after the for-loop.
+    llvm::Value* zeroConstant = llvm::Constant::getNullValue(SizeLTy);
+    llvm::Value *Counter = CGF.Builder.CreateLoad(IndexPtr);
+    llvm::Value *IsNE = CGF.Builder.CreateICmpNE(Counter, zeroConstant,
+                                                 "isne");
+    // If the condition is true, execute the body.
+    CGF.Builder.CreateCondBr(IsNE, ForBody, AfterFor);
+    
+    CGF.EmitBlock(ForBody);
+    
+    llvm::BasicBlock *ContinueBlock = CGF.createBasicBlock("for.inc");
+    // Inside the loop body, emit the constructor call on the array element.
+    Counter = CGF.Builder.CreateLoad(IndexPtr);
+    Counter = CGF.Builder.CreateSub(Counter, One);
+    llvm::Value *Address = CGF.Builder.CreateInBoundsGEP(Ptr, Counter, 
+                                                         "arrayidx");
+    if (IsStrong)
+      CGF.EmitARCRelease(CGF.Builder.CreateLoad(Address, 
+                                          ElementType.isVolatileQualified()),
+                         /*precise*/ true);
+    else
+      CGF.EmitARCDestroyWeak(Address);
+    
+    CGF.EmitBlock(ContinueBlock);
+    
+    // Emit the decrement of the loop counter.
+    Counter = CGF.Builder.CreateLoad(IndexPtr);
+    Counter = CGF.Builder.CreateSub(Counter, One, "dec");
+    CGF.Builder.CreateStore(Counter, IndexPtr);
+    
+    // Finally, branch back up to the condition for the next iteration.
+    CGF.EmitBranch(CondBlock);
+    
+    // Emit the fall-through block.
+    CGF.EmitBlock(AfterFor, true);    
   }
 
   CGF.PopCleanupBlock();

+ 2 - 0
lib/CodeGen/CGExprConstant.cpp

@@ -570,6 +570,8 @@ public:
     case CK_GetObjCProperty:
     case CK_ToVoid:
     case CK_Dynamic:
+    case CK_ObjCProduceObject:
+    case CK_ObjCConsumeObject:
       return 0;
 
     // These might need to be supported for constexpr.

+ 42 - 15
lib/CodeGen/CGExprScalar.cpp

@@ -1106,7 +1106,12 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
     // function pointers on Itanium and ARM).
     return CGF.CGM.getCXXABI().EmitMemberPointerConversion(CGF, CE, Src);
   }
-  
+
+  case CK_ObjCProduceObject:
+    return CGF.EmitARCRetainScalarExpr(E);
+  case CK_ObjCConsumeObject:
+    return CGF.EmitObjCConsumeObject(E->getType(), Visit(E));
+
   case CK_FloatingRealToComplex:
   case CK_FloatingComplexCast:
   case CK_IntegralRealToComplex:
@@ -2228,20 +2233,42 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E,unsigned UICmpOpc,
 Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
   bool Ignore = TestAndClearIgnoreResultAssign();
 
-  // __block variables need to have the rhs evaluated first, plus this should
-  // improve codegen just a little.
-  Value *RHS = Visit(E->getRHS());
-  LValue LHS = EmitCheckedLValue(E->getLHS());
-
-  // Store the value into the LHS.  Bit-fields are handled specially
-  // because the result is altered by the store, i.e., [C99 6.5.16p1]
-  // 'An assignment expression has the value of the left operand after
-  // the assignment...'.
-  if (LHS.isBitField())
-    CGF.EmitStoreThroughBitfieldLValue(RValue::get(RHS), LHS, E->getType(),
-                                       &RHS);
-  else
-    CGF.EmitStoreThroughLValue(RValue::get(RHS), LHS, E->getType());
+  Value *RHS;
+  LValue LHS;
+
+  switch (E->getLHS()->getType().getObjCLifetime()) {
+  case Qualifiers::OCL_Strong:
+    llvm::tie(LHS, RHS) = CGF.EmitARCStoreStrong(E, Ignore);
+    break;
+
+  case Qualifiers::OCL_Autoreleasing:
+    llvm::tie(LHS,RHS) = CGF.EmitARCStoreAutoreleasing(E);
+    break;
+
+  case Qualifiers::OCL_Weak:
+    RHS = Visit(E->getRHS());
+    LHS = EmitCheckedLValue(E->getLHS());    
+    RHS = CGF.EmitARCStoreWeak(LHS.getAddress(), RHS, Ignore);
+    break;
+
+  // No reason to do any of these differently.
+  case Qualifiers::OCL_None:
+  case Qualifiers::OCL_ExplicitNone:
+    // __block variables need to have the rhs evaluated first, plus
+    // this should improve codegen just a little.
+    RHS = Visit(E->getRHS());
+    LHS = EmitCheckedLValue(E->getLHS());
+
+    // Store the value into the LHS.  Bit-fields are handled specially
+    // because the result is altered by the store, i.e., [C99 6.5.16p1]
+    // 'An assignment expression has the value of the left operand after
+    // the assignment...'.
+    if (LHS.isBitField())
+      CGF.EmitStoreThroughBitfieldLValue(RValue::get(RHS), LHS, E->getType(),
+                                         &RHS);
+    else
+      CGF.EmitStoreThroughLValue(RValue::get(RHS), LHS, E->getType());
+  }
 
   // If the result is clearly ignored, return now.
   if (Ignore)

+ 1362 - 17
lib/CodeGen/CGObjC.cpp

@@ -15,15 +15,29 @@
 #include "CGObjCRuntime.h"
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
+#include "TargetInfo.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/StmtObjC.h"
 #include "clang/Basic/Diagnostic.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Target/TargetData.h"
+#include "llvm/InlineAsm.h"
 using namespace clang;
 using namespace CodeGen;
 
+typedef llvm::PointerIntPair<llvm::Value*,1,bool> TryEmitResult;
+static TryEmitResult
+tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e);
+
+/// Given the address of a variable of pointer type, find the correct
+/// null to store into it.
+static llvm::Constant *getNullForVariable(llvm::Value *addr) {
+  const llvm::Type *type =
+    cast<llvm::PointerType>(addr->getType())->getElementType();
+  return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(type));
+}
+
 /// Emits an instance of NSConstantString representing the object.
 llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E)
 {
@@ -55,6 +69,7 @@ static RValue AdjustRelatedResultType(CodeGenFunction &CGF,
                                       RValue Result) {
   if (!Method)
     return Result;
+
   if (!Method->hasRelatedResultType() ||
       CGF.getContext().hasSameType(E->getType(), Method->getResultType()) ||
       !Result.isScalar())
@@ -71,6 +86,18 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
   // implementation vary between runtimes.  We can get the receiver and
   // arguments in generic code.
 
+  bool isDelegateInit = E->isDelegateInitCall();
+
+  // 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,
+  // though.
+  bool retainSelf =
+    (!isDelegateInit &&
+     CGM.getLangOptions().ObjCAutoRefCount &&
+     E->getMethodDecl() &&
+     E->getMethodDecl()->hasAttr<NSConsumesSelfAttr>());
+
   CGObjCRuntime &Runtime = CGM.getObjCRuntime();
   bool isSuperMessage = false;
   bool isClassMessage = false;
@@ -80,8 +107,15 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
   llvm::Value *Receiver = 0;
   switch (E->getReceiverKind()) {
   case ObjCMessageExpr::Instance:
-    Receiver = EmitScalarExpr(E->getInstanceReceiver());
     ReceiverType = E->getInstanceReceiver()->getType();
+    if (retainSelf) {
+      TryEmitResult ter = tryEmitARCRetainScalarExpr(*this,
+                                                   E->getInstanceReceiver());
+      Receiver = ter.getPointer();
+      if (!ter.getInt())
+        Receiver = EmitARCRetainNonBlock(Receiver);
+    } else
+      Receiver = EmitScalarExpr(E->getInstanceReceiver());
     break;
 
   case ObjCMessageExpr::Class: {
@@ -92,6 +126,9 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
     assert(OID && "Invalid Objective-C class message send");
     Receiver = Runtime.GetClass(Builder, OID);
     isClassMessage = true;
+
+    if (retainSelf)
+      Receiver = EmitARCRetainNonBlock(Receiver);
     break;
   }
 
@@ -99,6 +136,9 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
     ReceiverType = E->getSuperType();
     Receiver = LoadObjCSelf();
     isSuperMessage = true;
+
+    if (retainSelf)
+      Receiver = EmitARCRetainNonBlock(Receiver);
     break;
 
   case ObjCMessageExpr::SuperClass:
@@ -106,14 +146,36 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
     Receiver = LoadObjCSelf();
     isSuperMessage = true;
     isClassMessage = true;
+
+    if (retainSelf)
+      Receiver = EmitARCRetainNonBlock(Receiver);
     break;
   }
 
+  QualType ResultType =
+    E->getMethodDecl() ? E->getMethodDecl()->getResultType() : E->getType();
+
   CallArgList Args;
   EmitCallArgs(Args, E->getMethodDecl(), E->arg_begin(), E->arg_end());
 
-  QualType ResultType =
-    E->getMethodDecl() ? E->getMethodDecl()->getResultType() : E->getType();
+  // For delegate init calls in ARC, do an unsafe store of null into
+  // self.  This represents the call taking direct ownership of that
+  // value.  We have to do this after emitting the other call
+  // arguments because they might also reference self, but we don't
+  // have to worry about any of them modifying self because that would
+  // be an undefined read and write of an object in unordered
+  // expressions.
+  if (isDelegateInit) {
+    assert(getLangOptions().ObjCAutoRefCount &&
+           "delegate init calls should only be marked in ARC");
+
+    // Do an unsafe store of null into self.
+    llvm::Value *selfAddr =
+      LocalDeclMap[cast<ObjCMethodDecl>(CurCodeDecl)->getSelfDecl()];
+    assert(selfAddr && "no self entry for a delegate init call?");
+
+    Builder.CreateStore(getNullForVariable(selfAddr), selfAddr);
+  }
 
   RValue result;
   if (isSuperMessage) {
@@ -134,10 +196,52 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E,
                                          Receiver, Args, OID,
                                          E->getMethodDecl());
   }
-  
+
+  // For delegate init calls in ARC, implicitly store the result of
+  // the call back into self.  This takes ownership of the value.
+  if (isDelegateInit) {
+    llvm::Value *selfAddr =
+      LocalDeclMap[cast<ObjCMethodDecl>(CurCodeDecl)->getSelfDecl()];
+    llvm::Value *newSelf = result.getScalarVal();
+
+    // The delegate return type isn't necessarily a matching type; in
+    // fact, it's quite likely to be 'id'.
+    const llvm::Type *selfTy =
+      cast<llvm::PointerType>(selfAddr->getType())->getElementType();
+    newSelf = Builder.CreateBitCast(newSelf, selfTy);
+
+    Builder.CreateStore(newSelf, selfAddr);
+  }
+
   return AdjustRelatedResultType(*this, E, E->getMethodDecl(), result);
 }
 
+namespace {
+struct FinishARCDealloc : EHScopeStack::Cleanup {
+  void Emit(CodeGenFunction &CGF, bool isForEH) {
+    const ObjCMethodDecl *method = cast<ObjCMethodDecl>(CGF.CurCodeDecl);
+    const ObjCImplementationDecl *impl
+      = cast<ObjCImplementationDecl>(method->getDeclContext());
+    const ObjCInterfaceDecl *iface = impl->getClassInterface();
+    if (!iface->getSuperClass()) return;
+
+    // Call [super dealloc] if we have a superclass.
+    llvm::Value *self = CGF.LoadObjCSelf();
+
+    CallArgList args;
+    CGF.CGM.getObjCRuntime().GenerateMessageSendSuper(CGF, ReturnValueSlot(),
+                                                      CGF.getContext().VoidTy,
+                                                      method->getSelector(),
+                                                      iface,
+                                                      /*is category*/ false,
+                                                      self,
+                                                      /*is class msg*/ false,
+                                                      args,
+                                                      method);
+  }
+};
+}
+
 /// StartObjCMethod - Begin emission of an ObjCMethod. This generates
 /// the LLVM function and sets the other context used by
 /// CodeGenFunction.
@@ -164,8 +268,21 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD,
   CurGD = OMD;
 
   StartFunction(OMD, OMD->getResultType(), Fn, FI, args, StartLoc);
+
+  // In ARC, certain methods get an extra cleanup.
+  if (CGM.getLangOptions().ObjCAutoRefCount &&
+      OMD->isInstanceMethod() &&
+      OMD->getSelector().isUnarySelector()) {
+    const IdentifierInfo *ident = 
+      OMD->getSelector().getIdentifierInfoForSlot(0);
+    if (ident->isStr("dealloc"))
+      EHStack.pushCleanup<FinishARCDealloc>(getARCCleanupKind());
+  }
 }
 
+static llvm::Value *emitARCRetainLoadOfScalar(CodeGenFunction &CGF,
+                                              LValue lvalue, QualType type);
+
 void CodeGenFunction::GenerateObjCGetterBody(ObjCIvarDecl *Ivar, 
                                              bool IsAtomic, bool IsStrong) {
   LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), 
@@ -269,6 +386,9 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
     RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(),
                                            Types.ConvertType(PD->getType())));
     EmitReturnOfRValue(RV, PD->getType());
+
+    // objc_getProperty does an autorelease, so we should suppress ours.
+    AutoreleaseResult = false;
   } else {
     const llvm::Triple &Triple = getContext().Target.getTriple();
     QualType IVART = Ivar->getType();
@@ -347,17 +467,23 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
     else {
         LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), 
                                     Ivar, 0);
-        if (PD->getType()->isReferenceType()) {
-          RValue RV = RValue::get(LV.getAddress());
-          EmitReturnOfRValue(RV, PD->getType());
-        }
-        else {
-          CodeGenTypes &Types = CGM.getTypes();
-          RValue RV = EmitLoadOfLValue(LV, IVART);
-          RV = RValue::get(Builder.CreateBitCast(RV.getScalarVal(),
-                                               Types.ConvertType(PD->getType())));
-          EmitReturnOfRValue(RV, PD->getType());
+        QualType propType = PD->getType();
+
+        llvm::Value *value;
+        if (propType->isReferenceType()) {
+          value = LV.getAddress();
+        } else {
+          // In ARC, we want to emit this retained.
+          if (getLangOptions().ObjCAutoRefCount &&
+              PD->getType()->isObjCRetainableType())
+            value = emitARCRetainLoadOfScalar(*this, LV, IVART);
+          else
+            value = EmitLoadOfLValue(LV, IVART).getScalarVal();
+
+          value = Builder.CreateBitCast(value, ConvertType(propType));
         }
+
+        EmitReturnOfRValue(RValue::get(value), propType);
     }
   }
 
@@ -597,6 +723,11 @@ namespace {
   };
 }
 
+static void pushReleaseForIvar(CodeGenFunction &CGF, ObjCIvarDecl *ivar,
+                               llvm::Value *self);
+static void pushWeakReleaseForIvar(CodeGenFunction &CGF, ObjCIvarDecl *ivar,
+                                   llvm::Value *self);
+
 static void emitCXXDestructMethod(CodeGenFunction &CGF,
                                   ObjCImplementationDecl *impl) {
   CodeGenFunction::RunCleanupsScope scope(CGF);
@@ -631,6 +762,14 @@ static void emitCXXDestructMethod(CodeGenFunction &CGF,
         CGF.EHStack.pushCleanup<CallIvarDtor>(NormalAndEHCleanup,
                                               ivar, self);
       break;
+
+    case QualType::DK_objc_strong_lifetime:
+      pushReleaseForIvar(CGF, ivar, self);
+      break;
+
+    case QualType::DK_objc_weak_lifetime:
+      pushWeakReleaseForIvar(CGF, ivar, self);
+      break;
     }
   }
 
@@ -645,6 +784,9 @@ void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP,
 
   // Emit .cxx_construct.
   if (ctor) {
+    // Suppress the final autorelease in ARC.
+    AutoreleaseResult = false;
+
     llvm::SmallVector<CXXCtorInitializer *, 8> IvarInitializers;
     for (ObjCImplementationDecl::init_const_iterator B = IMP->init_begin(),
            E = IMP->init_end(); B != E; ++B) {
@@ -747,6 +889,16 @@ RValue CodeGenFunction::EmitLoadOfPropertyRefLValue(LValue LV,
 
   llvm::Value *Receiver = LV.getPropertyRefBaseAddr();
 
+  if (CGM.getLangOptions().ObjCAutoRefCount) {
+    QualType receiverType;
+    if (E->isSuperReceiver())
+      receiverType = E->getSuperReceiverType();
+    else if (E->isClassReceiver())
+      receiverType = getContext().getObjCClassType();
+    else
+      receiverType = E->getBase()->getType();
+  }
+
   // Accesses to 'super' follow a different code path.
   if (E->isSuperReceiver())
     return AdjustRelatedResultType(*this, E, method,
@@ -757,9 +909,9 @@ RValue CodeGenFunction::EmitLoadOfPropertyRefLValue(LValue LV,
   const ObjCInterfaceDecl *ReceiverClass
     = (E->isClassReceiver() ? E->getClassReceiver() : 0);
   return AdjustRelatedResultType(*this, E, method,
-                                 CGM.getObjCRuntime().
-                 GenerateMessageSend(*this, Return, ResultType, S,
-                                     Receiver, CallArgList(), ReceiverClass));
+          CGM.getObjCRuntime().
+             GenerateMessageSend(*this, Return, ResultType, S,
+                                 Receiver, CallArgList(), ReceiverClass));
 }
 
 void CodeGenFunction::EmitStoreThroughPropertyRefLValue(RValue Src,
@@ -1072,4 +1224,1197 @@ void CodeGenFunction::EmitObjCAtSynchronizedStmt(
   CGM.getObjCRuntime().EmitSynchronizedStmt(*this, S);
 }
 
+/// Produce the code for a CK_ObjCProduceObject.  Just does a
+/// primitive retain.
+llvm::Value *CodeGenFunction::EmitObjCProduceObject(QualType type,
+                                                    llvm::Value *value) {
+  return EmitARCRetain(type, value);
+}
+
+namespace {
+  struct CallObjCRelease : EHScopeStack::Cleanup {
+    CallObjCRelease(QualType type, llvm::Value *ptr, llvm::Value *condition)
+      : type(type), ptr(ptr), condition(condition) {}
+    QualType type;
+    llvm::Value *ptr;
+    llvm::Value *condition;
+
+    void Emit(CodeGenFunction &CGF, bool forEH) {
+      llvm::Value *object;
+
+      // If we're in a conditional branch, we had to stash away in an
+      // alloca the pointer to be released.
+      llvm::BasicBlock *cont = 0;
+      if (condition) {
+        llvm::BasicBlock *release = CGF.createBasicBlock("release.yes");
+        cont = CGF.createBasicBlock("release.cont");
+
+        llvm::Value *cond = CGF.Builder.CreateLoad(condition);
+        CGF.Builder.CreateCondBr(cond, release, cont);
+        CGF.EmitBlock(release);
+        object = CGF.Builder.CreateLoad(ptr);
+      } else {
+        object = ptr;
+      }
+
+      CGF.EmitARCRelease(object, /*precise*/ true);
+
+      if (cont) CGF.EmitBlock(cont);
+    }
+  };
+}
+
+/// Produce the code for a CK_ObjCConsumeObject.  Does a primitive
+/// release at the end of the full-expression.
+llvm::Value *CodeGenFunction::EmitObjCConsumeObject(QualType type,
+                                                    llvm::Value *object) {
+  // If we're in a conditional branch, we need to make the cleanup
+  // conditional.  FIXME: this really needs to be supported by the
+  // environment.
+  llvm::AllocaInst *cond;
+  llvm::Value *ptr;
+  if (isInConditionalBranch()) {
+    cond = CreateTempAlloca(Builder.getInt1Ty(), "release.cond");
+    ptr = CreateTempAlloca(object->getType(), "release.value");
+
+    // The alloca is false until we get here.
+    // FIXME: er. doesn't this need to be set at the start of the condition?
+    InitTempAlloca(cond, Builder.getFalse());
+
+    // Then it turns true.
+    Builder.CreateStore(Builder.getTrue(), cond);
+    Builder.CreateStore(object, ptr);
+  } else {
+    cond = 0;
+    ptr = object;
+  }
+
+  EHStack.pushCleanup<CallObjCRelease>(getARCCleanupKind(), type, ptr, cond);
+  return object;
+}
+
+llvm::Value *CodeGenFunction::EmitObjCExtendObjectLifetime(QualType type,
+                                                           llvm::Value *value) {
+  return EmitARCRetainAutorelease(type, value);
+}
+
+
+static llvm::Constant *createARCRuntimeFunction(CodeGenModule &CGM,
+                                                const llvm::FunctionType *type,
+                                                llvm::StringRef fnName) {
+  llvm::Constant *fn = CGM.CreateRuntimeFunction(type, fnName);
+
+  // In -fobjc-no-arc-runtime, emit weak references to the runtime
+  // support library.
+  if (CGM.getLangOptions().ObjCNoAutoRefCountRuntime)
+    if (llvm::Function *f = dyn_cast<llvm::Function>(fn))
+      f->setLinkage(llvm::Function::ExternalWeakLinkage);
+
+  return fn;
+}
+
+/// Perform an operation having the signature
+///   i8* (i8*)
+/// where a null input causes a no-op and returns null.
+static llvm::Value *emitARCValueOperation(CodeGenFunction &CGF,
+                                          llvm::Value *value,
+                                          llvm::Constant *&fn,
+                                          llvm::StringRef fnName) {
+  if (isa<llvm::ConstantPointerNull>(value)) return value;
+
+  if (!fn) {
+    std::vector<const llvm::Type*> args(1, CGF.Int8PtrTy);
+    const llvm::FunctionType *fnType =
+      llvm::FunctionType::get(CGF.Int8PtrTy, args, false);
+    fn = createARCRuntimeFunction(CGF.CGM, fnType, fnName);
+  }
+
+  // Cast the argument to 'id'.
+  const llvm::Type *origType = value->getType();
+  value = CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy);
+
+  // Call the function.
+  llvm::CallInst *call = CGF.Builder.CreateCall(fn, value);
+  call->setDoesNotThrow();
+
+  // Cast the result back to the original type.
+  return CGF.Builder.CreateBitCast(call, origType);
+}
+
+/// Perform an operation having the following signature:
+///   i8* (i8**)
+static llvm::Value *emitARCLoadOperation(CodeGenFunction &CGF,
+                                         llvm::Value *addr,
+                                         llvm::Constant *&fn,
+                                         llvm::StringRef fnName) {
+  if (!fn) {
+    std::vector<const llvm::Type*> args(1, CGF.Int8PtrPtrTy);
+    const llvm::FunctionType *fnType =
+      llvm::FunctionType::get(CGF.Int8PtrTy, args, false);
+    fn = createARCRuntimeFunction(CGF.CGM, fnType, fnName);
+  }
+
+  // Cast the argument to 'id*'.
+  const llvm::Type *origType = addr->getType();
+  addr = CGF.Builder.CreateBitCast(addr, CGF.Int8PtrPtrTy);
+
+  // Call the function.
+  llvm::CallInst *call = CGF.Builder.CreateCall(fn, addr);
+  call->setDoesNotThrow();
+
+  // Cast the result back to a dereference of the original type.
+  llvm::Value *result = call;
+  if (origType != CGF.Int8PtrPtrTy)
+    result = CGF.Builder.CreateBitCast(result,
+                        cast<llvm::PointerType>(origType)->getElementType());
+
+  return result;
+}
+
+/// Perform an operation having the following signature:
+///   i8* (i8**, i8*)
+static llvm::Value *emitARCStoreOperation(CodeGenFunction &CGF,
+                                          llvm::Value *addr,
+                                          llvm::Value *value,
+                                          llvm::Constant *&fn,
+                                          llvm::StringRef fnName,
+                                          bool ignored) {
+  assert(cast<llvm::PointerType>(addr->getType())->getElementType()
+           == value->getType());
+
+  if (!fn) {
+    std::vector<const llvm::Type*> argTypes(2);
+    argTypes[0] = CGF.Int8PtrPtrTy;
+    argTypes[1] = CGF.Int8PtrTy;
+
+    const llvm::FunctionType *fnType
+      = llvm::FunctionType::get(CGF.Int8PtrTy, argTypes, false);
+    fn = createARCRuntimeFunction(CGF.CGM, fnType, fnName);
+  }
+
+  const llvm::Type *origType = value->getType();
+
+  addr = CGF.Builder.CreateBitCast(addr, CGF.Int8PtrPtrTy);
+  value = CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy);
+    
+  llvm::CallInst *result = CGF.Builder.CreateCall2(fn, addr, value);
+  result->setDoesNotThrow();
+
+  if (ignored) return 0;
+
+  return CGF.Builder.CreateBitCast(result, origType);
+}
+
+/// Perform an operation having the following signature:
+///   void (i8**, i8**)
+static void emitARCCopyOperation(CodeGenFunction &CGF,
+                                 llvm::Value *dst,
+                                 llvm::Value *src,
+                                 llvm::Constant *&fn,
+                                 llvm::StringRef fnName) {
+  assert(dst->getType() == src->getType());
+
+  if (!fn) {
+    std::vector<const llvm::Type*> argTypes(2, CGF.Int8PtrPtrTy);
+    const llvm::FunctionType *fnType
+      = llvm::FunctionType::get(CGF.Builder.getVoidTy(), argTypes, false);
+    fn = createARCRuntimeFunction(CGF.CGM, fnType, fnName);
+  }
+
+  dst = CGF.Builder.CreateBitCast(dst, CGF.Int8PtrPtrTy);
+  src = CGF.Builder.CreateBitCast(src, CGF.Int8PtrPtrTy);
+    
+  llvm::CallInst *result = CGF.Builder.CreateCall2(fn, dst, src);
+  result->setDoesNotThrow();
+}
+
+/// Produce the code to do a retain.  Based on the type, calls one of:
+///   call i8* @objc_retain(i8* %value)
+///   call i8* @objc_retainBlock(i8* %value)
+llvm::Value *CodeGenFunction::EmitARCRetain(QualType type, llvm::Value *value) {
+  if (type->isBlockPointerType())
+    return EmitARCRetainBlock(value);
+  else
+    return EmitARCRetainNonBlock(value);
+}
+
+/// Retain the given object, with normal retain semantics.
+///   call i8* @objc_retain(i8* %value)
+llvm::Value *CodeGenFunction::EmitARCRetainNonBlock(llvm::Value *value) {
+  return emitARCValueOperation(*this, value,
+                               CGM.getARCEntrypoints().objc_retain,
+                               "objc_retain");
+}
+
+/// Retain the given block, with _Block_copy semantics.
+///   call i8* @objc_retainBlock(i8* %value)
+llvm::Value *CodeGenFunction::EmitARCRetainBlock(llvm::Value *value) {
+  return emitARCValueOperation(*this, value,
+                               CGM.getARCEntrypoints().objc_retainBlock,
+                               "objc_retainBlock");
+}
+
+/// Retain the given object which is the result of a function call.
+///   call i8* @objc_retainAutoreleasedReturnValue(i8* %value)
+///
+/// Yes, this function name is one character away from a different
+/// call with completely different semantics.
+llvm::Value *
+CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) {
+  // Fetch the void(void) inline asm which marks that we're going to
+  // retain the autoreleased return value.
+  llvm::InlineAsm *&marker
+    = CGM.getARCEntrypoints().retainAutoreleasedReturnValueMarker;
+  if (!marker) {
+    llvm::StringRef assembly
+      = CGM.getTargetCodeGenInfo()
+           .getARCRetainAutoreleasedReturnValueMarker();
+
+    // If we have an empty assembly string, there's nothing to do.
+    if (assembly.empty()) {
+
+    // Otherwise, at -O0, build an inline asm that we're going to call
+    // in a moment.
+    } else if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
+      llvm::FunctionType *type =
+        llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()),
+                                /*variadic*/ false);
+      
+      marker = llvm::InlineAsm::get(type, assembly, "", /*sideeffects*/ true);
+
+    // If we're at -O1 and above, we don't want to litter the code
+    // with this marker yet, so leave a breadcrumb for the ARC
+    // optimizer to pick up.
+    } else {
+      llvm::NamedMDNode *metadata =
+        CGM.getModule().getOrInsertNamedMetadata(
+                            "clang.arc.retainAutoreleasedReturnValueMarker");
+      assert(metadata->getNumOperands() <= 1);
+      if (metadata->getNumOperands() == 0) {
+        llvm::Value *string = llvm::MDString::get(getLLVMContext(), assembly);
+        llvm::Value *args[] = { string };
+        metadata->addOperand(llvm::MDNode::get(getLLVMContext(), args));
+      }
+    }
+  }
+
+  // Call the marker asm if we made one, which we do only at -O0.
+  if (marker) Builder.CreateCall(marker);
+
+  return emitARCValueOperation(*this, value,
+                     CGM.getARCEntrypoints().objc_retainAutoreleasedReturnValue,
+                               "objc_retainAutoreleasedReturnValue");
+}
+
+/// Release the given object.
+///   call void @objc_release(i8* %value)
+void CodeGenFunction::EmitARCRelease(llvm::Value *value, bool precise) {
+  if (isa<llvm::ConstantPointerNull>(value)) return;
+
+  llvm::Constant *&fn = CGM.getARCEntrypoints().objc_release;
+  if (!fn) {
+    std::vector<const llvm::Type*> args(1, Int8PtrTy);
+    const llvm::FunctionType *fnType =
+      llvm::FunctionType::get(Builder.getVoidTy(), args, false);
+    fn = createARCRuntimeFunction(CGM, fnType, "objc_release");
+  }
+
+  // Cast the argument to 'id'.
+  value = Builder.CreateBitCast(value, Int8PtrTy);
+
+  // Call objc_release.
+  llvm::CallInst *call = Builder.CreateCall(fn, value);
+  call->setDoesNotThrow();
+
+  if (!precise) {
+    llvm::SmallVector<llvm::Value*,1> args;
+    call->setMetadata("clang.imprecise_release",
+                      llvm::MDNode::get(Builder.getContext(), args));
+  }
+}
+
+/// Store into a strong object.  Always calls this:
+///   call void @objc_storeStrong(i8** %addr, i8* %value)
+llvm::Value *CodeGenFunction::EmitARCStoreStrongCall(llvm::Value *addr,
+                                                     llvm::Value *value,
+                                                     bool ignored) {
+  assert(cast<llvm::PointerType>(addr->getType())->getElementType()
+           == value->getType());
+
+  llvm::Constant *&fn = CGM.getARCEntrypoints().objc_storeStrong;
+  if (!fn) {
+    const llvm::Type *argTypes[] = { Int8PtrPtrTy, Int8PtrTy };
+    const llvm::FunctionType *fnType
+      = llvm::FunctionType::get(Builder.getVoidTy(), argTypes, false);
+    fn = createARCRuntimeFunction(CGM, fnType, "objc_storeStrong");
+  }
+
+  addr = Builder.CreateBitCast(addr, Int8PtrPtrTy);
+  llvm::Value *castValue = Builder.CreateBitCast(value, Int8PtrTy);
+  
+  Builder.CreateCall2(fn, addr, castValue)->setDoesNotThrow();
+
+  if (ignored) return 0;
+  return value;
+}
+
+/// Store into a strong object.  Sometimes calls this:
+///   call void @objc_storeStrong(i8** %addr, i8* %value)
+/// Other times, breaks it down into components.
+llvm::Value *CodeGenFunction::EmitARCStoreStrong(LValue dst, QualType type,
+                                                 llvm::Value *newValue,
+                                                 bool ignored) {
+  bool isBlock = type->isBlockPointerType();
+
+  // Use a store barrier at -O0 unless this is a block type or the
+  // lvalue is inadequately aligned.
+  if (shouldUseFusedARCCalls() &&
+      !isBlock &&
+      !(dst.getAlignment() && dst.getAlignment() < PointerAlignInBytes)) {
+    return EmitARCStoreStrongCall(dst.getAddress(), newValue, ignored);
+  }
+
+  // Otherwise, split it out.
+
+  // Retain the new value.
+  newValue = EmitARCRetain(type, newValue);
+
+  // Read the old value.
+  llvm::Value *oldValue =
+    EmitLoadOfScalar(dst.getAddress(), dst.isVolatileQualified(),
+                     dst.getAlignment(), type, dst.getTBAAInfo());
+
+  // Store.  We do this before the release so that any deallocs won't
+  // see the old value.
+  EmitStoreOfScalar(newValue, dst.getAddress(),
+                    dst.isVolatileQualified(), dst.getAlignment(),
+                    type, dst.getTBAAInfo());
+
+  // Finally, release the old value.
+  EmitARCRelease(oldValue, /*precise*/ false);
+
+  return newValue;
+}
+
+/// Autorelease the given object.
+///   call i8* @objc_autorelease(i8* %value)
+llvm::Value *CodeGenFunction::EmitARCAutorelease(llvm::Value *value) {
+  return emitARCValueOperation(*this, value,
+                               CGM.getARCEntrypoints().objc_autorelease,
+                               "objc_autorelease");
+}
+
+/// Autorelease the given object.
+///   call i8* @objc_autoreleaseReturnValue(i8* %value)
+llvm::Value *
+CodeGenFunction::EmitARCAutoreleaseReturnValue(llvm::Value *value) {
+  return emitARCValueOperation(*this, value,
+                            CGM.getARCEntrypoints().objc_autoreleaseReturnValue,
+                               "objc_autoreleaseReturnValue");
+}
+
+/// Do a fused retain/autorelease of the given object.
+///   call i8* @objc_retainAutoreleaseReturnValue(i8* %value)
+llvm::Value *
+CodeGenFunction::EmitARCRetainAutoreleaseReturnValue(llvm::Value *value) {
+  return emitARCValueOperation(*this, value,
+                     CGM.getARCEntrypoints().objc_retainAutoreleaseReturnValue,
+                               "objc_retainAutoreleaseReturnValue");
+}
+
+/// Do a fused retain/autorelease of the given object.
+///   call i8* @objc_retainAutorelease(i8* %value)
+/// or
+///   %retain = call i8* @objc_retainBlock(i8* %value)
+///   call i8* @objc_autorelease(i8* %retain)
+llvm::Value *CodeGenFunction::EmitARCRetainAutorelease(QualType type,
+                                                       llvm::Value *value) {
+  if (!type->isBlockPointerType())
+    return EmitARCRetainAutoreleaseNonBlock(value);
+
+  if (isa<llvm::ConstantPointerNull>(value)) return value;
+
+  const llvm::Type *origType = value->getType();
+  value = Builder.CreateBitCast(value, Int8PtrTy);
+  value = EmitARCRetainBlock(value);
+  value = EmitARCAutorelease(value);
+  return Builder.CreateBitCast(value, origType);
+}
+
+/// Do a fused retain/autorelease of the given object.
+///   call i8* @objc_retainAutorelease(i8* %value)
+llvm::Value *
+CodeGenFunction::EmitARCRetainAutoreleaseNonBlock(llvm::Value *value) {
+  return emitARCValueOperation(*this, value,
+                               CGM.getARCEntrypoints().objc_retainAutorelease,
+                               "objc_retainAutorelease");
+}
+
+/// i8* @objc_loadWeak(i8** %addr)
+/// Essentially objc_autorelease(objc_loadWeakRetained(addr)).
+llvm::Value *CodeGenFunction::EmitARCLoadWeak(llvm::Value *addr) {
+  return emitARCLoadOperation(*this, addr,
+                              CGM.getARCEntrypoints().objc_loadWeak,
+                              "objc_loadWeak");
+}
+
+/// i8* @objc_loadWeakRetained(i8** %addr)
+llvm::Value *CodeGenFunction::EmitARCLoadWeakRetained(llvm::Value *addr) {
+  return emitARCLoadOperation(*this, addr,
+                              CGM.getARCEntrypoints().objc_loadWeakRetained,
+                              "objc_loadWeakRetained");
+}
+
+/// i8* @objc_storeWeak(i8** %addr, i8* %value)
+/// Returns %value.
+llvm::Value *CodeGenFunction::EmitARCStoreWeak(llvm::Value *addr,
+                                               llvm::Value *value,
+                                               bool ignored) {
+  return emitARCStoreOperation(*this, addr, value,
+                               CGM.getARCEntrypoints().objc_storeWeak,
+                               "objc_storeWeak", ignored);
+}
+
+/// i8* @objc_initWeak(i8** %addr, i8* %value)
+/// Returns %value.  %addr is known to not have a current weak entry.
+/// Essentially equivalent to:
+///   *addr = nil; objc_storeWeak(addr, value);
+void CodeGenFunction::EmitARCInitWeak(llvm::Value *addr, llvm::Value *value) {
+  // If we're initializing to null, just write null to memory; no need
+  // to get the runtime involved.  But don't do this if optimization
+  // is enabled, because accounting for this would make the optimizer
+  // much more complicated.
+  if (isa<llvm::ConstantPointerNull>(value) &&
+      CGM.getCodeGenOpts().OptimizationLevel == 0) {
+    Builder.CreateStore(value, addr);
+    return;
+  }
+
+  emitARCStoreOperation(*this, addr, value,
+                        CGM.getARCEntrypoints().objc_initWeak,
+                        "objc_initWeak", /*ignored*/ true);
+}
+
+/// void @objc_destroyWeak(i8** %addr)
+/// Essentially objc_storeWeak(addr, nil).
+void CodeGenFunction::EmitARCDestroyWeak(llvm::Value *addr) {
+  llvm::Constant *&fn = CGM.getARCEntrypoints().objc_destroyWeak;
+  if (!fn) {
+    std::vector<const llvm::Type*> args(1, Int8PtrPtrTy);
+    const llvm::FunctionType *fnType =
+      llvm::FunctionType::get(Builder.getVoidTy(), args, false);
+    fn = createARCRuntimeFunction(CGM, fnType, "objc_destroyWeak");
+  }
+
+  // Cast the argument to 'id*'.
+  addr = Builder.CreateBitCast(addr, Int8PtrPtrTy);
+
+  llvm::CallInst *call = Builder.CreateCall(fn, addr);
+  call->setDoesNotThrow();
+}
+
+/// void @objc_moveWeak(i8** %dest, i8** %src)
+/// Disregards the current value in %dest.  Leaves %src pointing to nothing.
+/// Essentially (objc_copyWeak(dest, src), objc_destroyWeak(src)).
+void CodeGenFunction::EmitARCMoveWeak(llvm::Value *dst, llvm::Value *src) {
+  emitARCCopyOperation(*this, dst, src,
+                       CGM.getARCEntrypoints().objc_moveWeak,
+                       "objc_moveWeak");
+}
+
+/// void @objc_copyWeak(i8** %dest, i8** %src)
+/// Disregards the current value in %dest.  Essentially
+///   objc_release(objc_initWeak(dest, objc_readWeakRetained(src)))
+void CodeGenFunction::EmitARCCopyWeak(llvm::Value *dst, llvm::Value *src) {
+  emitARCCopyOperation(*this, dst, src,
+                       CGM.getARCEntrypoints().objc_copyWeak,
+                       "objc_copyWeak");
+}
+
+/// Produce the code to do a objc_autoreleasepool_push.
+///   call i8* @objc_autoreleasePoolPush(void)
+llvm::Value *CodeGenFunction::EmitObjCAutoreleasePoolPush() {
+  llvm::Constant *&fn = CGM.getRREntrypoints().objc_autoreleasePoolPush;
+  if (!fn) {
+    const llvm::FunctionType *fnType =
+      llvm::FunctionType::get(Int8PtrTy, false);
+    fn = createARCRuntimeFunction(CGM, fnType, "objc_autoreleasePoolPush");
+  }
+
+  llvm::CallInst *call = Builder.CreateCall(fn);
+  call->setDoesNotThrow();
+
+  return call;
+}
+
+/// Produce the code to do a primitive release.
+///   call void @objc_autoreleasePoolPop(i8* %ptr)
+void CodeGenFunction::EmitObjCAutoreleasePoolPop(llvm::Value *value) {
+  assert(value->getType() == Int8PtrTy);
+
+  llvm::Constant *&fn = CGM.getRREntrypoints().objc_autoreleasePoolPop;
+  if (!fn) {
+    std::vector<const llvm::Type*> args(1, Int8PtrTy);
+    const llvm::FunctionType *fnType =
+      llvm::FunctionType::get(Builder.getVoidTy(), args, false);
+
+    // We don't want to use a weak import here; instead we should not
+    // fall into this path.
+    fn = createARCRuntimeFunction(CGM, fnType, "objc_autoreleasePoolPop");
+  }
+
+  llvm::CallInst *call = Builder.CreateCall(fn, value);
+  call->setDoesNotThrow();
+}
+
+/// Produce the code to do an MRR version objc_autoreleasepool_push.
+/// Which is: [[NSAutoreleasePool alloc] init];
+/// Where alloc is declared as: + (id) alloc; in NSAutoreleasePool class.
+/// init is declared as: - (id) init; in its NSObject super class.
+///
+llvm::Value *CodeGenFunction::EmitObjCMRRAutoreleasePoolPush() {
+  CGObjCRuntime &Runtime = CGM.getObjCRuntime();
+  llvm::Value *Receiver = Runtime.EmitNSAutoreleasePoolClassRef(Builder);
+  // [NSAutoreleasePool alloc]
+  IdentifierInfo *II = &CGM.getContext().Idents.get("alloc");
+  Selector AllocSel = getContext().Selectors.getSelector(0, &II);
+  CallArgList Args;
+  RValue AllocRV =  
+    Runtime.GenerateMessageSend(*this, ReturnValueSlot(), 
+                                getContext().getObjCIdType(),
+                                AllocSel, Receiver, Args); 
+
+  // [Receiver init]
+  Receiver = AllocRV.getScalarVal();
+  II = &CGM.getContext().Idents.get("init");
+  Selector InitSel = getContext().Selectors.getSelector(0, &II);
+  RValue InitRV =
+    Runtime.GenerateMessageSend(*this, ReturnValueSlot(),
+                                getContext().getObjCIdType(),
+                                InitSel, Receiver, Args); 
+  return InitRV.getScalarVal();
+}
+
+/// Produce the code to do a primitive release.
+/// [tmp drain];
+void CodeGenFunction::EmitObjCMRRAutoreleasePoolPop(llvm::Value *Arg) {
+  IdentifierInfo *II = &CGM.getContext().Idents.get("drain");
+  Selector DrainSel = getContext().Selectors.getSelector(0, &II);
+  CallArgList Args;
+  CGM.getObjCRuntime().GenerateMessageSend(*this, ReturnValueSlot(),
+                              getContext().VoidTy, DrainSel, Arg, Args); 
+}
+
+namespace {
+  struct ObjCReleasingCleanup : EHScopeStack::Cleanup {
+  private:
+    QualType type;
+    llvm::Value *addr;
+
+  protected:
+    ObjCReleasingCleanup(QualType type, llvm::Value *addr)
+      : type(type), addr(addr) {}
+
+    virtual llvm::Value *getAddress(CodeGenFunction &CGF,
+                                    llvm::Value *addr) {
+      return addr;
+    }
+
+    virtual void release(CodeGenFunction &CGF,
+                         QualType type,
+                         llvm::Value *addr) = 0;
+
+  public:
+    void Emit(CodeGenFunction &CGF, bool isForEH) {
+      const ArrayType *arrayType = CGF.getContext().getAsArrayType(type);
+
+      llvm::Value *addr = getAddress(CGF, this->addr);
+
+      // If we don't have an array type, this is easy.
+      if (!arrayType)
+        return release(CGF, type, addr);
+
+      llvm::Value *begin = addr;
+      QualType baseType;
+
+      // Otherwise, this is more painful.
+      llvm::Value *count = emitArrayLength(CGF, arrayType, baseType,
+                                           begin);
+
+      assert(baseType == CGF.getContext().getBaseElementType(arrayType));
+
+      llvm::BasicBlock *incomingBB = CGF.Builder.GetInsertBlock();
+
+      //   id *cur = begin;
+      //   id *end = begin + count;
+      llvm::Value *end =
+        CGF.Builder.CreateInBoundsGEP(begin, count, "array.end");
+
+      // loopBB:
+      llvm::BasicBlock *loopBB = CGF.createBasicBlock("release-loop");
+      CGF.EmitBlock(loopBB);
+
+      llvm::PHINode *cur = CGF.Builder.CreatePHI(begin->getType(), 2, "cur");
+      cur->addIncoming(begin, incomingBB);
+
+      //   if (cur == end) goto endBB;
+      llvm::Value *eq = CGF.Builder.CreateICmpEQ(cur, end, "release-loop.done");
+      llvm::BasicBlock *bodyBB = CGF.createBasicBlock("release-loop.body");
+      llvm::BasicBlock *endBB = CGF.createBasicBlock("release-loop.cont");
+      CGF.Builder.CreateCondBr(eq, endBB, bodyBB);
+      CGF.EmitBlock(bodyBB);
+
+      // Release the value at 'cur'.
+      release(CGF, baseType, cur);
+
+      //   ++cur;
+      //   goto loopBB;
+      llvm::Value *next = CGF.Builder.CreateConstInBoundsGEP1_32(cur, 1);
+      cur->addIncoming(next, CGF.Builder.GetInsertBlock());
+      CGF.Builder.CreateBr(loopBB);
+
+      // endBB:
+      CGF.EmitBlock(endBB);
+    }
+
+  private:
+    /// Computes the length of an array in elements, as well
+    /// as the base
+    static llvm::Value *emitArrayLength(CodeGenFunction &CGF,
+                                        const ArrayType *origArrayType,
+                                        QualType &baseType,
+                                        llvm::Value *&addr) {
+      ASTContext &Ctx = CGF.getContext();
+      const ArrayType *arrayType = origArrayType;
+
+      // If it's a VLA, we have to load the stored size.  Note that
+      // this is the size of the VLA in bytes, not its size in elements.
+      llvm::Value *vlaSizeInBytes = 0;
+      if (isa<VariableArrayType>(arrayType)) {
+        vlaSizeInBytes = CGF.GetVLASize(cast<VariableArrayType>(arrayType));
+
+        // Walk into all VLAs.  This doesn't require changes to addr,
+        // which has type T* where T is the first non-VLA element type.
+        do {
+          QualType elementType = arrayType->getElementType();
+          arrayType = Ctx.getAsArrayType(elementType);
+
+          // If we only have VLA components, 'addr' requires no adjustment.
+          if (!arrayType) {
+            baseType = elementType;
+            return divideVLASizeByBaseType(CGF, vlaSizeInBytes, baseType);
+          }
+        } while (isa<VariableArrayType>(arrayType));
+
+        // We get out here only if we find a constant array type
+        // inside the VLA.
+      }
+
+      // We have some number of constant-length arrays, so addr should
+      // have LLVM type [M x [N x [...]]]*.  Build a GEP that walks
+      // down to the first element of addr.
+      llvm::SmallVector<llvm::Value*, 8> gepIndices;
+
+      // GEP down to the array type.
+      llvm::ConstantInt *zero = CGF.Builder.getInt32(0);
+      gepIndices.push_back(zero);
+
+      // It's more efficient to calculate the count from the LLVM
+      // constant-length arrays than to re-evaluate the array bounds.
+      uint64_t countFromCLAs = 1;
+
+      const llvm::ArrayType *llvmArrayType =
+        cast<llvm::ArrayType>(
+          cast<llvm::PointerType>(addr->getType())->getElementType());
+      while (true) {
+        assert(isa<ConstantArrayType>(arrayType));
+        assert(cast<ConstantArrayType>(arrayType)->getSize().getZExtValue()
+                 == llvmArrayType->getNumElements());
+
+        gepIndices.push_back(zero);
+        countFromCLAs *= llvmArrayType->getNumElements();
+
+        llvmArrayType =
+          dyn_cast<llvm::ArrayType>(llvmArrayType->getElementType());
+        if (!llvmArrayType) break;
+
+        arrayType = Ctx.getAsArrayType(arrayType->getElementType());
+        assert(arrayType && "LLVM and Clang types are out-of-synch");
+      }
+
+      // Create the actual GEP.
+      addr = CGF.Builder.CreateInBoundsGEP(addr, gepIndices.begin(),
+                                           gepIndices.end(), "array.begin");
+
+      baseType = arrayType->getElementType();
+
+      // If we had an VLA dimensions, we need to use the captured size.
+      if (vlaSizeInBytes)
+        return divideVLASizeByBaseType(CGF, vlaSizeInBytes, baseType);
+
+      // Otherwise, use countFromCLAs.
+      assert(countFromCLAs == (uint64_t)
+               (Ctx.getTypeSizeInChars(origArrayType).getQuantity() /
+                Ctx.getTypeSizeInChars(baseType).getQuantity()));
+
+      return llvm::ConstantInt::get(CGF.IntPtrTy, countFromCLAs);
+    }
+
+    static llvm::Value *divideVLASizeByBaseType(CodeGenFunction &CGF,
+                                                llvm::Value *vlaSizeInBytes,
+                                                QualType baseType) {
+      // Divide the base type size back out of the 
+      CharUnits baseSize = CGF.getContext().getTypeSizeInChars(baseType);
+      llvm::Value *baseSizeInBytes =
+        llvm::ConstantInt::get(vlaSizeInBytes->getType(),
+                               baseSize.getQuantity());
+
+      return CGF.Builder.CreateUDiv(vlaSizeInBytes, baseSizeInBytes,
+                                    "array.vla-count");
+    }
+  };
+
+  /// A cleanup that calls @objc_release on all the objects to release.
+  struct CallReleaseForObject : ObjCReleasingCleanup {
+    bool precise;
+    CallReleaseForObject(QualType type, llvm::Value *addr, bool precise)
+      : ObjCReleasingCleanup(type, addr), precise(precise) {}
+
+    void release(CodeGenFunction &CGF, QualType type, llvm::Value *addr) {
+      llvm::Value *ptr = CGF.Builder.CreateLoad(addr, "tmp");
+      CGF.EmitARCRelease(ptr, precise);
+    }
+  };
+
+  /// A cleanup that calls @objc_storeStrong(nil) on all the objects to
+  /// release in an ivar.
+  struct CallReleaseForIvar : ObjCReleasingCleanup {
+    const ObjCIvarDecl *ivar;
+    CallReleaseForIvar(const ObjCIvarDecl *ivar, llvm::Value *self)
+      : ObjCReleasingCleanup(ivar->getType(), self), ivar(ivar) {}
+
+    llvm::Value *getAddress(CodeGenFunction &CGF, llvm::Value *addr) {
+      LValue lvalue
+        = CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), addr, ivar, /*CVR*/ 0);
+      return lvalue.getAddress();
+    }
+
+    void release(CodeGenFunction &CGF, QualType type, llvm::Value *addr) {
+      // Release ivars by storing nil into them;  it just makes things easier.
+      llvm::Value *null = getNullForVariable(addr);
+      CGF.EmitARCStoreStrongCall(addr, null, /*ignored*/ true);
+    }
+  };
+
+  /// A cleanup that calls @objc_release on all of the objects to release in
+  /// a field.
+  struct CallReleaseForField : CallReleaseForObject {
+    const FieldDecl *Field;
+    
+    explicit CallReleaseForField(const FieldDecl *Field)
+      : CallReleaseForObject(Field->getType(), 0, /*precise=*/true),
+        Field(Field) { }
+    
+    llvm::Value *getAddress(CodeGenFunction &CGF, llvm::Value *) {
+      llvm::Value *This = CGF.LoadCXXThis();      
+      LValue LV = CGF.EmitLValueForField(This, Field, 0);
+      return LV.getAddress();
+    }
+  };
+  
+  /// A cleanup that calls @objc_weak_release on all the objects to
+  /// release in an object.
+  struct CallWeakReleaseForObject : ObjCReleasingCleanup {
+    CallWeakReleaseForObject(QualType type, llvm::Value *addr)
+      : ObjCReleasingCleanup(type, addr) {}
+
+    void release(CodeGenFunction &CGF, QualType type, llvm::Value *addr) {
+      CGF.EmitARCDestroyWeak(addr);
+    }
+  };
+
+  
+  /// A cleanup that calls @objc_weak_release on all the objects to
+  /// release in an ivar.
+  struct CallWeakReleaseForIvar : CallWeakReleaseForObject {
+    const ObjCIvarDecl *ivar;
+    CallWeakReleaseForIvar(const ObjCIvarDecl *ivar, llvm::Value *self)
+    : CallWeakReleaseForObject(ivar->getType(), self), ivar(ivar) {}
+    
+    llvm::Value *getAddress(CodeGenFunction &CGF, llvm::Value *addr) {
+      LValue lvalue
+      = CGF.EmitLValueForIvar(CGF.TypeOfSelfObject(), addr, ivar, /*CVR*/ 0);
+      return lvalue.getAddress();
+    }
+  };
+
+  /// A cleanup that calls @objc_weak_release on all the objects to
+  /// release in a field;
+  struct CallWeakReleaseForField : CallWeakReleaseForObject {
+    const FieldDecl *Field;
+    CallWeakReleaseForField(const FieldDecl *Field)
+      : CallWeakReleaseForObject(Field->getType(), 0), Field(Field) {}
+    
+    llvm::Value *getAddress(CodeGenFunction &CGF, llvm::Value *) {
+      llvm::Value *This = CGF.LoadCXXThis();      
+      LValue LV = CGF.EmitLValueForField(This, Field, 0);
+      return LV.getAddress();
+    }
+  };
+  
+  struct CallObjCAutoreleasePoolObject : EHScopeStack::Cleanup {
+    llvm::Value *Token;
+
+    CallObjCAutoreleasePoolObject(llvm::Value *token) : Token(token) {}
+
+    void Emit(CodeGenFunction &CGF, bool isForEH) {
+      CGF.EmitObjCAutoreleasePoolPop(Token);
+    }
+  };
+  struct CallObjCMRRAutoreleasePoolObject : EHScopeStack::Cleanup {
+    llvm::Value *Token;
+
+    CallObjCMRRAutoreleasePoolObject(llvm::Value *token) : Token(token) {}
+
+    void Emit(CodeGenFunction &CGF, bool isForEH) {
+      CGF.EmitObjCMRRAutoreleasePoolPop(Token);
+    }
+  };
+}
+
+void CodeGenFunction::EmitObjCAutoreleasePoolCleanup(llvm::Value *Ptr) {
+  if (CGM.getLangOptions().ObjCAutoRefCount)
+    EHStack.pushCleanup<CallObjCAutoreleasePoolObject>(NormalCleanup, Ptr);
+  else
+    EHStack.pushCleanup<CallObjCMRRAutoreleasePoolObject>(NormalCleanup, Ptr);
+}
+
+/// PushARCReleaseCleanup - Enter a cleanup to perform a release on a
+/// given object or array of objects.
+void CodeGenFunction::PushARCReleaseCleanup(CleanupKind cleanupKind,
+                                            QualType type,
+                                            llvm::Value *addr,
+                                            bool precise) {
+  EHStack.pushCleanup<CallReleaseForObject>(cleanupKind, type, addr, precise);
+}
+
+/// PushARCWeakReleaseCleanup - Enter a cleanup to perform a weak
+/// release on the given object or array of objects.
+void CodeGenFunction::PushARCWeakReleaseCleanup(CleanupKind cleanupKind,
+                                                QualType type,
+                                                llvm::Value *addr) {
+  EHStack.pushCleanup<CallWeakReleaseForObject>(cleanupKind, type, addr);
+}
+
+/// PushARCReleaseCleanup - Enter a cleanup to perform a release on a
+/// given object or array of objects.
+void CodeGenFunction::PushARCFieldReleaseCleanup(CleanupKind cleanupKind,
+                                                 const FieldDecl *field) {
+  EHStack.pushCleanup<CallReleaseForField>(cleanupKind, field);
+}
+
+/// PushARCWeakReleaseCleanup - Enter a cleanup to perform a weak
+/// release on the given object or array of objects.
+void CodeGenFunction::PushARCFieldWeakReleaseCleanup(CleanupKind cleanupKind,
+                                                     const FieldDecl *field) {
+  EHStack.pushCleanup<CallWeakReleaseForField>(cleanupKind, field);
+}
+
+static void pushReleaseForIvar(CodeGenFunction &CGF, ObjCIvarDecl *ivar,
+                               llvm::Value *self) {
+  CGF.EHStack.pushCleanup<CallReleaseForIvar>(CGF.getARCCleanupKind(),
+                                              ivar, self);
+}
+
+static void pushWeakReleaseForIvar(CodeGenFunction &CGF, ObjCIvarDecl *ivar,
+                                   llvm::Value *self) {
+  CGF.EHStack.pushCleanup<CallWeakReleaseForIvar>(CGF.getARCCleanupKind(),
+                                                  ivar, self);
+}
+
+static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF,
+                                                  LValue lvalue,
+                                                  QualType type) {
+  switch (type.getObjCLifetime()) {
+  case Qualifiers::OCL_None:
+  case Qualifiers::OCL_ExplicitNone:
+  case Qualifiers::OCL_Strong:
+  case Qualifiers::OCL_Autoreleasing:
+    return TryEmitResult(CGF.EmitLoadOfLValue(lvalue, type).getScalarVal(),
+                         false);
+
+  case Qualifiers::OCL_Weak:
+    return TryEmitResult(CGF.EmitARCLoadWeakRetained(lvalue.getAddress()),
+                         true);
+  }
+
+  llvm_unreachable("impossible lifetime!");
+  return TryEmitResult();
+}
+
+static TryEmitResult tryEmitARCRetainLoadOfScalar(CodeGenFunction &CGF,
+                                                  const Expr *e) {
+  e = e->IgnoreParens();
+  QualType type = e->getType();
+
+  // As a very special optimization, in ARC++, if the l-value is the
+  // result of a non-volatile assignment, do a simple retain of the
+  // result of the call to objc_storeWeak instead of reloading.
+  if (CGF.getLangOptions().CPlusPlus &&
+      !type.isVolatileQualified() &&
+      type.getObjCLifetime() == Qualifiers::OCL_Weak &&
+      isa<BinaryOperator>(e) &&
+      cast<BinaryOperator>(e)->getOpcode() == BO_Assign)
+    return TryEmitResult(CGF.EmitScalarExpr(e), false);
+
+  return tryEmitARCRetainLoadOfScalar(CGF, CGF.EmitLValue(e), type);
+}
+
+static llvm::Value *emitARCRetainAfterCall(CodeGenFunction &CGF,
+                                           llvm::Value *value);
+
+/// Given that the given expression is some sort of call (which does
+/// not return retained), emit a retain following it.
+static llvm::Value *emitARCRetainCall(CodeGenFunction &CGF, const Expr *e) {
+  llvm::Value *value = CGF.EmitScalarExpr(e);
+  return emitARCRetainAfterCall(CGF, value);
+}
+
+static llvm::Value *emitARCRetainAfterCall(CodeGenFunction &CGF,
+                                           llvm::Value *value) {
+  if (llvm::CallInst *call = dyn_cast<llvm::CallInst>(value)) {
+    CGBuilderTy::InsertPoint ip = CGF.Builder.saveIP();
+
+    // Place the retain immediately following the call.
+    CGF.Builder.SetInsertPoint(call->getParent(),
+                               ++llvm::BasicBlock::iterator(call));
+    value = CGF.EmitARCRetainAutoreleasedReturnValue(value);
+
+    CGF.Builder.restoreIP(ip);
+    return value;
+  } else if (llvm::InvokeInst *invoke = dyn_cast<llvm::InvokeInst>(value)) {
+    CGBuilderTy::InsertPoint ip = CGF.Builder.saveIP();
+
+    // Place the retain at the beginning of the normal destination block.
+    llvm::BasicBlock *BB = invoke->getNormalDest();
+    CGF.Builder.SetInsertPoint(BB, BB->begin());
+    value = CGF.EmitARCRetainAutoreleasedReturnValue(value);
+
+    CGF.Builder.restoreIP(ip);
+    return value;
+
+  // Bitcasts can arise because of related-result returns.  Rewrite
+  // the operand.
+  } else if (llvm::BitCastInst *bitcast = dyn_cast<llvm::BitCastInst>(value)) {
+    llvm::Value *operand = bitcast->getOperand(0);
+    operand = emitARCRetainAfterCall(CGF, operand);
+    bitcast->setOperand(0, operand);
+    return bitcast;
+
+  // Generic fall-back case.
+  } else {
+    // Retain using the non-block variant: we never need to do a copy
+    // of a block that's been returned to us.
+    return CGF.EmitARCRetainNonBlock(value);
+  }
+}
+
+static TryEmitResult
+tryEmitARCRetainScalarExpr(CodeGenFunction &CGF, const Expr *e) {
+  QualType originalType = e->getType();
+
+  // The desired result type, if it differs from the type of the
+  // ultimate opaque expression.
+  const llvm::Type *resultType = 0;
+
+  while (true) {
+    e = e->IgnoreParens();
+
+    // There's a break at the end of this if-chain;  anything
+    // that wants to keep looping has to explicitly continue.
+    if (const CastExpr *ce = dyn_cast<CastExpr>(e)) {
+      switch (ce->getCastKind()) {
+      // No-op casts don't change the type, so we just ignore them.
+      case CK_NoOp:
+        e = ce->getSubExpr();
+        continue;
+
+      case CK_LValueToRValue: {
+        TryEmitResult loadResult
+          = tryEmitARCRetainLoadOfScalar(CGF, ce->getSubExpr());
+        if (resultType) {
+          llvm::Value *value = loadResult.getPointer();
+          value = CGF.Builder.CreateBitCast(value, resultType);
+          loadResult.setPointer(value);
+        }
+        return loadResult;
+      }
+
+      // These casts can change the type, so remember that and
+      // soldier on.  We only need to remember the outermost such
+      // cast, though.
+      case CK_AnyPointerToObjCPointerCast:
+      case CK_AnyPointerToBlockPointerCast:
+      case CK_BitCast:
+        if (!resultType)
+          resultType = CGF.ConvertType(ce->getType());
+        e = ce->getSubExpr();
+        assert(e->getType()->hasPointerRepresentation());
+        continue;
+
+      // For consumptions, just emit the subexpression and thus elide
+      // the retain/release pair.
+      case CK_ObjCConsumeObject: {
+        llvm::Value *result = CGF.EmitScalarExpr(ce->getSubExpr());
+        if (resultType) result = CGF.Builder.CreateBitCast(result, resultType);
+        return TryEmitResult(result, true);
+      }
+
+      case CK_GetObjCProperty: {
+        llvm::Value *result = emitARCRetainCall(CGF, ce);
+        if (resultType) result = CGF.Builder.CreateBitCast(result, resultType);
+        return TryEmitResult(result, true);
+      }
+
+      default:
+        break;
+      }
+
+    // Skip __extension__.
+    } else if (const UnaryOperator *op = dyn_cast<UnaryOperator>(e)) {
+      if (op->getOpcode() == UO_Extension) {
+        e = op->getSubExpr();
+        continue;
+      }
+
+    // For calls and message sends, use the retained-call logic.
+    // Delegate inits are a special case in that they're the only
+    // returns-retained expression that *isn't* surrounded by
+    // a consume.
+    } else if (isa<CallExpr>(e) ||
+               (isa<ObjCMessageExpr>(e) &&
+                !cast<ObjCMessageExpr>(e)->isDelegateInitCall())) {
+      llvm::Value *result = emitARCRetainCall(CGF, e);
+      if (resultType) result = CGF.Builder.CreateBitCast(result, resultType);
+      return TryEmitResult(result, true);
+    }
+
+    // Conservatively halt the search at any other expression kind.
+    break;
+  }
+
+  // We didn't find an obvious production, so emit what we've got and
+  // tell the caller that we didn't manage to retain.
+  llvm::Value *result = CGF.EmitScalarExpr(e);
+  if (resultType) result = CGF.Builder.CreateBitCast(result, resultType);
+  return TryEmitResult(result, false);
+}
+
+static llvm::Value *emitARCRetainLoadOfScalar(CodeGenFunction &CGF,
+                                                LValue lvalue,
+                                                QualType type) {
+  TryEmitResult result = tryEmitARCRetainLoadOfScalar(CGF, lvalue, type);
+  llvm::Value *value = result.getPointer();
+  if (!result.getInt())
+    value = CGF.EmitARCRetain(type, value);
+  return value;
+}
+
+/// EmitARCRetainScalarExpr - Semantically equivalent to
+/// EmitARCRetainObject(e->getType(), EmitScalarExpr(e)), but making a
+/// best-effort attempt to peephole expressions that naturally produce
+/// retained objects.
+llvm::Value *CodeGenFunction::EmitARCRetainScalarExpr(const Expr *e) {
+  TryEmitResult result = tryEmitARCRetainScalarExpr(*this, e);
+  llvm::Value *value = result.getPointer();
+  if (!result.getInt())
+    value = EmitARCRetain(e->getType(), value);
+  return value;
+}
+
+llvm::Value *
+CodeGenFunction::EmitARCRetainAutoreleaseScalarExpr(const Expr *e) {
+  TryEmitResult result = tryEmitARCRetainScalarExpr(*this, e);
+  llvm::Value *value = result.getPointer();
+  if (result.getInt())
+    value = EmitARCAutorelease(value);
+  else
+    value = EmitARCRetainAutorelease(e->getType(), value);
+  return value;
+}
+
+std::pair<LValue,llvm::Value*>
+CodeGenFunction::EmitARCStoreStrong(const BinaryOperator *e,
+                                    bool ignored) {
+  // Evaluate the RHS first.
+  TryEmitResult result = tryEmitARCRetainScalarExpr(*this, e->getRHS());
+  llvm::Value *value = result.getPointer();
+
+  LValue lvalue = EmitLValue(e->getLHS());
+
+  // If the RHS was emitted retained, expand this.
+  if (result.getInt()) {
+    llvm::Value *oldValue =
+      EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatileQualified(),
+                       lvalue.getAlignment(), e->getType(),
+                       lvalue.getTBAAInfo());
+    EmitStoreOfScalar(value, lvalue.getAddress(),
+                      lvalue.isVolatileQualified(), lvalue.getAlignment(),
+                      e->getType(), lvalue.getTBAAInfo());
+    EmitARCRelease(oldValue, /*precise*/ false);
+  } else {
+    value = EmitARCStoreStrong(lvalue, e->getType(), value, ignored);
+  }
+
+  return std::pair<LValue,llvm::Value*>(lvalue, value);
+}
+
+std::pair<LValue,llvm::Value*>
+CodeGenFunction::EmitARCStoreAutoreleasing(const BinaryOperator *e) {
+  llvm::Value *value = EmitARCRetainAutoreleaseScalarExpr(e->getRHS());
+  LValue lvalue = EmitLValue(e->getLHS());
+
+  EmitStoreOfScalar(value, lvalue.getAddress(),
+                    lvalue.isVolatileQualified(), lvalue.getAlignment(),
+                    e->getType(), lvalue.getTBAAInfo());
+
+  return std::pair<LValue,llvm::Value*>(lvalue, value);
+}
+
+void CodeGenFunction::EmitObjCAutoreleasePoolStmt(
+                                             const ObjCAutoreleasePoolStmt &ARPS) {
+  const Stmt *subStmt = ARPS.getSubStmt();
+  const CompoundStmt &S = cast<CompoundStmt>(*subStmt);
+
+  CGDebugInfo *DI = getDebugInfo();
+  if (DI) {
+    DI->setLocation(S.getLBracLoc());
+    DI->EmitRegionStart(Builder);
+  }
+
+  // Keep track of the current cleanup stack depth.
+  RunCleanupsScope Scope(*this);
+  const llvm::Triple Triple = getContext().Target.getTriple();
+  if (CGM.getLangOptions().ObjCAutoRefCount ||
+      (CGM.isTargetDarwin() && 
+       ((Triple.getArch() == llvm::Triple::x86_64 && 
+         Triple.getDarwinMajorNumber() >= 11)
+        || (Triple.getEnvironmentName() == "iphoneos" && 
+            Triple.getDarwinMajorNumber() >= 5)))) {
+    llvm::Value *token = EmitObjCAutoreleasePoolPush();
+    EHStack.pushCleanup<CallObjCAutoreleasePoolObject>(NormalCleanup, token);
+  } else {
+    llvm::Value *token = EmitObjCMRRAutoreleasePoolPush();
+    EHStack.pushCleanup<CallObjCMRRAutoreleasePoolObject>(NormalCleanup, token);
+  }
+
+  for (CompoundStmt::const_body_iterator I = S.body_begin(),
+       E = S.body_end(); I != E; ++I)
+    EmitStmt(*I);
+
+  if (DI) {
+    DI->setLocation(S.getRBracLoc());
+    DI->EmitRegionEnd(Builder);
+  }
+}
 CGObjCRuntime::~CGObjCRuntime() {}

+ 2 - 2
lib/CodeGen/CGObjCGNU.cpp

@@ -969,7 +969,7 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF,
 
   ActualArgs.add(RValue::get(EnforceType(Builder, Receiver, IdTy)), ASTIdTy);
   ActualArgs.add(RValue::get(cmd), CGF.getContext().getObjCSelType());
-  ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
+  ActualArgs.addFrom(CallArgs);
 
   CodeGenTypes &Types = CGM.getTypes();
   const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
@@ -1121,7 +1121,7 @@ CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
   CallArgList ActualArgs;
   ActualArgs.add(RValue::get(Receiver), ASTIdTy);
   ActualArgs.add(RValue::get(cmd), CGF.getContext().getObjCSelType());
-  ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
+  ActualArgs.addFrom(CallArgs);
 
   CodeGenTypes &Types = CGM.getTypes();
   const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,

+ 92 - 37
lib/CodeGen/CGObjCMac.cpp

@@ -63,10 +63,13 @@ private:
   /// The default messenger, used for sends whose ABI is unchanged from
   /// the all-integer/pointer case.
   llvm::Constant *getMessageSendFn() const {
+    // Add the non-lazy-bind attribute, since objc_msgSend is likely to
+    // be called a lot.
     const llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
     return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
                                                              params, true),
-                                     "objc_msgSend");
+                                     "objc_msgSend",
+                                     llvm::Attribute::NonLazyBind);
   }
 
   /// void objc_msgSend_stret (id, SEL, ...)
@@ -887,6 +890,11 @@ private:
   llvm::Value *EmitClassRef(CGBuilderTy &Builder,
                             const ObjCInterfaceDecl *ID);
   
+  llvm::Value *EmitClassRefFromId(CGBuilderTy &Builder,
+                                  IdentifierInfo *II);
+  
+  llvm::Value *EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder);
+  
   /// EmitSuperClassRef - Emits reference to class's main metadata class.
   llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
 
@@ -1158,6 +1166,11 @@ private:
   /// for the given class reference.
   llvm::Value *EmitClassRef(CGBuilderTy &Builder,
                             const ObjCInterfaceDecl *ID);
+  
+  llvm::Value *EmitClassRefFromId(CGBuilderTy &Builder,
+                                  IdentifierInfo *II);
+  
+  llvm::Value *EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder);
 
   /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
   /// for the given super class reference.
@@ -1526,7 +1539,7 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF,
     Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
   ActualArgs.add(RValue::get(Arg0), Arg0Ty);
   ActualArgs.add(RValue::get(Sel), CGF.getContext().getObjCSelType());
-  ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
+  ActualArgs.addFrom(CallArgs);
 
   CodeGenTypes &Types = CGM.getTypes();
   const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
@@ -1562,7 +1575,7 @@ static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
   if (FQT.isObjCGCStrong())
     return Qualifiers::Strong;
   
-  if (FQT.isObjCGCWeak())
+  if (FQT.isObjCGCWeak() || FQT.getObjCLifetime() == Qualifiers::OCL_Weak)
     return Qualifiers::Weak;
   
   if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
@@ -1579,7 +1592,8 @@ llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
   llvm::Constant *nullPtr = 
     llvm::Constant::getNullValue(llvm::Type::getInt8PtrTy(VMContext));
 
-  if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
+  if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC &&
+      !CGM.getLangOptions().ObjCAutoRefCount)
     return nullPtr;
 
   bool hasUnion = false;
@@ -2129,7 +2143,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
                      Interface->all_referenced_protocol_begin(),
                      Interface->all_referenced_protocol_end());
   unsigned Flags = eClassFlags_Factory;
-  if (ID->getNumIvarInitializers())
+  if (ID->hasCXXStructors())
     Flags |= eClassFlags_HasCXXStructors;
   unsigned Size =
     CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity();
@@ -3461,25 +3475,35 @@ llvm::Constant *CGObjCMac::EmitModuleSymbols() {
   return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
 }
 
-llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
-                                     const ObjCInterfaceDecl *ID) {
-  LazySymbols.insert(ID->getIdentifier());
-
-  llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
-
+llvm::Value *CGObjCMac::EmitClassRefFromId(CGBuilderTy &Builder,
+                                     IdentifierInfo *II) {
+  LazySymbols.insert(II);
+  
+  llvm::GlobalVariable *&Entry = ClassReferences[II];
+  
   if (!Entry) {
     llvm::Constant *Casted =
-      llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
-                                     ObjCTypes.ClassPtrTy);
+    llvm::ConstantExpr::getBitCast(GetClassName(II),
+                                   ObjCTypes.ClassPtrTy);
     Entry =
-      CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
-                        "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
-                        4, true);
+    CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
+                      "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
+                      4, true);
   }
-
+  
   return Builder.CreateLoad(Entry, "tmp");
 }
 
+llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
+                                     const ObjCInterfaceDecl *ID) {
+  return EmitClassRefFromId(Builder, ID->getIdentifier());
+}
+
+llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder) {
+  IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
+  return EmitClassRefFromId(Builder, II);
+}
+
 llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
                                      bool lvalue) {
   llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
@@ -3567,12 +3591,18 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
   uint64_t MaxFieldOffset = 0;
   uint64_t MaxSkippedFieldOffset = 0;
   uint64_t LastBitfieldOrUnnamedOffset = 0;
+  uint64_t FirstFieldDelta = 0;
 
   if (RecFields.empty())
     return;
   unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
   unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
-
+  if (!RD && CGM.getLangOptions().ObjCAutoRefCount) {
+    FieldDecl *FirstField = RecFields[0];
+    FirstFieldDelta = 
+      ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(FirstField));
+  }
+  
   for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
     FieldDecl *Field = RecFields[i];
     uint64_t FieldOffset;
@@ -3580,9 +3610,10 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
       // Note that 'i' here is actually the field index inside RD of Field,
       // although this dependency is hidden.
       const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
-      FieldOffset = RL.getFieldOffset(i) / ByteSizeInBits;
+      FieldOffset = (RL.getFieldOffset(i) / ByteSizeInBits) - FirstFieldDelta;
     } else
-      FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field));
+      FieldOffset = 
+        ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field)) - FirstFieldDelta;
 
     // Skip over unnamed or bitfields
     if (!Field->getIdentifier() || Field->isBitField()) {
@@ -3861,12 +3892,16 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
   bool hasUnion = false;
 
   const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
-  if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
+  if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC &&
+      !CGM.getLangOptions().ObjCAutoRefCount)
     return llvm::Constant::getNullValue(PtrTy);
 
   llvm::SmallVector<ObjCIvarDecl*, 32> Ivars;
   const ObjCInterfaceDecl *OI = OMD->getClassInterface();
-  CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
+  if (CGM.getLangOptions().ObjCAutoRefCount)
+    CGM.getContext().ShallowCollectObjCIvars(OI, Ivars);
+  else
+    CGM.getContext().DeepCollectObjCIvars(OI, true, Ivars);
 
   llvm::SmallVector<FieldDecl*, 32> RecFields;
   for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
@@ -4743,7 +4778,12 @@ enum MetaDataDlags {
   CLS_META = 0x1,
   CLS_ROOT = 0x2,
   OBJC2_CLS_HIDDEN = 0x10,
-  CLS_EXCEPTION = 0x20
+  CLS_EXCEPTION = 0x20,
+
+  /// (Obsolete) ARC-specific: this class has a .release_ivars method
+  CLS_HAS_IVAR_RELEASER = 0x40,
+  /// class was compiled with -fobjc-arr
+  CLS_COMPILED_BY_ARC = 0x80  // (1<<7)
 };
 /// BuildClassRoTInitializer - generate meta-data for:
 /// struct _class_ro_t {
@@ -4767,6 +4807,10 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
   const ObjCImplementationDecl *ID) {
   std::string ClassName = ID->getNameAsString();
   std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets!
+
+  if (CGM.getLangOptions().ObjCAutoRefCount)
+    flags |= CLS_COMPILED_BY_ARC;
+
   Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
   Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
   Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
@@ -4936,7 +4980,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
     ID->getClassInterface()->getVisibility() == HiddenVisibility;
   if (classIsHidden)
     flags |= OBJC2_CLS_HIDDEN;
-  if (ID->getNumIvarInitializers())
+  if (ID->hasCXXStructors())
     flags |= eClassFlags_ABI2_HasCXXStructors;
   if (!ID->getClassInterface()->getSuperClass()) {
     // class is root
@@ -4972,7 +5016,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
   flags = CLS;
   if (classIsHidden)
     flags |= OBJC2_CLS_HIDDEN;
-  if (ID->getNumIvarInitializers())
+  if (ID->hasCXXStructors())
     flags |= eClassFlags_ABI2_HasCXXStructors;
 
   if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
@@ -5719,28 +5763,39 @@ CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
   return GV;
 }
 
-llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
-                                                  const ObjCInterfaceDecl *ID) {
-  llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
-
+llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CGBuilderTy &Builder,
+                                                        IdentifierInfo *II) {
+  llvm::GlobalVariable *&Entry = ClassReferences[II];
+  
   if (!Entry) {
-    std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
+    std::string ClassName(getClassSymbolPrefix() + II->getName().str());
     llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
     Entry =
-      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
-                               false, llvm::GlobalValue::InternalLinkage,
-                               ClassGV,
-                               "\01L_OBJC_CLASSLIST_REFERENCES_$_");
+    new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
+                             false, llvm::GlobalValue::InternalLinkage,
+                             ClassGV,
+                             "\01L_OBJC_CLASSLIST_REFERENCES_$_");
     Entry->setAlignment(
-      CGM.getTargetData().getABITypeAlignment(
-        ObjCTypes.ClassnfABIPtrTy));
+                        CGM.getTargetData().getABITypeAlignment(
+                                                                ObjCTypes.ClassnfABIPtrTy));
     Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
     CGM.AddUsedGlobal(Entry);
   }
-
+  
   return Builder.CreateLoad(Entry, "tmp");
 }
 
+llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
+                                                  const ObjCInterfaceDecl *ID) {
+  return EmitClassRefFromId(Builder, ID->getIdentifier());
+}
+
+llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(
+                                                    CGBuilderTy &Builder) {
+  IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
+  return EmitClassRefFromId(Builder, II);
+}
+
 llvm::Value *
 CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
                                           const ObjCInterfaceDecl *ID) {

+ 7 - 1
lib/CodeGen/CGObjCRuntime.h

@@ -205,7 +205,13 @@ public:
   /// interface decl.
   virtual llvm::Value *GetClass(CGBuilderTy &Builder,
                                 const ObjCInterfaceDecl *OID) = 0;
-
+  
+  
+  virtual llvm::Value *EmitNSAutoreleasePoolClassRef(CGBuilderTy &Builder) {
+    assert(false &&"autoreleasepool unsupported in this ABI");
+    return 0;
+  }
+  
   /// EnumerationMutationFunction - Return the function that's called by the
   /// compiler when a mutation is detected during foreach iteration.
   virtual llvm::Constant *EnumerationMutationFunction() = 0;

+ 4 - 1
lib/CodeGen/CGStmt.cpp

@@ -151,6 +151,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) {
   case Stmt::ObjCForCollectionStmtClass:
     EmitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(*S));
     break;
+  case Stmt::ObjCAutoreleasePoolStmtClass:
+    EmitObjCAutoreleasePoolStmt(cast<ObjCAutoreleasePoolStmt>(*S));
+    break;
       
   case Stmt::CXXTryStmtClass:
     EmitCXXTryStmt(cast<CXXTryStmt>(*S));
@@ -764,7 +767,7 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
   } else if (RV->getType()->isAnyComplexType()) {
     EmitComplexExprIntoAddr(RV, ReturnValue, false);
   } else {
-    EmitAggExpr(RV, AggValueSlot::forAddr(ReturnValue, false, true));
+    EmitAggExpr(RV, AggValueSlot::forAddr(ReturnValue, Qualifiers(), true));
   }
 
   EmitBranchThroughCleanup(ReturnBlock);

+ 20 - 8
lib/CodeGen/CGValue.h

@@ -101,8 +101,6 @@ public:
 /// bitfields, this is not a simple LLVM pointer, it may be a pointer plus a
 /// bitrange.
 class LValue {
-  // FIXME: alignment?
-
   enum {
     Simple,       // This is a normal l-value, use getAddress().
     VectorElt,    // This is a vector element l-value (V[i]), use getVector*
@@ -318,9 +316,11 @@ public:
 class AggValueSlot {
   /// The address.
   llvm::Value *Addr;
+
+  // Qualifiers
+  Qualifiers Quals;
   
   // Associated flags.
-  bool VolatileFlag : 1;
   bool LifetimeFlag : 1;
   bool RequiresGCollection : 1;
   
@@ -335,25 +335,31 @@ public:
   static AggValueSlot ignored() {
     AggValueSlot AV;
     AV.Addr = 0;
-    AV.VolatileFlag = AV.LifetimeFlag = AV.RequiresGCollection = AV.IsZeroed =0;
+    AV.Quals = Qualifiers();
+    AV.LifetimeFlag = AV.RequiresGCollection = AV.IsZeroed =0;
     return AV;
   }
 
   /// forAddr - Make a slot for an aggregate value.
   ///
   /// \param Volatile - true if the slot should be volatile-initialized
+  ///
+  /// \param Qualifiers - The qualifiers that dictate how the slot
+  /// should be initialied. Only 'volatile' and the Objective-C
+  /// lifetime qualifiers matter.
+  ///
   /// \param LifetimeExternallyManaged - true if the slot's lifetime
   ///   is being externally managed; false if a destructor should be
   ///   registered for any temporaries evaluated into the slot
   /// \param RequiresGCollection - true if the slot is located
   ///   somewhere that ObjC GC calls should be emitted for
-  static AggValueSlot forAddr(llvm::Value *Addr, bool Volatile,
+  static AggValueSlot forAddr(llvm::Value *Addr, Qualifiers Quals,
                               bool LifetimeExternallyManaged,
                               bool RequiresGCollection = false,
                               bool IsZeroed = false) {
     AggValueSlot AV;
     AV.Addr = Addr;
-    AV.VolatileFlag = Volatile;
+    AV.Quals = Quals;
     AV.LifetimeFlag = LifetimeExternallyManaged;
     AV.RequiresGCollection = RequiresGCollection;
     AV.IsZeroed = IsZeroed;
@@ -362,7 +368,7 @@ public:
 
   static AggValueSlot forLValue(LValue LV, bool LifetimeExternallyManaged,
                                 bool RequiresGCollection = false) {
-    return forAddr(LV.getAddress(), LV.isVolatileQualified(),
+    return forAddr(LV.getAddress(), LV.getQuals(),
                    LifetimeExternallyManaged, RequiresGCollection);
   }
 
@@ -373,8 +379,14 @@ public:
     LifetimeFlag = Managed;
   }
 
+  Qualifiers getQualifiers() const { return Quals; }
+
   bool isVolatile() const {
-    return VolatileFlag;
+    return Quals.hasVolatile();
+  }
+
+  Qualifiers::ObjCLifetime getObjCLifetime() const {
+    return Quals.getObjCLifetime();
   }
 
   bool requiresGCollection() const {

+ 18 - 1
lib/CodeGen/CodeGenFunction.cpp

@@ -31,7 +31,7 @@ using namespace CodeGen;
 CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
   : CodeGenTypeCache(cgm), CGM(cgm),
     Target(CGM.getContext().Target), Builder(cgm.getModule().getContext()),
-    BlockInfo(0), BlockPointer(0),
+    AutoreleaseResult(false), BlockInfo(0), BlockPointer(0),
     NormalCleanupDest(0), EHCleanupDest(0), NextCleanupDestIndex(1),
     ExceptionSlot(0), EHSelectorSlot(0),
     DebugInfo(0), DisableDebugInfo(false), DidCallStackSave(false),
@@ -142,6 +142,13 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
   assert(BreakContinueStack.empty() &&
          "mismatched push/pop in break/continue stack!");
 
+  // Pop any cleanups that might have been associated with the
+  // parameters.  Do this in whatever block we're currently in; it's
+  // important to do this before we enter the return block or return
+  // edges will be *really* confused.
+  if (EHStack.stable_begin() != PrologueCleanupDepth)
+    PopCleanupBlocks(PrologueCleanupDepth);
+
   // Emit function epilog (to return).
   EmitReturnBlock();
 
@@ -311,9 +318,19 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
     ReturnValue = CurFn->arg_begin();
   } else {
     ReturnValue = CreateIRTemp(RetTy, "retval");
+
+    // Tell the epilog emitter to autorelease the result.  We do this
+    // now so that various specialized functions can suppress it
+    // during their IR-generation.
+    if (getLangOptions().ObjCAutoRefCount &&
+        !CurFnInfo->isReturnsRetained() &&
+        RetTy->isObjCRetainableType())
+      AutoreleaseResult = true;
   }
 
   EmitStartEHSpec(CurCodeDecl);
+
+  PrologueCleanupDepth = EHStack.stable_begin();
   EmitFunctionProlog(*CurFnInfo, CurFn, Args);
 
   if (D && isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance())

+ 79 - 4
lib/CodeGen/CodeGenFunction.h

@@ -18,6 +18,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/CharUnits.h"
+#include "clang/Frontend/CodeGenOptions.h"
 #include "clang/Basic/ABI.h"
 #include "clang/Basic/TargetInfo.h"
 #include "llvm/ADT/DenseMap.h"
@@ -63,6 +64,7 @@ namespace clang {
   class ObjCAtTryStmt;
   class ObjCAtThrowStmt;
   class ObjCAtSynchronizedStmt;
+  class ObjCAutoreleasePoolStmt;
 
 namespace CodeGen {
   class CodeGenTypes;
@@ -568,6 +570,10 @@ public:
   /// CurGD - The GlobalDecl for the current function being compiled.
   GlobalDecl CurGD;
 
+  /// PrologueCleanupDepth - The cleanup depth enclosing all the
+  /// cleanups associated with the parameters.
+  EHScopeStack::stable_iterator PrologueCleanupDepth;
+
   /// ReturnBlock - Unified return block.
   JumpDest ReturnBlock;
 
@@ -584,6 +590,9 @@ public:
 
   bool CatchUndefined;
 
+  /// In ARC, whether we should autorelease the return value.
+  bool AutoreleaseResult;
+
   const CodeGen::CGBlockInfo *BlockInfo;
   llvm::Value *BlockPointer;
 
@@ -1048,6 +1057,9 @@ public:
   void disableDebugInfo() { DisableDebugInfo = true; }
   void enableDebugInfo() { DisableDebugInfo = false; }
 
+  bool shouldUseFusedARCCalls() {
+    return CGM.getCodeGenOpts().OptimizationLevel == 0;
+  }
 
   const LangOptions &getLangOptions() const { return CGM.getLangOptions(); }
 
@@ -1345,7 +1357,8 @@ public:
   /// CreateAggTemp - Create a temporary memory object for the given
   /// aggregate type.
   AggValueSlot CreateAggTemp(QualType T, const llvm::Twine &Name = "tmp") {
-    return AggValueSlot::forAddr(CreateMemTemp(T, Name), false, false);
+    return AggValueSlot::forAddr(CreateMemTemp(T, Name), T.getQualifiers(),
+                                 false);
   }
 
   /// Emit a cast to void* in the appropriate address space.
@@ -1379,12 +1392,11 @@ public:
   /// EmitAnyExprToMem - Emits the code necessary to evaluate an
   /// arbitrary expression into the given memory location.
   void EmitAnyExprToMem(const Expr *E, llvm::Value *Location,
-                        bool IsLocationVolatile,
-                        bool IsInitializer);
+                        Qualifiers Quals, bool IsInitializer);
 
   /// EmitExprAsInit - Emits the code necessary to initialize a
   /// location in memory with the given initializer.
-  void EmitExprAsInit(const Expr *init, const VarDecl *var,
+  void EmitExprAsInit(const Expr *init, const ValueDecl *D,
                       llvm::Value *loc, CharUnits alignment,
                       bool capturedByInit);
 
@@ -1584,6 +1596,10 @@ public:
   /// This function can be called with a null (unreachable) insert point.
   void EmitVarDecl(const VarDecl &D);
 
+  void EmitScalarInit(const Expr *init, const ValueDecl *D,
+                      llvm::Value *addr, bool capturedByInit,
+                      bool isVolatile, unsigned alignment, QualType type);
+
   typedef void SpecialInitFn(CodeGenFunction &Init, const VarDecl &D,
                              llvm::Value *Address);
 
@@ -1709,6 +1725,7 @@ public:
   void EmitObjCAtTryStmt(const ObjCAtTryStmt &S);
   void EmitObjCAtThrowStmt(const ObjCAtThrowStmt &S);
   void EmitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt &S);
+  void EmitObjCAutoreleasePoolStmt(const ObjCAutoreleasePoolStmt &S);
 
   llvm::Constant *getUnwindResumeFn();
   llvm::Constant *getUnwindResumeOrRethrowFn();
@@ -1961,6 +1978,64 @@ public:
   RValue EmitObjCMessageExpr(const ObjCMessageExpr *E,
                              ReturnValueSlot Return = ReturnValueSlot());
 
+  /// Retrieves the default cleanup kind for an ARC cleanup.
+  /// Except under -fobjc-arc-eh, ARC cleanups are normal-only.
+  CleanupKind getARCCleanupKind() {
+    return CGM.getCodeGenOpts().ObjCAutoRefCountExceptions
+             ? NormalAndEHCleanup : NormalCleanup;
+  }
+
+  // ARC primitives.
+  void EmitARCInitWeak(llvm::Value *value, llvm::Value *addr);
+  void EmitARCDestroyWeak(llvm::Value *addr);
+  llvm::Value *EmitARCLoadWeak(llvm::Value *addr);
+  llvm::Value *EmitARCLoadWeakRetained(llvm::Value *addr);
+  llvm::Value *EmitARCStoreWeak(llvm::Value *value, llvm::Value *addr,
+                                bool ignored);
+  void EmitARCCopyWeak(llvm::Value *dst, llvm::Value *src);
+  void EmitARCMoveWeak(llvm::Value *dst, llvm::Value *src);
+  llvm::Value *EmitARCRetainAutorelease(QualType type, llvm::Value *value);
+  llvm::Value *EmitARCRetainAutoreleaseNonBlock(llvm::Value *value);
+  llvm::Value *EmitARCStoreStrong(LValue addr, QualType type,
+                                  llvm::Value *value, bool ignored);
+  llvm::Value *EmitARCStoreStrongCall(llvm::Value *addr, llvm::Value *value,
+                                      bool ignored);
+  llvm::Value *EmitARCRetain(QualType type, llvm::Value *value);
+  llvm::Value *EmitARCRetainNonBlock(llvm::Value *value);
+  llvm::Value *EmitARCRetainBlock(llvm::Value *value);
+  void EmitARCRelease(llvm::Value *value, bool precise);
+  llvm::Value *EmitARCAutorelease(llvm::Value *value);
+  llvm::Value *EmitARCAutoreleaseReturnValue(llvm::Value *value);
+  llvm::Value *EmitARCRetainAutoreleaseReturnValue(llvm::Value *value);
+  llvm::Value *EmitARCRetainAutoreleasedReturnValue(llvm::Value *value);
+
+  std::pair<LValue,llvm::Value*>
+  EmitARCStoreAutoreleasing(const BinaryOperator *e);
+  std::pair<LValue,llvm::Value*>
+  EmitARCStoreStrong(const BinaryOperator *e, bool ignored);
+
+  llvm::Value *EmitObjCProduceObject(QualType T, llvm::Value *Ptr);
+  llvm::Value *EmitObjCConsumeObject(QualType T, llvm::Value *Ptr);
+  llvm::Value *EmitObjCExtendObjectLifetime(QualType T, llvm::Value *Ptr);
+
+  llvm::Value *EmitARCRetainScalarExpr(const Expr *expr);
+  llvm::Value *EmitARCRetainAutoreleaseScalarExpr(const Expr *expr);
+
+  void PushARCReleaseCleanup(CleanupKind kind, QualType type,
+                             llvm::Value *addr, bool precise);
+  void PushARCWeakReleaseCleanup(CleanupKind kind, QualType type,
+                                 llvm::Value *addr);
+  void PushARCFieldReleaseCleanup(CleanupKind cleanupKind,
+                                  const FieldDecl *Field);
+  void PushARCFieldWeakReleaseCleanup(CleanupKind cleanupKind,
+                                      const FieldDecl *Field);
+
+  void EmitObjCAutoreleasePoolPop(llvm::Value *Ptr); 
+  llvm::Value *EmitObjCAutoreleasePoolPush();
+  llvm::Value *EmitObjCMRRAutoreleasePoolPush();
+  void EmitObjCAutoreleasePoolCleanup(llvm::Value *Ptr);
+  void EmitObjCMRRAutoreleasePoolPop(llvm::Value *Ptr); 
+
   /// EmitReferenceBindingToExpr - Emits a reference binding to the passed in
   /// expression. Will emit a temporary variable if E is not an LValue.
   RValue EmitReferenceBindingToExpr(const Expr* E,

+ 17 - 4
lib/CodeGen/CodeGenModule.cpp

@@ -64,7 +64,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
     ABI(createCXXABI(*this)), 
     Types(C, M, TD, getTargetCodeGenInfo().getABIInfo(), ABI),
     TBAA(0),
-    VTables(*this), Runtime(0), DebugInfo(0),
+    VTables(*this), Runtime(0), DebugInfo(0), ARCData(0), RRData(0),
     CFConstantStringClassRef(0), ConstantStringClassRef(0),
     VMContext(M.getContext()),
     NSConcreteGlobalBlockDecl(0), NSConcreteStackBlockDecl(0),
@@ -88,6 +88,10 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
 
   Block.GlobalUniqueCount = 0;
 
+  if (C.getLangOptions().ObjCAutoRefCount)
+    ARCData = new ARCEntrypoints();
+  RRData = new RREntrypoints();
+
   // Initialize the type cache.
   llvm::LLVMContext &LLVMContext = M.getContext();
   VoidTy = llvm::Type::getVoidTy(LLVMContext);
@@ -108,6 +112,8 @@ CodeGenModule::~CodeGenModule() {
   delete &ABI;
   delete TBAA;
   delete DebugInfo;
+  delete ARCData;
+  delete RRData;
 }
 
 void CodeGenModule::createObjCRuntime() {
@@ -830,7 +836,8 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD) {
 llvm::Constant *
 CodeGenModule::GetOrCreateLLVMFunction(llvm::StringRef MangledName,
                                        const llvm::Type *Ty,
-                                       GlobalDecl D, bool ForVTable) {
+                                       GlobalDecl D, bool ForVTable,
+                                       llvm::Attributes ExtraAttrs) {
   // Lookup the entry, lazily creating it if necessary.
   llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
   if (Entry) {
@@ -869,6 +876,8 @@ CodeGenModule::GetOrCreateLLVMFunction(llvm::StringRef MangledName,
   assert(F->getName() == MangledName && "name was uniqued!");
   if (D.getDecl())
     SetFunctionAttributes(D, F, IsIncompleteFunction);
+  if (ExtraAttrs != llvm::Attribute::None)
+    F->addFnAttr(ExtraAttrs);
 
   // This is the first use or definition of a mangled name.  If there is a
   // deferred decl with this name, remember that we need to emit it at the end
@@ -937,8 +946,10 @@ llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD,
 /// type and name.
 llvm::Constant *
 CodeGenModule::CreateRuntimeFunction(const llvm::FunctionType *FTy,
-                                     llvm::StringRef Name) {
-  return GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false);
+                                     llvm::StringRef Name,
+                                     llvm::Attributes ExtraAttrs) {
+  return GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false,
+                                 ExtraAttrs);
 }
 
 static bool DeclIsConstantGlobal(ASTContext &Context, const VarDecl *D,
@@ -1997,6 +2008,7 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
                              false, true, false, ObjCMethodDecl::Required);
     D->addInstanceMethod(DTORMethod);
     CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, DTORMethod, false);
+    D->setHasCXXStructors(true);
   }
 
   // If the implementation doesn't have any ivar initializers, we don't need
@@ -2015,6 +2027,7 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) {
                                                 ObjCMethodDecl::Required);
   D->addInstanceMethod(CTORMethod);
   CodeGenFunction(*this).GenerateObjCCtorDtorMethod(D, CTORMethod, true);
+  D->setHasCXXStructors(true);
 }
 
 /// EmitNamespace - Emit all declarations in a namespace.

+ 84 - 3
lib/CodeGen/CodeGenModule.h

@@ -131,6 +131,71 @@ namespace CodeGen {
     /// The alignment of a pointer into the generic address space.
     unsigned char PointerAlignInBytes;
   };
+
+struct RREntrypoints {
+  RREntrypoints() { memset(this, 0, sizeof(*this)); }
+  /// void objc_autoreleasePoolPop(void*);
+  llvm::Constant *objc_autoreleasePoolPop;
+
+  /// void *objc_autoreleasePoolPush(void);
+  llvm::Constant *objc_autoreleasePoolPush;
+};
+
+struct ARCEntrypoints {
+  ARCEntrypoints() { memset(this, 0, sizeof(*this)); }
+
+  /// id objc_autorelease(id);
+  llvm::Constant *objc_autorelease;
+
+  /// id objc_autoreleaseReturnValue(id);
+  llvm::Constant *objc_autoreleaseReturnValue;
+
+  /// void objc_copyWeak(id *dest, id *src);
+  llvm::Constant *objc_copyWeak;
+
+  /// void objc_destroyWeak(id*);
+  llvm::Constant *objc_destroyWeak;
+
+  /// id objc_initWeak(id*, id);
+  llvm::Constant *objc_initWeak;
+
+  /// id objc_loadWeak(id*);
+  llvm::Constant *objc_loadWeak;
+
+  /// id objc_loadWeakRetained(id*);
+  llvm::Constant *objc_loadWeakRetained;
+
+  /// void objc_moveWeak(id *dest, id *src);
+  llvm::Constant *objc_moveWeak;
+
+  /// id objc_retain(id);
+  llvm::Constant *objc_retain;
+
+  /// id objc_retainAutorelease(id);
+  llvm::Constant *objc_retainAutorelease;
+
+  /// id objc_retainAutoreleaseReturnValue(id);
+  llvm::Constant *objc_retainAutoreleaseReturnValue;
+
+  /// id objc_retainAutoreleasedReturnValue(id);
+  llvm::Constant *objc_retainAutoreleasedReturnValue;
+
+  /// id objc_retainBlock(id);
+  llvm::Constant *objc_retainBlock;
+
+  /// void objc_release(id);
+  llvm::Constant *objc_release;
+
+  /// id objc_storeStrong(id*, id);
+  llvm::Constant *objc_storeStrong;
+
+  /// id objc_storeWeak(id*, id);
+  llvm::Constant *objc_storeWeak;
+
+  /// A void(void) inline asm to use to mark that the return value of
+  /// a call will be immediately retain.
+  llvm::InlineAsm *retainAutoreleasedReturnValueMarker;
+};
   
 /// CodeGenModule - This class organizes the cross-function state that is used
 /// while generating LLVM code.
@@ -157,6 +222,8 @@ class CodeGenModule : public CodeGenTypeCache {
 
   CGObjCRuntime* Runtime;
   CGDebugInfo* DebugInfo;
+  ARCEntrypoints *ARCData;
+  RREntrypoints *RRData;
 
   // WeakRefReferences - A set of references that have only been seen via
   // a weakref so far. This is used to remove the weak of the reference if we ever
@@ -275,6 +342,16 @@ public:
   /// getCXXABI() - Return a reference to the configured C++ ABI.
   CGCXXABI &getCXXABI() { return ABI; }
 
+  ARCEntrypoints &getARCEntrypoints() const {
+    assert(getLangOptions().ObjCAutoRefCount && ARCData != 0);
+    return *ARCData;
+  }
+
+  RREntrypoints &getRREntrypoints() const {
+    assert(RRData != 0);
+    return *RRData;
+  }
+
   llvm::Value *getStaticLocalDeclAddress(const VarDecl *VD) {
     return StaticLocalDeclMap[VD];
   }
@@ -474,7 +551,7 @@ public:
   /// created).
   llvm::Constant *GetAddrOfConstantCString(const std::string &str,
                                            const char *GlobalName=0);
-
+  
   /// GetAddrOfCXXConstructor - Return the address of the constructor of the
   /// given type.
   llvm::GlobalValue *GetAddrOfCXXConstructor(const CXXConstructorDecl *ctor,
@@ -514,7 +591,9 @@ public:
   /// CreateRuntimeFunction - Create a new runtime function with the specified
   /// type and name.
   llvm::Constant *CreateRuntimeFunction(const llvm::FunctionType *Ty,
-                                        llvm::StringRef Name);
+                                        llvm::StringRef Name,
+                                        llvm::Attributes ExtraAttrs =
+                                          llvm::Attribute::None);
   /// CreateRuntimeVariable - Create a new runtime global variable with the
   /// specified type and name.
   llvm::Constant *CreateRuntimeVariable(const llvm::Type *Ty,
@@ -642,7 +721,9 @@ private:
   llvm::Constant *GetOrCreateLLVMFunction(llvm::StringRef MangledName,
                                           const llvm::Type *Ty,
                                           GlobalDecl D,
-                                          bool ForVTable);
+                                          bool ForVTable,
+                                          llvm::Attributes ExtraAttrs =
+                                            llvm::Attribute::None);
   llvm::Constant *GetOrCreateLLVMGlobal(llvm::StringRef MangledName,
                                         const llvm::PointerType *PTy,
                                         const VarDecl *D,

+ 34 - 1
lib/CodeGen/ItaniumCXXABI.cpp

@@ -802,10 +802,27 @@ bool ItaniumCXXABI::NeedsArrayCookie(const CXXNewExpr *expr) {
   if (expr->doesUsualArrayDeleteWantSize())
     return true;
 
+  // Automatic Reference Counting:
+  //   We need an array cookie for pointers with strong or weak lifetime.
+  QualType AllocatedType = expr->getAllocatedType();
+  if (getContext().getLangOptions().ObjCAutoRefCount &&
+      AllocatedType->isObjCLifetimeType()) {
+    switch (AllocatedType.getObjCLifetime()) {
+    case Qualifiers::OCL_None:
+    case Qualifiers::OCL_ExplicitNone:
+    case Qualifiers::OCL_Autoreleasing:
+      return false;
+      
+    case Qualifiers::OCL_Strong:
+    case Qualifiers::OCL_Weak:
+      return true;
+    }
+  }
+
   // Otherwise, if the class has a non-trivial destructor, it always
   // needs a cookie.
   const CXXRecordDecl *record =
-    expr->getAllocatedType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
+    AllocatedType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
   return (record && !record->hasTrivialDestructor());
 }
 
@@ -816,6 +833,22 @@ bool ItaniumCXXABI::NeedsArrayCookie(const CXXDeleteExpr *expr,
   if (expr->doesUsualArrayDeleteWantSize())
     return true;
 
+  // Automatic Reference Counting:
+  //   We need an array cookie for pointers with strong or weak lifetime.
+  if (getContext().getLangOptions().ObjCAutoRefCount &&
+      elementType->isObjCLifetimeType()) {
+    switch (elementType.getObjCLifetime()) {
+    case Qualifiers::OCL_None:
+    case Qualifiers::OCL_ExplicitNone:
+    case Qualifiers::OCL_Autoreleasing:
+      return false;
+
+    case Qualifiers::OCL_Strong:
+    case Qualifiers::OCL_Weak:
+      return true;
+    }
+  }
+  
   // Otherwise, if the class has a non-trivial destructor, it always
   // needs a cookie.
   const CXXRecordDecl *record =

+ 4 - 2
lib/CodeGen/TargetInfo.cpp

@@ -2277,6 +2277,10 @@ public:
     return 13;
   }
 
+  llvm::StringRef getARCRetainAutoreleasedReturnValueMarker() const {
+    return "mov\tr7, r7\t\t@ marker for objc_retainAutoreleaseReturnValue";
+  }
+
   bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
                                llvm::Value *Address) const {
     CodeGen::CGBuilderTy &Builder = CGF.Builder;
@@ -2290,8 +2294,6 @@ public:
 
     return false;
   }
-
-
 };
 
 }

+ 14 - 0
lib/CodeGen/TargetInfo.h

@@ -111,6 +111,20 @@ namespace clang {
                                                   const llvm::Type* Ty) const {
       return Ty;
     }
+
+    /// Retrieve the address of a function to call immediately before
+    /// calling objc_retainAutoreleasedReturnValue.  The
+    /// implementation of objc_autoreleaseReturnValue sniffs the
+    /// instruction stream following its return address to decide
+    /// whether it's a call to objc_retainAutoreleasedReturnValue.
+    /// This can be prohibitively expensive, depending on the
+    /// relocation model, and so on some targets it instead sniffs for
+    /// a particular instruction sequence.  This functions returns
+    /// that instruction sequence in inline assembly, which will be
+    /// empty if none is required.
+    virtual llvm::StringRef getARCRetainAutoreleasedReturnValueMarker() const {
+      return "";
+    }
   };
 }
 

+ 8 - 1
lib/Driver/ToolChain.cpp

@@ -201,7 +201,8 @@ ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
 }
 
 void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args,
-                                             ArgStringList &CmdArgs) const {
+                                             ArgStringList &CmdArgs,
+                                             bool ObjCXXAutoRefCount) const {
   CXXStdlibType Type = GetCXXStdlibType(Args);
 
   switch (Type) {
@@ -209,10 +210,16 @@ void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &Args,
     CmdArgs.push_back("-nostdinc++");
     CmdArgs.push_back("-cxx-isystem");
     CmdArgs.push_back("/usr/include/c++/v1");
+      
+    if (ObjCXXAutoRefCount)
+      CmdArgs.push_back("-fobjc-arc-cxxlib=libc++");
     break;
 
   case ToolChain::CST_Libstdcxx:
     // Currently handled by the mass of goop in InitHeaderSearch.
+
+    if (ObjCXXAutoRefCount)
+      CmdArgs.push_back("-fobjc-arc-cxxlib=libstdc++");
     break;
   }
 }

+ 96 - 1
lib/Driver/ToolChains.cpp

@@ -26,6 +26,7 @@
 
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -41,7 +42,8 @@ using namespace clang::driver::toolchains;
 /// Darwin - Darwin tool chain for i386 and x86_64.
 
 Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple)
-  : ToolChain(Host, Triple), TargetInitialized(false)
+  : ToolChain(Host, Triple), TargetInitialized(false),
+    ARCRuntimeForSimulator(ARCSimulator_None)
 {
   // Compute the initial Darwin version based on the host.
   bool HadExtra;
@@ -70,6 +72,25 @@ bool Darwin::HasNativeLLVMSupport() const {
   return true;
 }
 
+/// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0.
+bool Darwin::HasARCRuntime() const {
+  // FIXME: Remove this once there is a proper way to detect an ARC runtime
+  // for the simulator.
+  switch (ARCRuntimeForSimulator) {
+  case ARCSimulator_None:
+    break;
+  case ARCSimulator_HasARCRuntime:
+    return true;
+  case ARCSimulator_NoARCRuntime:
+    return false;
+  }
+
+  if (isTargetIPhoneOS())
+    return !isIPhoneOSVersionLT(5);
+  else
+    return !isMacosxVersionLT(10, 7);
+}
+
 // FIXME: Can we tablegen this?
 static const char *GetArmArchForMArch(llvm::StringRef Value) {
   if (Value == "armv6k")
@@ -320,6 +341,30 @@ void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args,
     CmdArgs.push_back(Args.MakeArgString("-L" + P.str()));
 }
 
+void DarwinClang::AddLinkARCArgs(const ArgList &Args,
+                                 ArgStringList &CmdArgs) const {
+  
+  CmdArgs.push_back("-force_load");    
+  llvm::sys::Path P(getDriver().ClangExecutable);
+  P.eraseComponent(); // 'clang'
+  P.eraseComponent(); // 'bin'
+  P.appendComponent("lib");
+  P.appendComponent("arc");
+  P.appendComponent("libarclite_");
+  std::string s = P.str();
+  // Mash in the platform.
+  if (isTargetIPhoneOS())
+    s += "iphoneos";
+  // FIXME: isTargetIphoneOSSimulator() is not returning true.
+  else if (ARCRuntimeForSimulator != ARCSimulator_None)
+    s += "iphonesimulator";
+  else
+    s += "macosx";
+  s += ".a";
+
+  CmdArgs.push_back(Args.MakeArgString(s));
+}
+
 void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
                                         ArgStringList &CmdArgs) const {
   // Darwin doesn't support real static executables, don't link any runtime
@@ -389,6 +434,35 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args,
   }
 }
 
+static inline llvm::StringRef SimulatorVersionDefineName() {
+  return "__IPHONE_OS_VERSION_MIN_REQUIRED";
+}
+
+/// \brief Parse the simulator version define:
+/// __IPHONE_OS_VERSION_MIN_REQUIRED=([0-9])([0-9][0-9])([0-9][0-9])
+// and return the grouped values as integers, e.g:
+//   __IPHONE_OS_VERSION_MIN_REQUIRED=40201
+// will return Major=4, Minor=2, Micro=1.
+static bool GetVersionFromSimulatorDefine(llvm::StringRef define,
+                                          unsigned &Major, unsigned &Minor,
+                                          unsigned &Micro) {
+  assert(define.startswith(SimulatorVersionDefineName()));
+  llvm::StringRef name, version;
+  llvm::tie(name, version) = define.split('=');
+  if (version.empty())
+    return false;
+  std::string verstr = version.str();
+  char *end;
+  unsigned num = (unsigned) strtol(verstr.c_str(), &end, 10);
+  if (*end != '\0')
+    return false;
+  Major = num / 10000;
+  num = num % 10000;
+  Minor = num / 100;
+  Micro = num % 100;
+  return true;
+}
+
 void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
   const OptTable &Opts = getDriver().getOpts();
 
@@ -396,6 +470,27 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {
   Arg *iOSVersion = Args.getLastArg(options::OPT_miphoneos_version_min_EQ);
   Arg *iOSSimVersion = Args.getLastArg(
     options::OPT_mios_simulator_version_min_EQ);
+
+  // FIXME: HACK! When compiling for the simulator we don't get a
+  // '-miphoneos-version-min' to help us know whether there is an ARC runtime
+  // or not; try to parse a __IPHONE_OS_VERSION_MIN_REQUIRED
+  // define passed in command-line.
+  if (!iOSVersion) {
+    for (arg_iterator it = Args.filtered_begin(options::OPT_D),
+           ie = Args.filtered_end(); it != ie; ++it) {
+      llvm::StringRef define = (*it)->getValue(Args);
+      if (define.startswith(SimulatorVersionDefineName())) {
+        unsigned Major, Minor, Micro;
+        if (GetVersionFromSimulatorDefine(define, Major, Minor, Micro) &&
+            Major < 10 && Minor < 100 && Micro < 100) {
+          ARCRuntimeForSimulator = Major < 5 ? ARCSimulator_NoARCRuntime
+                                             : ARCSimulator_HasARCRuntime;
+        }
+        break;
+      }
+    }
+  }
+
   if (OSXVersion && (iOSVersion || iOSSimVersion)) {
     getDriver().Diag(clang::diag::err_drv_argument_not_allowed_with)
           << OSXVersion->getAsString(Args)

+ 18 - 0
lib/Driver/ToolChains.h

@@ -57,6 +57,16 @@ private:
   // the argument translation business.
   mutable bool TargetInitialized;
 
+  // FIXME: Remove this once there is a proper way to detect an ARC runtime
+  // for the simulator.
+ public:
+  mutable enum {
+    ARCSimulator_None,
+    ARCSimulator_HasARCRuntime,
+    ARCSimulator_NoARCRuntime
+  } ARCRuntimeForSimulator;
+
+private:
   /// Whether we are targeting iPhoneOS target.
   mutable bool TargetIsIPhoneOS;
 
@@ -157,6 +167,10 @@ public:
   virtual void AddLinkSearchPathArgs(const ArgList &Args,
                                      ArgStringList &CmdArgs) const = 0;
 
+  /// AddLinkARCArgs - Add the linker arguments to link the ARC runtime library.
+  virtual void AddLinkARCArgs(const ArgList &Args,
+                              ArgStringList &CmdArgs) const = 0;
+  
   /// AddLinkRuntimeLibArgs - Add the linker arguments to link the compiler
   /// runtime library.
   virtual void AddLinkRuntimeLibArgs(const ArgList &Args,
@@ -170,6 +184,8 @@ public:
 
   virtual bool HasNativeLLVMSupport() const;
 
+  virtual bool HasARCRuntime() const;
+
   virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args,
                                         const char *BoundArch) const;
 
@@ -257,6 +273,8 @@ public:
   virtual void AddCCKextLibArgs(const ArgList &Args,
                                 ArgStringList &CmdArgs) const;
 
+  virtual void AddLinkARCArgs(const ArgList &Args,
+                              ArgStringList &CmdArgs) const;
   /// }
 };
 

+ 41 - 3
lib/Driver/Tools.cpp

@@ -30,6 +30,7 @@
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Support/Process.h"
+#include "llvm/Support/ErrorHandling.h"
 
 #include "InputInfo.h"
 #include "ToolChains.h"
@@ -147,6 +148,12 @@ static void AddLinkerInputs(const ToolChain &TC,
   }
 }
 
+/// \brief Determine whether Objective-C automated reference counting is
+/// enabled.
+static bool isObjCAutoRefCount(const ArgList &Args) {
+  return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false);
+}
+
 static void addProfileRT(const ToolChain &TC, const ArgList &Args,
                          ArgStringList &CmdArgs) {
   if (Args.hasArg(options::OPT_fprofile_arcs) ||
@@ -318,8 +325,12 @@ void Clang::AddPreprocessingOptions(const Driver &D,
 
   // Add C++ include arguments, if needed.
   types::ID InputType = Inputs[0].getType();
-  if (types::isCXX(InputType))
-    getToolChain().AddClangCXXStdlibIncludeArgs(Args, CmdArgs);
+  if (types::isCXX(InputType)) {
+    bool ObjCXXAutoRefCount
+      = types::isObjC(InputType) && isObjCAutoRefCount(Args);
+    getToolChain().AddClangCXXStdlibIncludeArgs(Args, CmdArgs, 
+                                                ObjCXXAutoRefCount);
+  }
 
   // Add -Wp, and -Xassembler if using the preprocessor.
 
@@ -1542,6 +1553,24 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
                     options::OPT_fno_lax_vector_conversions))
     CmdArgs.push_back("-fno-lax-vector-conversions");
 
+  // Allow -fno-objc-arr to trump -fobjc-arr/-fobjc-arc.
+  // NOTE: This logic is duplicated in ToolChains.cpp.
+  bool ARC = isObjCAutoRefCount(Args);
+  if (ARC) {
+    CmdArgs.push_back("-fobjc-arc");
+
+    // Certain deployment targets don't have runtime support.
+    if (!getToolChain().HasARCRuntime())
+      CmdArgs.push_back("-fobjc-no-arc-runtime");
+
+    // Allow the user to enable full exceptions code emission.
+    // We define off for Objective-CC, on for Objective-C++.
+    if (Args.hasFlag(options::OPT_fobjc_arc_exceptions,
+                     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
   // rewriter.
   if (IsRewriter)
@@ -1553,7 +1582,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   if (!GCArg)
     GCArg = Args.getLastArg(options::OPT_fobjc_gc);
   if (GCArg) {
-    if (getToolChain().SupportsObjCGC()) {
+    if (ARC) {
+      D.Diag(clang::diag::err_drv_objc_gc_arr)
+        << GCArg->getAsString(Args);
+    } else if (getToolChain().SupportsObjCGC()) {
       GCArg->render(Args, CmdArgs);
     } else {
       // FIXME: We should move this to a hard error.
@@ -3141,6 +3173,12 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA,
 
   getDarwinToolChain().AddLinkSearchPathArgs(Args, CmdArgs);
 
+  // In ARC, if we don't have runtime support, link in the runtime
+  // stubs.  We have to do this *before* adding any of the normal
+  // linker inputs so that its initializer gets run first.
+  if (!getDarwinToolChain().HasARCRuntime() && isObjCAutoRefCount(Args))
+    getDarwinToolChain().AddLinkARCArgs(Args, CmdArgs);
+
   AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
 
   if (LinkingOutput) {

+ 37 - 8
lib/Frontend/CompilerInvocation.cpp

@@ -169,6 +169,8 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts,
     Res.push_back("-fno-use-cxa-atexit");
   if (Opts.CXXCtorDtorAliases)
     Res.push_back("-mconstructor-aliases");
+  if (Opts.ObjCAutoRefCountExceptions)
+    Res.push_back("-fobjc-arc-eh");
   if (!Opts.DebugPass.empty()) {
     Res.push_back("-mdebug-pass");
     Res.push_back(Opts.DebugPass);
@@ -670,6 +672,10 @@ static void LangOptsToArgs(const LangOptions &Opts,
       Res.push_back("-fobjc-gc-only");
     }
   }
+  if (Opts.ObjCAutoRefCount)
+    Res.push_back("-fobjc-arc");
+  if (Opts.ObjCNoAutoRefCountRuntime)
+    Res.push_back("-fobjc-no-arc-runtime");
   if (!Opts.ObjCInferRelatedResultType)
     Res.push_back("-fno-objc-infer-related-result-type");
   
@@ -951,6 +957,7 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
                      (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize);
 
   Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose);
+  Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions);
   Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit);
   Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases);
   Opts.CodeModel = Args.getLastArgValue(OPT_mcode_model);
@@ -1480,17 +1487,26 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
   if (Args.hasArg(OPT_fno_operator_names))
     Opts.CXXOperatorNames = 0;
 
+  if (Opts.ObjC1) {
+    if (Args.hasArg(OPT_fobjc_gc_only))
+      Opts.setGCMode(LangOptions::GCOnly);
+    else if (Args.hasArg(OPT_fobjc_gc))
+      Opts.setGCMode(LangOptions::HybridGC);
+    else if (Args.hasArg(OPT_fobjc_arc)) {
+      Opts.ObjCAutoRefCount = 1;
+      if (!Args.hasArg(OPT_fobjc_nonfragile_abi))
+        Diags.Report(diag::err_arc_nonfragile_abi);
+      if (Args.hasArg(OPT_fobjc_no_arc_runtime))
+        Opts.ObjCNoAutoRefCountRuntime = 1;
+    }
+
+    if (Args.hasArg(OPT_fno_objc_infer_related_result_type))
+      Opts.ObjCInferRelatedResultType = 0;
+  }
+    
   if (Args.hasArg(OPT_fgnu89_inline))
     Opts.GNUInline = 1;
 
-  if (Args.hasArg(OPT_fobjc_gc_only))
-    Opts.setGCMode(LangOptions::GCOnly);
-  else if (Args.hasArg(OPT_fobjc_gc))
-    Opts.setGCMode(LangOptions::HybridGC);
-  
-  if (Args.hasArg(OPT_fno_objc_infer_related_result_type))
-    Opts.ObjCInferRelatedResultType = 0;
-  
   if (Args.hasArg(OPT_fapple_kext)) {
     if (!Opts.CPlusPlus)
       Diags.Report(diag::warn_c_kext);
@@ -1715,6 +1731,19 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
 
     Opts.addRemappedFile(Split.first, Split.second);
   }
+  
+  if (Arg *A = Args.getLastArg(OPT_fobjc_arc_cxxlib_EQ)) {
+    llvm::StringRef Name = A->getValue(Args);
+    unsigned Library = llvm::StringSwitch<unsigned>(Name)
+      .Case("libc++", ARCXX_libcxx)
+      .Case("libstdc++", ARCXX_libstdcxx)
+      .Case("none", ARCXX_nolib)
+      .Default(~0U);
+    if (Library == ~0U)
+      Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
+    else
+      Opts.ObjCXXARCStandardLibrary = (ObjCXXARCStandardLibraryKind)Library;
+  }
 }
 
 static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,

+ 141 - 4
lib/Frontend/InitPreprocessor.cpp

@@ -221,6 +221,125 @@ static void DefineExactWidthIntType(TargetInfo::IntType Ty,
                         ConstSuffix);
 }
 
+/// \brief Add definitions required for a smooth interaction between
+/// Objective-C++ automatic reference counting and libc++.
+static void AddObjCXXARCLibcxxDefines(const LangOptions &LangOpts, 
+                                      MacroBuilder &Builder) {
+  Builder.defineMacro("_LIBCPP_PREDEFINED_OBJC_ARC_ADDRESSOF");
+  
+  std::string Result;
+  {
+    // Provide overloads of the function std::__1::addressof() that accept
+    // references to lifetime-qualified objects. libc++'s (more general)
+    // std::__1::addressof() template fails to instantiate with such types,
+    // because it attempts to convert the object to a char& before 
+    // dereferencing.
+    llvm::raw_string_ostream Out(Result);
+    
+    Out << "#pragma clang diagnostic push\n"
+        << "#pragma clang diagnostic ignored \"-Wc++0x-extensions\"\n"
+        << "namespace std { inline namespace __1 {\n"
+        << "\n";
+    
+    Out << "template <class _Tp>\n"
+        << "inline __attribute__ ((__visibility__(\"hidden\"), "
+        << "__always_inline__))\n"
+        << "__attribute__((objc_lifetime(strong))) _Tp*\n"
+        << "addressof(__attribute__((objc_lifetime(strong))) _Tp& __x) {\n"
+        << "  return &__x;\n"
+        << "}\n"
+        << "\n";
+      
+    if (!LangOpts.ObjCNoAutoRefCountRuntime) {
+      Out << "template <class _Tp>\n"
+          << "inline __attribute__ ((__visibility__(\"hidden\"),"
+          << "__always_inline__))\n"
+          << "__attribute__((objc_lifetime(weak))) _Tp*\n"
+          << "addressof(__attribute__((objc_lifetime(weak))) _Tp& __x) {\n"
+          << "  return &__x;\n"
+          << "};\n"
+          << "\n";
+    }
+      
+    Out << "template <class _Tp>\n"
+        << "inline __attribute__ ((__visibility__(\"hidden\"),"
+        << "__always_inline__))\n"
+        << "__attribute__((objc_lifetime(autoreleasing))) _Tp*\n"
+        << "addressof(__attribute__((objc_lifetime(autoreleasing))) _Tp& __x) "
+        << "{\n"
+        << " return &__x;\n"
+        << "}\n"
+        << "\n";
+    
+    Out << "template <class _Tp>\n"
+        << "inline __attribute__ ((__visibility__(\"hidden\"), "
+        << "__always_inline__))\n"
+        << "__unsafe_unretained _Tp* addressof(__unsafe_unretained _Tp& __x)"
+        << " {\n"
+        << "  return &__x;\n"
+        << "}\n";
+      
+    Out << "\n"
+        << "} }\n"
+        << "#pragma clang diagnostic pop\n"
+        << "\n";    
+  }
+  Builder.append(Result);
+}
+
+/// \brief Add definitions required for a smooth interaction between
+/// Objective-C++ automated reference counting and libstdc++ (4.2).
+static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts, 
+                                         MacroBuilder &Builder) {
+  Builder.defineMacro("_GLIBCXX_PREDEFINED_OBJC_ARC_IS_SCALAR");
+  
+  std::string Result;
+  {
+    // Provide specializations for the __is_scalar type trait so that 
+    // lifetime-qualified objects are not considered "scalar" types, which
+    // libstdc++ uses as an indicator of the presence of trivial copy, assign,
+    // default-construct, and destruct semantics (none of which hold for
+    // lifetime-qualified objects in ARC).
+    llvm::raw_string_ostream Out(Result);
+    
+    Out << "namespace std {\n"
+        << "\n"
+        << "struct __true_type;\n"
+        << "struct __false_type;\n"
+        << "\n";
+    
+    Out << "template<typename _Tp> struct __is_scalar;\n"
+        << "\n";
+      
+    Out << "template<typename _Tp>\n"
+        << "struct __is_scalar<__attribute__((objc_lifetime(strong))) _Tp> {\n"
+        << "  enum { __value = 0 };\n"
+        << "  typedef __false_type __type;\n"
+        << "};\n"
+        << "\n";
+      
+    if (!LangOpts.ObjCNoAutoRefCountRuntime) {
+      Out << "template<typename _Tp>\n"
+          << "struct __is_scalar<__attribute__((objc_lifetime(weak))) _Tp> {\n"
+          << "  enum { __value = 0 };\n"
+          << "  typedef __false_type __type;\n"
+          << "};\n"
+          << "\n";
+    }
+    
+    Out << "template<typename _Tp>\n"
+        << "struct __is_scalar<__attribute__((objc_lifetime(autoreleasing)))"
+        << " _Tp> {\n"
+        << "  enum { __value = 0 };\n"
+        << "  typedef __false_type __type;\n"
+        << "};\n"
+        << "\n";
+      
+    Out << "}\n";
+  }
+  Builder.append(Result);
+}
+
 static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
                                                const LangOptions &LangOpts,
                                                const FrontendOptions &FEOpts,
@@ -560,6 +679,7 @@ void clang::InitializePreprocessor(Preprocessor &PP,
                                    const PreprocessorOptions &InitOpts,
                                    const HeaderSearchOptions &HSOpts,
                                    const FrontendOptions &FEOpts) {
+  const LangOptions &LangOpts = PP.getLangOptions();
   std::string PredefineBuffer;
   PredefineBuffer.reserve(4080);
   llvm::raw_string_ostream Predefines(PredefineBuffer);
@@ -575,10 +695,27 @@ void clang::InitializePreprocessor(Preprocessor &PP,
     Builder.append("# 1 \"<built-in>\" 3");
 
   // Install things like __POWERPC__, __GNUC__, etc into the macro table.
-  if (InitOpts.UsePredefines)
-    InitializePredefinedMacros(PP.getTargetInfo(), PP.getLangOptions(),
-                               FEOpts, Builder);
-
+  if (InitOpts.UsePredefines) {
+    InitializePredefinedMacros(PP.getTargetInfo(), LangOpts, FEOpts, Builder);
+
+    // Install definitions to make Objective-C++ ARC work well with various
+    // C++ Standard Library implementations.
+    if (LangOpts.ObjC1 && LangOpts.CPlusPlus && LangOpts.ObjCAutoRefCount) {
+      switch (InitOpts.ObjCXXARCStandardLibrary) {
+      case ARCXX_nolib:
+        break;
+
+      case ARCXX_libcxx:
+        AddObjCXXARCLibcxxDefines(LangOpts, Builder);
+        break;
+
+      case ARCXX_libstdcxx:
+        AddObjCXXARCLibstdcxxDefines(LangOpts, Builder);
+        break;
+      }
+    }
+  }
+  
   // Even with predefines off, some macros are still predefined.
   // These should all be defined in the preprocessor according to the
   // current language configuration.

+ 5 - 0
lib/Lex/PPMacroExpansion.cpp

@@ -551,6 +551,11 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
            .Case("cxx_exceptions", LangOpts.Exceptions)
            .Case("cxx_rtti", LangOpts.RTTI)
            .Case("enumerator_attributes", true)
+           // Objective-C features
+           .Case("objc_arr", LangOpts.ObjCAutoRefCount) // FIXME: REMOVE?
+           .Case("objc_arc", LangOpts.ObjCAutoRefCount)
+           .Case("objc_arc_weak", LangOpts.ObjCAutoRefCount && 
+                 !LangOpts.ObjCNoAutoRefCountRuntime)
            .Case("objc_nonfragile_abi", LangOpts.ObjCNonFragileABI)
            .Case("objc_weak_class", LangOpts.ObjCNonFragileABI)
            .Case("ownership_holds", true)

+ 3 - 1
lib/Parse/ParseDecl.cpp

@@ -31,9 +31,11 @@ using namespace clang;
 ///
 /// Called type-id in C++.
 TypeResult Parser::ParseTypeName(SourceRange *Range,
-                                 Declarator::TheContext Context) {
+                                 Declarator::TheContext Context,
+                                 ObjCDeclSpec *objcQuals) {
   // Parse the common declaration-specifiers piece.
   DeclSpec DS(AttrFactory);
+  DS.setObjCQualifiers(objcQuals);
   ParseSpecifierQualifierList(DS);
 
   // Parse the abstract-declarator, if present.

+ 30 - 2
lib/Parse/ParseExpr.cpp

@@ -1740,7 +1740,12 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
 ///         '(' type-name ')' '{' initializer-list ',' '}'
 ///       cast-expression: [C99 6.5.4]
 ///         '(' type-name ')' cast-expression
-///
+/// [ARC]   bridged-cast-expression
+/// 
+/// [ARC] bridged-cast-expression:
+///         (__bridge type-name) cast-expression
+///         (__bridge_transfer type-name) cast-expression
+///         (__bridge_retained type-name) cast-expression
 ExprResult
 Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
                              ParsedType TypeOfCast, ParsedType &CastTy,
@@ -1772,7 +1777,30 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
     // If the substmt parsed correctly, build the AST node.
     if (!Stmt.isInvalid())
       Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.take(), Tok.getLocation());
-
+  } else if (ExprType >= CompoundLiteral && 
+             (Tok.is(tok::kw___bridge) || 
+              Tok.is(tok::kw___bridge_transfer) ||
+              Tok.is(tok::kw___bridge_retained))) {
+    // Parse an Objective-C ARC ownership cast expression.
+    ObjCBridgeCastKind Kind;
+    if (Tok.is(tok::kw___bridge))
+      Kind = OBC_Bridge;
+    else if (Tok.is(tok::kw___bridge_transfer))
+      Kind = OBC_BridgeTransfer;
+    else 
+      Kind = OBC_BridgeRetained;
+             
+    SourceLocation BridgeKeywordLoc = ConsumeToken();
+    TypeResult Ty = ParseTypeName();
+    SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, OpenLoc);
+    ExprResult SubExpr = ParseCastExpression(false, false, ParsedType());
+    
+    if (Ty.isInvalid() || SubExpr.isInvalid())
+      return ExprError();
+    
+    return Actions.ActOnObjCBridgedCast(getCurScope(), OpenLoc, Kind,
+                                        BridgeKeywordLoc, Ty.get(),
+                                        RParenLoc, SubExpr.get());
   } else if (ExprType >= CompoundLiteral &&
              isTypeIdInParens(isAmbiguousTypeId)) {
 

+ 40 - 2
lib/Parse/ParseObjc.cpp

@@ -480,6 +480,10 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl,
 ///     retain
 ///     copy
 ///     nonatomic
+///     atomic
+///     strong
+///     weak
+///     unsafe_unretained
 ///
 void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl) {
   assert(Tok.getKind() == tok::l_paren);
@@ -504,16 +508,22 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl) {
       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readonly);
     else if (II->isStr("assign"))
       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_assign);
+    else if (II->isStr("unsafe_unretained"))
+      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_unsafe_unretained);
     else if (II->isStr("readwrite"))
       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readwrite);
     else if (II->isStr("retain"))
       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_retain);
+    else if (II->isStr("strong"))
+      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_strong);
     else if (II->isStr("copy"))
       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_copy);
     else if (II->isStr("nonatomic"))
       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nonatomic);
     else if (II->isStr("atomic"))
       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_atomic);
+    else if (II->isStr("weak"))
+      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_weak);
     else if (II->isStr("getter") || II->isStr("setter")) {
       bool IsSetter = II->getNameStart()[0] == 's';
 
@@ -775,11 +785,12 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
 
   ParsedType Ty;
   if (isTypeSpecifierQualifier()) {
-    TypeResult TypeSpec = ParseTypeName(0, Declarator::ObjCPrototypeContext);
+    TypeResult TypeSpec =
+      ParseTypeName(0, Declarator::ObjCPrototypeContext, &DS);
     if (!TypeSpec.isInvalid())
       Ty = TypeSpec.get();
   }
-
+  
   if (Tok.is(tok::r_paren))
     ConsumeParen();
   else if (Tok.getLocation() == TypeStartLoc) {
@@ -853,6 +864,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
   }
 
   // Now parse the selector.
+  SourceLocation SelectorStartLoc = Tok.getLocation();
   SourceLocation selLoc;
   IdentifierInfo *SelIdent = ParseObjCSelectorPiece(selLoc);
 
@@ -1690,6 +1702,29 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
                                     FinallyStmt.take());
 }
 
+/// objc-autoreleasepool-statement:
+///   @autoreleasepool compound-statement
+///
+StmtResult
+Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) {
+  ConsumeToken(); // consume autoreleasepool
+  if (Tok.isNot(tok::l_brace)) {
+    Diag(Tok, diag::err_expected_lbrace);
+    return StmtError();
+  }
+  // Enter a scope to hold everything within the compound stmt.  Compound
+  // statements can always hold declarations.
+  ParseScope BodyScope(this, Scope::DeclScope);
+
+  StmtResult AutoreleasePoolBody(ParseCompoundStatementBody());
+
+  BodyScope.Exit();
+  if (AutoreleasePoolBody.isInvalid())
+    AutoreleasePoolBody = Actions.ActOnNullStmt(Tok.getLocation());
+  return Actions.ActOnObjCAutoreleasePoolStmt(atLoc, 
+                                                AutoreleasePoolBody.take());
+}
+
 ///   objc-method-def: objc-method-proto ';'[opt] '{' body '}'
 ///
 Decl *Parser::ParseObjCMethodDefinition() {
@@ -1765,6 +1800,9 @@ StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) {
   
   if (Tok.isObjCAtKeyword(tok::objc_synchronized))
     return ParseObjCSynchronizedStmt(AtLoc);
+
+  if (Tok.isObjCAtKeyword(tok::objc_autoreleasepool))
+    return ParseObjCAutoreleasePoolStmt(AtLoc);
   
   ExprResult Res(ParseExpressionWithLeadingAt(AtLoc));
   if (Res.isInvalid()) {

+ 1 - 2
lib/Rewrite/FixItRewriter.cpp

@@ -121,8 +121,7 @@ void FixItRewriter::HandleDiagnostic(Diagnostic::Level DiagLevel,
 
     if (Hint.CodeToInsert.empty()) {
       // We're removing code.
-      if (Rewrite.RemoveText(Hint.RemoveRange.getBegin(),
-                             Rewrite.getRangeSize(Hint.RemoveRange)))
+      if (Rewrite.RemoveText(Hint.RemoveRange))
         Failed = true;
       continue;
     }

+ 47 - 26
lib/Rewrite/Rewriter.cpp

@@ -231,10 +231,44 @@ RewriteBuffer &Rewriter::getEditBuffer(FileID FID) {
 /// InsertText - Insert the specified string at the specified location in the
 /// original buffer.
 bool Rewriter::InsertText(SourceLocation Loc, llvm::StringRef Str,
-                          bool InsertAfter) {
+                          bool InsertAfter, bool indentNewLines) {
+  using llvm::StringRef;
+
   if (!isRewritable(Loc)) return true;
   FileID FID;
   unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID);
+
+  llvm::SmallString<128> indentedStr;
+  if (indentNewLines && Str.find('\n') != StringRef::npos) {
+    StringRef MB = SourceMgr->getBufferData(FID);
+
+    unsigned lineNo = SourceMgr->getLineNumber(FID, StartOffs) - 1;
+    const SrcMgr::ContentCache *
+        Content = SourceMgr->getSLocEntry(FID).getFile().getContentCache();
+    unsigned lineOffs = Content->SourceLineCache[lineNo];
+
+    // Find the whitespace at the start of the line.
+    StringRef indentSpace;
+    {
+      unsigned i = lineOffs;
+      while (isWhitespace(MB[i]))
+        ++i;
+      indentSpace = MB.substr(lineOffs, i-lineOffs);
+    }
+
+    llvm::SmallVector<StringRef, 4> lines;
+    Str.split(lines, "\n");
+
+    for (unsigned i = 0, e = lines.size(); i != e; ++i) {
+      indentedStr += lines[i];
+      if (i < e-1) {
+        indentedStr += '\n';
+        indentedStr += indentSpace;
+      }
+    }
+    Str = indentedStr.str();
+  }
+
   getEditBuffer(FID).InsertText(StartOffs, Str, InsertAfter);
   return false;
 }
@@ -317,6 +351,7 @@ bool Rewriter::IncreaseIndentation(CharSourceRange range,
                                    SourceLocation parentIndent) {
   using llvm::StringRef;
 
+  if (range.isInvalid()) return true;
   if (!isRewritable(range.getBegin())) return true;
   if (!isRewritable(range.getEnd())) return true;
   if (!isRewritable(parentIndent)) return true;
@@ -330,7 +365,7 @@ bool Rewriter::IncreaseIndentation(CharSourceRange range,
 
   if (StartFileID != EndFileID || StartFileID != parentFileID)
     return true;
-  if (StartOff >= EndOff || parentOff >= StartOff)
+  if (StartOff > EndOff)
     return true;
 
   FileID FID = StartFileID;
@@ -343,16 +378,12 @@ bool Rewriter::IncreaseIndentation(CharSourceRange range,
   const SrcMgr::ContentCache *
       Content = SourceMgr->getSLocEntry(FID).getFile().getContentCache();
   
-  // Find where the line starts for the three offsets.
+  // Find where the lines start.
   unsigned parentLineOffs = Content->SourceLineCache[parentLineNo];
   unsigned startLineOffs = Content->SourceLineCache[startLineNo];
-  unsigned endLineOffs = Content->SourceLineCache[endLineNo];
-
-  if (startLineOffs == endLineOffs || startLineOffs == parentLineOffs)
-    return true;
 
   // Find the whitespace at the start of each line.
-  StringRef parentSpace, startSpace, endSpace;
+  StringRef parentSpace, startSpace;
   {
     unsigned i = parentLineOffs;
     while (isWhitespace(MB[i]))
@@ -363,11 +394,6 @@ bool Rewriter::IncreaseIndentation(CharSourceRange range,
     while (isWhitespace(MB[i]))
       ++i;
     startSpace = MB.substr(startLineOffs, i-startLineOffs);
-
-    i = endLineOffs;
-    while (isWhitespace(MB[i]))
-      ++i;
-    endSpace = MB.substr(endLineOffs, i-endLineOffs);
   }
   if (parentSpace.size() >= startSpace.size())
     return true;
@@ -378,19 +404,14 @@ bool Rewriter::IncreaseIndentation(CharSourceRange range,
 
   // Indent the lines between start/end offsets.
   RewriteBuffer &RB = getEditBuffer(FID);
-  for (unsigned i = startLineOffs; i != endLineOffs; ++i) {
-    if (MB[i] == '\n') {
-      unsigned startOfLine = i+1;
-      if (startOfLine == endLineOffs)
-        break;
-      StringRef origIndent;
-      unsigned ws = startOfLine;
-      while (isWhitespace(MB[ws]))
-        ++ws;
-      origIndent = MB.substr(startOfLine, ws-startOfLine);
-      if (origIndent.startswith(startSpace))
-        RB.InsertText(startOfLine, indent, /*InsertAfter=*/false);
-    }
+  for (unsigned lineNo = startLineNo; lineNo <= endLineNo; ++lineNo) {
+    unsigned offs = Content->SourceLineCache[lineNo];
+    unsigned i = offs;
+    while (isWhitespace(MB[i]))
+      ++i;
+    StringRef origIndent = MB.substr(offs, i-offs);
+    if (origIndent.startswith(startSpace))
+      RB.InsertText(offs, indent, /*InsertAfter=*/false);
   }
 
   return false;

+ 5 - 0
lib/Sema/AttributeList.cpp

@@ -177,6 +177,11 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
     .Case("cf_consumed", AT_cf_consumed)
     .Case("cf_returns_not_retained", AT_cf_returns_not_retained)
     .Case("cf_returns_retained", AT_cf_returns_retained)
+    .Case("cf_returns_autoreleased", AT_cf_returns_autoreleased)
+    .Case("ns_consumes_self", AT_ns_consumes_self)
+    .Case("ns_consumed", AT_ns_consumed)
+    .Case("objc_lifetime", AT_objc_lifetime)
+    .Case("objc_precise_lifetime", AT_objc_precise_lifetime)
     .Case("ownership_returns", AT_ownership_returns)
     .Case("ownership_holds", AT_ownership_holds)
     .Case("ownership_takes", AT_ownership_takes)

+ 3 - 0
lib/Sema/DelayedDiagnostic.cpp

@@ -47,5 +47,8 @@ void DelayedDiagnostic::Destroy() {
   case Deprecation: 
     delete [] DeprecationData.Message;
     break;
+
+  case ForbiddenType:
+    break;
   }
 }

+ 88 - 56
lib/Sema/JumpDiagnostics.cpp

@@ -111,90 +111,110 @@ unsigned JumpScopeChecker::GetDeepestCommonScope(unsigned A, unsigned B) {
   return A;
 }
 
+typedef std::pair<unsigned,unsigned> ScopePair;
+
 /// GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a
 /// diagnostic that should be emitted if control goes over it. If not, return 0.
-static std::pair<unsigned,unsigned>
-    GetDiagForGotoScopeDecl(const Decl *D, bool isCPlusPlus) {
+static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) {
   if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
     unsigned InDiag = 0, OutDiag = 0;
     if (VD->getType()->isVariablyModifiedType())
       InDiag = diag::note_protected_by_vla;
 
-    if (VD->hasAttr<BlocksAttr>()) {
-      InDiag = diag::note_protected_by___block;
-      OutDiag = diag::note_exits___block;
-    } else if (VD->hasAttr<CleanupAttr>()) {
-      InDiag = diag::note_protected_by_cleanup;
-      OutDiag = diag::note_exits_cleanup;
-    } else if (isCPlusPlus) {
-      if (!VD->hasLocalStorage())
-        return std::make_pair(InDiag, OutDiag);
-      
-      ASTContext &Context = D->getASTContext();
-      QualType T = Context.getBaseElementType(VD->getType());
-      if (!T->isDependentType()) {
-        // C++0x [stmt.dcl]p3:
-        //   A program that jumps from a point where a variable with automatic
-        //   storage duration is not in scope to a point where it is in scope
-        //   is ill-formed unless the variable has scalar type, class type with
-        //   a trivial default constructor and a trivial destructor, a 
-        //   cv-qualified version of one of these types, or an array of one of
-        //   the preceding types and is declared without an initializer (8.5).
-        // Check whether this is a C++ class.
-        CXXRecordDecl *Record = T->getAsCXXRecordDecl();
-        
-        if (const Expr *Init = VD->getInit()) {
-          bool CallsTrivialConstructor = false;
-          if (Record) {
-            // FIXME: With generalized initializer lists, this may
-            // classify "X x{};" as having no initializer.
-            if (const CXXConstructExpr *Construct 
-                                        = dyn_cast<CXXConstructExpr>(Init))
-              if (const CXXConstructorDecl *Constructor
-                                                = Construct->getConstructor())
-                if ((Context.getLangOptions().CPlusPlus0x
-                       ? Record->hasTrivialDefaultConstructor()
-                       : Record->isPOD()) &&
-                    Constructor->isDefaultConstructor())
-                  CallsTrivialConstructor = true;
-            
-            if (CallsTrivialConstructor && !Record->hasTrivialDestructor())
-              InDiag = diag::note_protected_by_variable_nontriv_destructor;
+    if (VD->hasAttr<BlocksAttr>())
+      return ScopePair(diag::note_protected_by___block,
+                       diag::note_exits___block);
+
+    if (VD->hasAttr<CleanupAttr>())
+      return ScopePair(diag::note_protected_by_cleanup,
+                       diag::note_exits_cleanup);
+
+    if (Context.getLangOptions().ObjCAutoRefCount && VD->hasLocalStorage()) {
+      switch (VD->getType().getObjCLifetime()) {
+      case Qualifiers::OCL_None:
+      case Qualifiers::OCL_ExplicitNone:
+      case Qualifiers::OCL_Autoreleasing:
+        break;
+
+      case Qualifiers::OCL_Strong:
+      case Qualifiers::OCL_Weak:
+        return ScopePair(diag::note_protected_by_objc_lifetime,
+                         diag::note_exits_objc_lifetime);
+      }
+    }
+
+    if (Context.getLangOptions().CPlusPlus && VD->hasLocalStorage()) {
+      // C++0x [stmt.dcl]p3:
+      //   A program that jumps from a point where a variable with automatic
+      //   storage duration is not in scope to a point where it is in scope
+      //   is ill-formed unless the variable has scalar type, class type with
+      //   a trivial default constructor and a trivial destructor, a 
+      //   cv-qualified version of one of these types, or an array of one of
+      //   the preceding types and is declared without an initializer.
+
+      // C++03 [stmt.dcl.p3:
+      //   A program that jumps from a point where a local variable
+      //   with automatic storage duration is not in scope to a point
+      //   where it is in scope is ill-formed unless the variable has
+      //   POD type and is declared without an initializer.
+
+      if (const Expr *init = VD->getInit()) {
+        // We actually give variables of record type (or array thereof)
+        // an initializer even if that initializer only calls a trivial
+        // ctor.  Detect that case.
+        // FIXME: With generalized initializer lists, this may
+        // classify "X x{};" as having no initializer.
+        unsigned inDiagToUse = diag::note_protected_by_variable_init;
+
+        const CXXRecordDecl *record = 0;
+
+        if (const CXXConstructExpr *cce = dyn_cast<CXXConstructExpr>(init)) {
+          const CXXConstructorDecl *ctor = cce->getConstructor();
+          record = ctor->getParent();
+
+          if (ctor->isTrivial() && ctor->isDefaultConstructor()) {
+            if (Context.getLangOptions().CPlusPlus0x) {
+              inDiagToUse = (record->hasTrivialDestructor() ? 0 :
+                        diag::note_protected_by_variable_nontriv_destructor);
+            } else {
+              if (record->isPOD())
+                inDiagToUse = 0;
+            }
           }
-          
-          if (!CallsTrivialConstructor)
-            InDiag = diag::note_protected_by_variable_init;
+        } else if (VD->getType()->isArrayType()) {
+          record = VD->getType()->getBaseElementTypeUnsafe()
+                                ->getAsCXXRecordDecl();
         }
-        
-        // Note whether we have a class with a non-trivial destructor.
-        if (Record && !Record->hasTrivialDestructor())
+
+        if (inDiagToUse)
+          InDiag = inDiagToUse;
+
+        // Also object to indirect jumps which leave scopes with dtors.
+        if (record && !record->hasTrivialDestructor())
           OutDiag = diag::note_exits_dtor;
       }
     }
     
-    return std::make_pair(InDiag, OutDiag);    
+    return ScopePair(InDiag, OutDiag);    
   }
 
   if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
     if (TD->getUnderlyingType()->isVariablyModifiedType())
-      return std::make_pair((unsigned) diag::note_protected_by_vla_typedef, 0);
+      return ScopePair(diag::note_protected_by_vla_typedef, 0);
   }
 
   if (const TypeAliasDecl *TD = dyn_cast<TypeAliasDecl>(D)) {
     if (TD->getUnderlyingType()->isVariablyModifiedType())
-      return std::make_pair((unsigned) diag::note_protected_by_vla_type_alias, 0);
+      return ScopePair(diag::note_protected_by_vla_type_alias, 0);
   }
 
-  return std::make_pair(0U, 0U);
+  return ScopePair(0U, 0U);
 }
 
 /// \brief Build scope information for a declaration that is part of a DeclStmt.
 void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) {
-  bool isCPlusPlus = this->S.getLangOptions().CPlusPlus;
-  
   // If this decl causes a new scope, push and switch to it.
-  std::pair<unsigned,unsigned> Diags
-    = GetDiagForGotoScopeDecl(D, isCPlusPlus);
+  std::pair<unsigned,unsigned> Diags = GetDiagForGotoScopeDecl(S.Context, D);
   if (Diags.first || Diags.second) {
     Scopes.push_back(GotoScope(ParentScope, Diags.first, Diags.second,
                                D->getLocation()));
@@ -369,6 +389,18 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) {
       continue;
     }
 
+    // Disallow jumps into the protected statement of an @autoreleasepool.
+    if (ObjCAutoreleasePoolStmt *AS = dyn_cast<ObjCAutoreleasePoolStmt>(SubStmt)){
+      // Recursively walk the AST for the @autoreleasepool part, protected by a new
+      // scope.
+      Scopes.push_back(GotoScope(ParentScope,
+                                 diag::note_protected_by_objc_autoreleasepool,
+                                 diag::note_exits_objc_autoreleasepool,
+                                 AS->getAtLoc()));
+      BuildScopeInformation(AS->getSubStmt(), Scopes.size()-1);
+      continue;
+    }
+
     // Recursively walk the AST.
     BuildScopeInformation(SubStmt, ParentScope);
   }

+ 35 - 5
lib/Sema/Sema.cpp

@@ -143,7 +143,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
     Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
     ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0), 
     PackContext(0), MSStructPragmaOn(false), VisContext(0),
-    LateTemplateParser(0), OpaqueParser(0),
+    ExprNeedsCleanups(0), LateTemplateParser(0), OpaqueParser(0),
     IdResolver(pp.getLangOptions()), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
     GlobalNewDeleteDeclared(false), 
     CompleteTranslationUnit(CompleteTranslationUnit),
@@ -162,7 +162,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
                                        &Context);
 
   ExprEvalContexts.push_back(
-                  ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0));  
+        ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0, false));
 
   FunctionScopes.push_back(new FunctionScopeInfo(Diags));
 }
@@ -202,6 +202,32 @@ Sema::~Sema() {
     ExternalSema->ForgetSema();
 }
 
+
+/// makeUnavailableInSystemHeader - There is an error in the current
+/// context.  If we're still in a system header, and we can plausibly
+/// make the relevant declaration unavailable instead of erroring, do
+/// so and return true.
+bool Sema::makeUnavailableInSystemHeader(SourceLocation loc,
+                                         llvm::StringRef msg) {
+  // If we're not in a function, it's an error.
+  FunctionDecl *fn = dyn_cast<FunctionDecl>(CurContext);
+  if (!fn) return false;
+
+  // If we're in template instantiation, it's an error.
+  if (!ActiveTemplateInstantiations.empty())
+    return false;
+  
+  // If that function's not in a system header, it's an error.
+  if (!Context.getSourceManager().isInSystemHeader(loc))
+    return false;
+
+  // If the function is already unavailable, it's not an error.
+  if (fn->hasAttr<UnavailableAttr>()) return true;
+
+  fn->addAttr(new (Context) UnavailableAttr(loc, Context, msg));
+  return true;
+}
+
 ASTMutationListener *Sema::getASTMutationListener() const {
   return getASTConsumer().GetASTMutationListener();
 }
@@ -211,13 +237,17 @@ ASTMutationListener *Sema::getASTMutationListener() const {
 /// The result is of the given category.
 ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
                                    CastKind Kind, ExprValueKind VK,
-                                   const CXXCastPath *BasePath) {
+                                   const CXXCastPath *BasePath,
+                                   CheckedConversionKind CCK) {
   QualType ExprTy = Context.getCanonicalType(E->getType());
   QualType TypeTy = Context.getCanonicalType(Ty);
 
   if (ExprTy == TypeTy)
     return Owned(E);
 
+  if (getLangOptions().ObjCAutoRefCount)
+    CheckObjCARCConversion(SourceRange(), Ty, E, CCK);
+
   // If this is a derived-to-base cast to a through a virtual base, we
   // need a vtable.
   if (Kind == CK_DerivedToBase && 
@@ -729,8 +759,8 @@ void Sema::PopFunctionOrBlockScope(const AnalysisBasedWarnings::Policy *WP,
 
 /// \brief Determine whether any errors occurred within this function/method/
 /// block.
-bool Sema::hasAnyErrorsInThisFunction() const {
-  return getCurFunction()->ErrorTrap.hasErrorOccurred();
+bool Sema::hasAnyUnrecoverableErrorsInThisFunction() const {
+  return getCurFunction()->ErrorTrap.hasUnrecoverableErrorOccurred();
 }
 
 BlockScopeInfo *Sema::getCurBlock() {

+ 104 - 33
lib/Sema/SemaCXXCast.cpp

@@ -63,7 +63,8 @@ static void CheckDynamicCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
                              CastKind &Kind,
                              CXXCastPath &BasePath);
 
-static bool CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType);
+static bool CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
+                               bool CheckCVR, bool CheckObjCLifetime);
 
 // The Try functions attempt a specific way of casting. If they succeed, they
 // return TC_Success. If their way of casting is not appropriate for the given
@@ -109,12 +110,14 @@ static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExp
                                                CXXCastPath &BasePath);
 
 static TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr,
-                                           QualType DestType, bool CStyle,
+                                           QualType DestType, 
+                                           Sema::CheckedConversionKind CCK,
                                            const SourceRange &OpRange,
                                            unsigned &msg,
                                            CastKind &Kind);
 static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
-                                   QualType DestType, bool CStyle,
+                                   QualType DestType, 
+                                   Sema::CheckedConversionKind CCK,
                                    const SourceRange &OpRange,
                                    unsigned &msg,
                                    CastKind &Kind,
@@ -248,8 +251,10 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
 
   InitializedEntity entity = InitializedEntity::InitializeTemporary(destType);
   InitializationKind initKind
-    = InitializationKind::CreateCast(/*type range?*/ range,
-                                     (CT == CT_CStyle || CT == CT_Functional));
+    = (CT == CT_CStyle)? InitializationKind::CreateCStyleCast(range.getBegin(),
+                                                              range)
+    : (CT == CT_Functional)? InitializationKind::CreateFunctionalCast(range)
+    : InitializationKind::CreateCast(/*type range?*/ range);
   InitializationSequence sequence(S, entity, initKind, &src, 1);
 
   assert(sequence.Failed() && "initialization succeeded on second try?");
@@ -373,8 +378,19 @@ static bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) {
 /// DestType casts away constness as defined in C++ 5.2.11p8ff. This is used by
 /// the cast checkers.  Both arguments must denote pointer (possibly to member)
 /// types.
+///
+/// \param CheckCVR Whether to check for const/volatile/restrict qualifiers.
+///
+/// \param CheckObjCLifetime Whether to check Objective-C lifetime qualifiers.
 static bool
-CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) {
+CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
+                   bool CheckCVR, bool CheckObjCLifetime) {
+  // 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.
+  if (!CheckCVR && CheckObjCLifetime && 
+      !Self.Context.getLangOptions().ObjCAutoRefCount)
+    return false;
+    
   // Casting away constness is defined in C++ 5.2.11p8 with reference to
   // C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since
   // the rules are non-trivial. So first we construct Tcv *...cv* as described
@@ -394,13 +410,23 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) {
   // purpose of this check, because other qualifiers (address spaces, 
   // Objective-C GC, etc.) are part of the type's identity.
   while (UnwrapDissimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) {
-    Qualifiers SrcQuals;
+    // Determine the relevant qualifiers at this level.
+    Qualifiers SrcQuals, DestQuals;
     Self.Context.getUnqualifiedArrayType(UnwrappedSrcType, SrcQuals);
-    cv1.push_back(Qualifiers::fromCVRMask(SrcQuals.getCVRQualifiers()));
-    
-    Qualifiers DestQuals;
     Self.Context.getUnqualifiedArrayType(UnwrappedDestType, DestQuals);
-    cv2.push_back(Qualifiers::fromCVRMask(DestQuals.getCVRQualifiers()));
+    
+    Qualifiers RetainedSrcQuals, RetainedDestQuals;
+    if (CheckCVR) {
+      RetainedSrcQuals.setCVRQualifiers(SrcQuals.getCVRQualifiers());
+      RetainedDestQuals.setCVRQualifiers(DestQuals.getCVRQualifiers());
+    }
+    
+    if (CheckObjCLifetime &&
+        !DestQuals.compatiblyIncludesObjCLifetime(SrcQuals))
+      return true;
+    
+    cv1.push_back(RetainedSrcQuals);
+    cv2.push_back(RetainedDestQuals);
   }
   if (cv1.empty())
     return false;
@@ -420,8 +446,10 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) {
   }
 
   // Test if they're compatible.
+  bool ObjCLifetimeConversion;
   return SrcConstruct != DestConstruct &&
-    !Self.IsQualificationConversion(SrcConstruct, DestConstruct, false);
+    !Self.IsQualificationConversion(SrcConstruct, DestConstruct, false,
+                                    ObjCLifetimeConversion);
 }
 
 /// CheckDynamicCast - Check that a dynamic_cast\<DestType\>(SrcExpr) is valid.
@@ -595,9 +623,10 @@ CheckReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
   }
 
   unsigned msg = diag::err_bad_cxx_cast_generic;
-  if (TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange,
-                         msg, Kind)
-      != TC_Success && msg != 0)
+  TryCastResult tcr = 
+    TryReinterpretCast(Self, SrcExpr, DestType, 
+                       /*CStyle*/false, OpRange, msg, Kind);
+  if (tcr != TC_Success && msg != 0)
   {
     if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
       return;
@@ -611,7 +640,10 @@ CheckReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
     } else {
       diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(), DestType);
     }
-  }    
+  } else if (tcr == TC_Success && Self.getLangOptions().ObjCAutoRefCount) {
+    Self.CheckObjCARCConversion(OpRange, DestType,
+                                SrcExpr.get(), Sema::CCK_OtherCast);
+  }
 }
 
 
@@ -654,8 +686,10 @@ CheckStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
   }
 
   unsigned msg = diag::err_bad_cxx_cast_generic;
-  if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg,
-                    Kind, BasePath) != TC_Success && msg != 0) {
+  TryCastResult tcr
+    = TryStaticCast(Self, SrcExpr, DestType, Sema::CCK_OtherCast, OpRange, msg,
+                    Kind, BasePath);
+  if (tcr != TC_Success && msg != 0) {
     if (SrcExpr.isInvalid())
       return;
     if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
@@ -667,6 +701,12 @@ CheckStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
     } else {
       diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType);
     }
+  } else if (tcr == TC_Success) {
+    if (Kind == CK_BitCast)
+      Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange);
+    if (Self.getLangOptions().ObjCAutoRefCount)
+      Self.CheckObjCARCConversion(OpRange, DestType,
+                                  SrcExpr.get(), Sema::CCK_OtherCast);
   }
   else if (Kind == CK_BitCast)
     Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange);
@@ -676,10 +716,15 @@ CheckStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
 /// possible. If @p CStyle, ignore access restrictions on hierarchy casting
 /// and casting away constness.
 static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
-                                   QualType DestType, bool CStyle,
+                                   QualType DestType, 
+                                   Sema::CheckedConversionKind CCK,
                                    const SourceRange &OpRange, unsigned &msg,
                                    CastKind &Kind,
                                    CXXCastPath &BasePath) {
+  // Determine whether we have the semantics of a C-style cast.
+  bool CStyle 
+    = (CCK == Sema::CCK_CStyleCast || CCK == Sema::CCK_FunctionalCast);
+  
   // The order the tests is not entirely arbitrary. There is one conversion
   // that can be handled in two different ways. Given:
   // struct A {};
@@ -715,7 +760,7 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
 
   // C++ 5.2.9p2: An expression e can be explicitly converted to a type T
   //   [...] if the declaration "T t(e);" is well-formed, [...].
-  tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CStyle, OpRange, msg,
+  tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CCK, OpRange, msg,
                               Kind);
   if (SrcExpr.isInvalid())
     return TC_Failed;
@@ -792,10 +837,20 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
         QualType DestPointee = DestPointer->getPointeeType();
         if (DestPointee->isIncompleteOrObjectType()) {
           // This is definitely the intended conversion, but it might fail due
-          // to a const violation.
-          if (!CStyle && !DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) {
-            msg = diag::err_bad_cxx_cast_qualifiers_away;
-            return TC_Failed;
+          // to a qualifier violation. Note that we permit Objective-C lifetime
+          // and GC qualifier mismatches here.
+          if (!CStyle) {
+            Qualifiers DestPointeeQuals = DestPointee.getQualifiers();
+            Qualifiers SrcPointeeQuals = SrcPointee.getQualifiers();
+            DestPointeeQuals.removeObjCGCAttr();
+            DestPointeeQuals.removeObjCLifetime();
+            SrcPointeeQuals.removeObjCGCAttr();
+            SrcPointeeQuals.removeObjCLifetime();
+            if (DestPointeeQuals != SrcPointeeQuals &&
+                !DestPointeeQuals.compatiblyIncludes(SrcPointeeQuals)) {
+              msg = diag::err_bad_cxx_cast_qualifiers_away;
+              return TC_Failed;
+            }
           }
           Kind = CK_BitCast;
           return TC_Success;
@@ -845,6 +900,7 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
   // FIXME: Should allow casting away constness if CStyle.
   bool DerivedToBase;
   bool ObjCConversion;
+  bool ObjCLifetimeConversion;
   QualType FromType = SrcExpr->getType();
   QualType ToType = R->getPointeeType();
   if (CStyle) {
@@ -854,8 +910,9 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
   
   if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(),
                                         ToType, FromType,
-                                        DerivedToBase, ObjCConversion) <
-        Sema::Ref_Compatible_With_Added_Qualification) {
+                                        DerivedToBase, ObjCConversion,
+                                        ObjCLifetimeConversion) 
+        < Sema::Ref_Compatible_With_Added_Qualification) {
     msg = diag::err_bad_lvalue_to_rvalue_cast;
     return TC_Failed;
   }
@@ -1172,7 +1229,8 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
 ///   @c static_cast if the declaration "T t(e);" is well-formed [...].
 TryCastResult
 TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
-                      bool CStyle, const SourceRange &OpRange, unsigned &msg,
+                      Sema::CheckedConversionKind CCK, 
+                      const SourceRange &OpRange, unsigned &msg,
                       CastKind &Kind) {
   if (DestType->isRecordType()) {
     if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
@@ -1184,7 +1242,11 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
   
   InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType);
   InitializationKind InitKind
-    = InitializationKind::CreateCast(/*FIXME:*/OpRange, CStyle);    
+    = (CCK == Sema::CCK_CStyleCast)
+        ? InitializationKind::CreateCStyleCast(OpRange.getBegin(), OpRange)
+    : (CCK == Sema::CCK_FunctionalCast)
+        ? InitializationKind::CreateFunctionalCast(OpRange)
+    : InitializationKind::CreateCast(OpRange);
   Expr *SrcExprRaw = SrcExpr.get();
   InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExprRaw, 1);
 
@@ -1193,7 +1255,8 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
   // There is no other way that works.
   // On the other hand, if we're checking a C-style cast, we've still got
   // the reinterpret_cast way.
-  
+  bool CStyle 
+    = (CCK == Sema::CCK_CStyleCast || CCK == Sema::CCK_FunctionalCast);
   if (InitSeq.Failed() && (CStyle || !DestType->isReferenceType()))
     return TC_NotApplicable;
     
@@ -1428,7 +1491,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
     //   constness.
     // A reinterpret_cast followed by a const_cast can, though, so in C-style,
     // we accept it.
-    if (!CStyle && CastsAwayConstness(Self, SrcType, DestType)) {
+    if (CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle,
+                           /*CheckObjCLifetime=*/CStyle)) {
       msg = diag::err_bad_cxx_cast_qualifiers_away;
       return TC_Failed;
     }
@@ -1543,7 +1607,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
 
   // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness.
   // The C-style cast operator can.
-  if (!CStyle && CastsAwayConstness(Self, SrcType, DestType)) {
+  if (CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle,
+                         /*CheckObjCLifetime=*/CStyle)) {
     msg = diag::err_bad_cxx_cast_qualifiers_away;
     return TC_Failed;
   }
@@ -1675,11 +1740,14 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
   if (tcr == TC_Success)
     Kind = CK_NoOp;
 
+  Sema::CheckedConversionKind CCK
+    = FunctionalStyle? Sema::CCK_FunctionalCast
+                     : Sema::CCK_CStyleCast;
   if (tcr == TC_NotApplicable) {
     // ... or if that is not possible, a static_cast, ignoring const, ...
     ExprResult CastExprRes = Owned(CastExpr);
-    tcr = TryStaticCast(*this, CastExprRes, CastTy, /*CStyle*/true, R, msg,
-                        Kind, BasePath);
+    tcr = TryStaticCast(*this, CastExprRes, CastTy, CCK, R, msg, Kind, 
+                        BasePath);
     if (CastExprRes.isInvalid())
       return ExprError();
     CastExpr = CastExprRes.take();
@@ -1694,6 +1762,9 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
     }
   }
 
+  if (getLangOptions().ObjCAutoRefCount && tcr == TC_Success)
+    CheckObjCARCConversion(R, CastTy, CastExpr, CCK);
+
   if (tcr != TC_Success && msg != 0) {
     if (CastExpr->getType() == Context.OverloadTy) {
       DeclAccessPair Found;

+ 268 - 14
lib/Sema/SemaChecking.cpp

@@ -22,6 +22,7 @@
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
+#include "clang/AST/EvaluatedExprVisitor.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/StmtObjC.h"
@@ -382,14 +383,14 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
   // casts here.
   // FIXME: We don't allow floating point scalars as input.
   Expr *FirstArg = TheCall->getArg(0);
-  if (!FirstArg->getType()->isPointerType()) {
+  const PointerType *pointerType = FirstArg->getType()->getAs<PointerType>();
+  if (!pointerType) {
     Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer)
       << FirstArg->getType() << FirstArg->getSourceRange();
     return ExprError();
   }
 
-  QualType ValType =
-    FirstArg->getType()->getAs<PointerType>()->getPointeeType();
+  QualType ValType = pointerType->getPointeeType();
   if (!ValType->isIntegerType() && !ValType->isAnyPointerType() &&
       !ValType->isBlockPointerType()) {
     Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer_intptr)
@@ -397,6 +398,20 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
     return ExprError();
   }
 
+  switch (ValType.getObjCLifetime()) {
+  case Qualifiers::OCL_None:
+  case Qualifiers::OCL_ExplicitNone:
+    // okay
+    break;
+
+  case Qualifiers::OCL_Weak:
+  case Qualifiers::OCL_Strong:
+  case Qualifiers::OCL_Autoreleasing:
+    Diag(DRE->getLocStart(), diag::err_arc_atomic_lifetime)
+      << ValType << FirstArg->getSourceRange();
+    return ExprError();
+  }
+
   // The majority of builtins return a value, but a few have special return
   // types, so allow them to override appropriately below.
   QualType ResultType = ValType;
@@ -518,7 +533,8 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
     CastKind Kind = CK_Invalid;
     ExprValueKind VK = VK_RValue;
     CXXCastPath BasePath;
-    Arg = CheckCastTypes(Arg.get()->getSourceRange(), ValType, Arg.take(), Kind, VK, BasePath);
+    Arg = CheckCastTypes(Arg.get()->getLocStart(), Arg.get()->getSourceRange(), 
+                         ValType, Arg.take(), Kind, VK, BasePath);
     if (Arg.isInvalid())
       return ExprError();
 
@@ -1849,6 +1865,7 @@ void Sema::CheckMemsetcpymoveArguments(const CallExpr *Call,
     QualType DestTy = Dest->getType();
     if (const PointerType *DestPtrTy = DestTy->getAs<PointerType>()) {
       QualType PointeeTy = DestPtrTy->getPointeeType();
+
       if (PointeeTy->isVoidType())
         continue;
 
@@ -1863,16 +1880,22 @@ void Sema::CheckMemsetcpymoveArguments(const CallExpr *Call,
         break;
       }
 
+      unsigned DiagID;
+
       // Always complain about dynamic classes.
-      if (isDynamicClassType(PointeeTy)) {
-        DiagRuntimeBehavior(
-          Dest->getExprLoc(), Dest,
-          PDiag(diag::warn_dyn_class_memaccess)
-            << ArgIdx << FnName << PointeeTy 
-            << Call->getCallee()->getSourceRange());
-      } else {
+      if (isDynamicClassType(PointeeTy))
+        DiagID = diag::warn_dyn_class_memaccess;
+      else if (PointeeTy.hasNonTrivialObjCLifetime() && 
+               !FnName->isStr("memset"))
+        DiagID = diag::warn_arc_object_memaccess;
+      else
         continue;
-      }
+
+      DiagRuntimeBehavior(
+        Dest->getExprLoc(), Dest,
+        PDiag(DiagID)
+          << ArgIdx << FnName << PointeeTy 
+          << Call->getCallee()->getSourceRange());
 
       DiagRuntimeBehavior(
         Dest->getExprLoc(), Dest,
@@ -1899,7 +1922,8 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
 
   // Perform checking for returned stack addresses, local blocks,
   // label addresses or references to temporaries.
-  if (lhsType->isPointerType() || lhsType->isBlockPointerType()) {
+  if (lhsType->isPointerType() ||
+      (!getLangOptions().ObjCAutoRefCount && lhsType->isBlockPointerType())) {
     stackE = EvalAddr(RetValExp, refVars);
   } else if (lhsType->isReferenceType()) {
     stackE = EvalVal(RetValExp, refVars);
@@ -2070,7 +2094,8 @@ static Expr *EvalAddr(Expr *E, llvm::SmallVectorImpl<DeclRefExpr *> &refVars) {
   // pointer values, and pointer-to-pointer conversions.
   case Stmt::ImplicitCastExprClass:
   case Stmt::CStyleCastExprClass:
-  case Stmt::CXXFunctionalCastExprClass: {
+  case Stmt::CXXFunctionalCastExprClass:
+  case Stmt::ObjCBridgedCastExprClass: {
     Expr* SubExpr = cast<CastExpr>(E)->getSubExpr();
     QualType T = SubExpr->getType();
 
@@ -3385,3 +3410,232 @@ void Sema::CheckArrayAccess(const Expr *expr) {
     }
   }
 }
+
+//===--- CHECK: Objective-C retain cycles ----------------------------------//
+
+namespace {
+  struct RetainCycleOwner {
+    RetainCycleOwner() : Variable(0), Indirect(false) {}
+    VarDecl *Variable;
+    SourceRange Range;
+    SourceLocation Loc;
+    bool Indirect;
+
+    void setLocsFrom(Expr *e) {
+      Loc = e->getExprLoc();
+      Range = e->getSourceRange();
+    }
+  };
+}
+
+/// Consider whether capturing the given variable can possibly lead to
+/// a retain cycle.
+static bool considerVariable(VarDecl *var, Expr *ref, RetainCycleOwner &owner) {
+  // In ARC, it's captured strongly iff the variable has __strong
+  // lifetime.  In MRR, it's captured strongly if the variable is
+  // __block and has an appropriate type.
+  if (var->getType().getObjCLifetime() != Qualifiers::OCL_Strong)
+    return false;
+
+  owner.Variable = var;
+  owner.setLocsFrom(ref);
+  return true;
+}
+
+static bool findRetainCycleOwner(Expr *e, RetainCycleOwner &owner) {
+  while (true) {
+    e = e->IgnoreParens();
+    if (CastExpr *cast = dyn_cast<CastExpr>(e)) {
+      switch (cast->getCastKind()) {
+      case CK_BitCast:
+      case CK_LValueBitCast:
+      case CK_LValueToRValue:
+        e = cast->getSubExpr();
+        continue;
+
+      case CK_GetObjCProperty: {
+        // Bail out if this isn't a strong explicit property.
+        const ObjCPropertyRefExpr *pre = cast->getSubExpr()->getObjCProperty();
+        if (pre->isImplicitProperty()) return false;
+        ObjCPropertyDecl *property = pre->getExplicitProperty();
+        if (!(property->getPropertyAttributes() &
+              (ObjCPropertyDecl::OBJC_PR_retain |
+               ObjCPropertyDecl::OBJC_PR_copy |
+               ObjCPropertyDecl::OBJC_PR_strong)) &&
+            !(property->getPropertyIvarDecl() &&
+              property->getPropertyIvarDecl()->getType()
+                .getObjCLifetime() == Qualifiers::OCL_Strong))
+          return false;
+
+        owner.Indirect = true;
+        e = const_cast<Expr*>(pre->getBase());
+        continue;
+      }
+        
+      default:
+        return false;
+      }
+    }
+
+    if (ObjCIvarRefExpr *ref = dyn_cast<ObjCIvarRefExpr>(e)) {
+      ObjCIvarDecl *ivar = ref->getDecl();
+      if (ivar->getType().getObjCLifetime() != Qualifiers::OCL_Strong)
+        return false;
+
+      // Try to find a retain cycle in the base.
+      if (!findRetainCycleOwner(ref->getBase(), owner))
+        return false;
+
+      if (ref->isFreeIvar()) owner.setLocsFrom(ref);
+      owner.Indirect = true;
+      return true;
+    }
+
+    if (DeclRefExpr *ref = dyn_cast<DeclRefExpr>(e)) {
+      VarDecl *var = dyn_cast<VarDecl>(ref->getDecl());
+      if (!var) return false;
+      return considerVariable(var, ref, owner);
+    }
+
+    if (BlockDeclRefExpr *ref = dyn_cast<BlockDeclRefExpr>(e)) {
+      owner.Variable = ref->getDecl();
+      owner.setLocsFrom(ref);
+      return true;
+    }
+
+    if (MemberExpr *member = dyn_cast<MemberExpr>(e)) {
+      if (member->isArrow()) return false;
+
+      // Don't count this as an indirect ownership.
+      e = member->getBase();
+      continue;
+    }
+
+    // Array ivars?
+
+    return false;
+  }
+}
+
+namespace {
+  struct FindCaptureVisitor : EvaluatedExprVisitor<FindCaptureVisitor> {
+    FindCaptureVisitor(ASTContext &Context, VarDecl *variable)
+      : EvaluatedExprVisitor<FindCaptureVisitor>(Context),
+        Variable(variable), Capturer(0) {}
+
+    VarDecl *Variable;
+    Expr *Capturer;
+
+    void VisitDeclRefExpr(DeclRefExpr *ref) {
+      if (ref->getDecl() == Variable && !Capturer)
+        Capturer = ref;
+    }
+
+    void VisitBlockDeclRefExpr(BlockDeclRefExpr *ref) {
+      if (ref->getDecl() == Variable && !Capturer)
+        Capturer = ref;
+    }
+
+    void VisitObjCIvarRefExpr(ObjCIvarRefExpr *ref) {
+      if (Capturer) return;
+      Visit(ref->getBase());
+      if (Capturer && ref->isFreeIvar())
+        Capturer = ref;
+    }
+
+    void VisitBlockExpr(BlockExpr *block) {
+      // Look inside nested blocks 
+      if (block->getBlockDecl()->capturesVariable(Variable))
+        Visit(block->getBlockDecl()->getBody());
+    }
+  };
+}
+
+/// Check whether the given argument is a block which captures a
+/// variable.
+static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) {
+  assert(owner.Variable && owner.Loc.isValid());
+
+  e = e->IgnoreParenCasts();
+  BlockExpr *block = dyn_cast<BlockExpr>(e);
+  if (!block || !block->getBlockDecl()->capturesVariable(owner.Variable))
+    return 0;
+
+  FindCaptureVisitor visitor(S.Context, owner.Variable);
+  visitor.Visit(block->getBlockDecl()->getBody());
+  return visitor.Capturer;
+}
+
+static void diagnoseRetainCycle(Sema &S, Expr *capturer,
+                                RetainCycleOwner &owner) {
+  assert(capturer);
+  assert(owner.Variable && owner.Loc.isValid());
+
+  S.Diag(capturer->getExprLoc(), diag::warn_arc_retain_cycle)
+    << owner.Variable << capturer->getSourceRange();
+  S.Diag(owner.Loc, diag::note_arc_retain_cycle_owner)
+    << owner.Indirect << owner.Range;
+}
+
+/// Check for a keyword selector that starts with the word 'add' or
+/// 'set'.
+static bool isSetterLikeSelector(Selector sel) {
+  if (sel.isUnarySelector()) return false;
+
+  llvm::StringRef str = sel.getNameForSlot(0);
+  while (!str.empty() && str.front() == '_') str = str.substr(1);
+  if (str.startswith("set") || str.startswith("add"))
+    str = str.substr(3);
+  else
+    return false;
+
+  if (str.empty()) return true;
+  return !islower(str.front());
+}
+
+/// Check a message send to see if it's likely to cause a retain cycle.
+void Sema::checkRetainCycles(ObjCMessageExpr *msg) {
+  // Only check instance methods whose selector looks like a setter.
+  if (!msg->isInstanceMessage() || !isSetterLikeSelector(msg->getSelector()))
+    return;
+
+  // Try to find a variable that the receiver is strongly owned by.
+  RetainCycleOwner owner;
+  if (msg->getReceiverKind() == ObjCMessageExpr::Instance) {
+    if (!findRetainCycleOwner(msg->getInstanceReceiver(), owner))
+      return;
+  } else {
+    assert(msg->getReceiverKind() == ObjCMessageExpr::SuperInstance);
+    owner.Variable = getCurMethodDecl()->getSelfDecl();
+    owner.Loc = msg->getSuperLoc();
+    owner.Range = msg->getSuperLoc();
+  }
+
+  // Check whether the receiver is captured by any of the arguments.
+  for (unsigned i = 0, e = msg->getNumArgs(); i != e; ++i)
+    if (Expr *capturer = findCapturingExpr(*this, msg->getArg(i), owner))
+      return diagnoseRetainCycle(*this, capturer, owner);
+}
+
+/// Check a property assign to see if it's likely to cause a retain cycle.
+void Sema::checkRetainCycles(Expr *receiver, Expr *argument) {
+  RetainCycleOwner owner;
+  if (!findRetainCycleOwner(receiver, owner))
+    return;
+
+  if (Expr *capturer = findCapturingExpr(*this, argument, owner))
+    diagnoseRetainCycle(*this, capturer, owner);
+}
+
+void Sema::checkUnsafeAssigns(SourceLocation Loc,
+                              QualType LHS, Expr *RHS) {
+  Qualifiers::ObjCLifetime LT = LHS.getObjCLifetime();
+  if (LT != Qualifiers::OCL_Weak && LT != Qualifiers::OCL_ExplicitNone)
+    return;
+  if (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS))
+    if (cast->getCastKind() == CK_ObjCConsumeObject)
+      Diag(Loc, diag::warn_arc_retained_assign)
+        << (LT == Qualifiers::OCL_ExplicitNone) 
+        << RHS->getSourceRange();
+}
+

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.