diff options
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 4 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 32 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 42 |
3 files changed, 73 insertions, 5 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index ad3fcfe0d3..2d3fcf8340 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/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. diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index d349220e3d..01bd0ed336 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/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)) { diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index a8c18c01a2..4f28321827 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/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()) { |