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
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 4c66ed8..fac2eac 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -221,9 +221,9 @@
   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 @@
     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 @@
   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 @@
   return CanQualType::CreateUnsafe(Result);
 }
 
-
 QualType ASTContext::getUnqualifiedArrayType(QualType type,
                                              Qualifiers &quals) {
   SplitQualType splitType = type.getSplitUnqualifiedType();
@@ -3725,11 +3730,7 @@
 }
 
 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 @@
 //                        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 @@
   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 @@
   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 @@
     // 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
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 08ac2a5..c10e6c4 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -228,6 +228,11 @@
     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 @@
     //   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 @@
 
         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(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()) {
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index e2c4f38..99eb0d3 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -474,8 +474,28 @@
   } 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"),
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 421770e..19554a3 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -933,6 +933,11 @@
     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;
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 9872139..97f4ea6 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1045,6 +1045,10 @@
     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 @@
 
   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 @@
          /*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 @@
                                  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 @@
   : 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 @@
   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;
 }
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index d177cb5..1a1fa91 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -162,6 +162,7 @@
   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 @@
   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());
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 06c5645..432ffee 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -282,6 +282,17 @@
       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 @@
   case CK_GetObjCProperty:
   case CK_LValueBitCast:
   case CK_UserDefinedConversion:
+  case CK_ObjCProduceObject:
+  case CK_ObjCConsumeObject:
     return false;
 
   case CK_LValueToRValue:
@@ -2301,6 +2314,8 @@
   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 @@
   case Expr::PackExpansionExprClass:
   case Expr::SubstNonTypeTemplateParmPackExprClass:
   case Expr::AsTypeExprClass:
+  case Expr::ObjCIndirectCopyRestoreExprClass:
     return ICEDiag(2, E->getLocStart());
 
   case Expr::SizeOfPackExprClass:
@@ -2995,7 +3011,8 @@
   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);
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index e81ec7e..a77fe5f 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/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 @@
     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 @@
   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 @@
     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:
diff --git a/lib/AST/ParentMap.cpp b/lib/AST/ParentMap.cpp
index eca351a..b7b2005 100644
--- a/lib/AST/ParentMap.cpp
+++ b/lib/AST/ParentMap.cpp
@@ -66,6 +66,15 @@
   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;
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 87588e4..d6a67b1 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -449,6 +449,12 @@
   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 @@
   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();
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index b117cd9..c70c87a 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -220,6 +220,10 @@
   VisitStmt(S);
 }
 
+void StmtProfiler::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {
+  VisitStmt(S);
+}
+
 void StmtProfiler::VisitExpr(Expr *S) {
   VisitStmt(S);
 }
@@ -952,6 +956,17 @@
   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);
 
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 938a686..080bca2 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -36,7 +36,10 @@
      (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 @@
   }
 }
 
-/// 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 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 @@
   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 @@
   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 @@
 // 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 @@
                  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 @@
     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 @@
                                 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 @@
   } 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 @@
     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 @@
 }
 
 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 @@
 
   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;
+}
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 4519606..ccb4560 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/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 @@
   // "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 @@
         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 @@
   
   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);
     }
-    std::swap(buffer, qualsBuffer);
+    
+    if (!qualsBuffer.empty()) {
+      if (!buffer.empty()) {
+        qualsBuffer += ' ';
+        qualsBuffer += buffer;
+      }
+      std::swap(buffer, qualsBuffer);
+    }
   }
   
   switch (T->getTypeClass()) {
@@ -159,13 +186,20 @@
   // 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);
     }
-    std::swap(buffer, qualsBuffer);
+
+    if (!qualsBuffer.empty()) {
+      if (!buffer.empty()) {
+        qualsBuffer += ' ';
+        qualsBuffer += buffer;
+      }
+      std::swap(buffer, qualsBuffer);
+    }
   }
 }
 
@@ -192,6 +226,7 @@
   if (isa<ArrayType>(T->getPointeeType()))
     S = '(' + S + ')';
   
+  IncludeStrongLifetimeRAII Strong(Policy);
   print(T->getPointeeType(), S);
 }
 
@@ -209,6 +244,7 @@
   if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
     S = '(' + S + ')';
   
+  IncludeStrongLifetimeRAII Strong(Policy);
   print(T->getPointeeTypeAsWritten(), S);
 }
 
@@ -221,6 +257,7 @@
   if (isa<ArrayType>(T->getPointeeTypeAsWritten()))
     S = '(' + S + ')';
   
+  IncludeStrongLifetimeRAII Strong(Policy);
   print(T->getPointeeTypeAsWritten(), S);
 }
 
@@ -236,6 +273,7 @@
   if (isa<ArrayType>(T->getPointeeType()))
     S = '(' + S + ')';
   
+  IncludeStrongLifetimeRAII Strong(Policy);
   print(T->getPointeeType(), S);
 }
 
@@ -245,12 +283,14 @@
   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 @@
   }
   S += ']';
   
+  IncludeStrongLifetimeRAII Strong(Policy);
   print(T->getElementType(), S);
 }
 
@@ -291,6 +332,7 @@
   }
   S += ']';
   
+  IncludeStrongLifetimeRAII Strong(Policy);
   print(T->getElementType(), S);
 }
 
@@ -518,6 +560,7 @@
   if (!S.empty())
     S = ' ' + S;
   std::string Str;
+  IncludeStrongLifetimeRAII Strong(Policy);
   print(T->getBaseType(), Str);
 
   switch (T->getUTTKind()) {
@@ -552,6 +595,7 @@
       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 @@
       Args = TemplateArgs.data();
       NumArgs = TemplateArgs.size();
     }
+    IncludeStrongLifetimeRAII Strong(Policy);
     Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
                                                                     NumArgs,
                                                                     Policy);
@@ -677,18 +722,21 @@
 
 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::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::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 @@
     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 @@
 // 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 @@
     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) {