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/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index ad3fcfe..2d3fcf8 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -31,9 +31,11 @@
 ///
 /// 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.
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index d349220..01bd0ed 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1740,7 +1740,12 @@
 ///         '(' 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 @@
     // 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)) {
 
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index a8c18c0..4f28321 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -480,6 +480,10 @@
 ///     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 @@
       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 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 @@
   }
 
   // Now parse the selector.
+  SourceLocation SelectorStartLoc = Tok.getLocation();
   SourceLocation selLoc;
   IdentifierInfo *SelIdent = ParseObjCSelectorPiece(selLoc);
 
@@ -1690,6 +1702,29 @@
                                     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 @@
   
   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()) {