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()) {