diff options
Diffstat (limited to 'lib/Parse/ParseObjc.cpp')
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 95 |
1 files changed, 54 insertions, 41 deletions
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index f32a322..fdbedc5 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -41,11 +41,11 @@ Decl *Parser::ParseObjCAtDirectives() { case tok::objc_class: return ParseObjCAtClassDeclaration(AtLoc); case tok::objc_interface: { - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); return ParseObjCAtInterfaceDeclaration(AtLoc, attrs); } case tok::objc_protocol: { - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); return ParseObjCAtProtocolDeclaration(AtLoc, attrs); } case tok::objc_implementation: @@ -327,7 +327,7 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, // If this is a method prototype, parse it. if (Tok.is(tok::minus) || Tok.is(tok::plus)) { Decl *methodPrototype = - ParseObjCMethodPrototype(interfaceDecl, MethodImplKind); + ParseObjCMethodPrototype(interfaceDecl, MethodImplKind, false); allMethods.push_back(methodPrototype); // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for // method definitions. @@ -340,7 +340,7 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, ParseObjCMethodDecl(Tok.getLocation(), tok::minus, interfaceDecl, - MethodImplKind); + MethodImplKind, false); continue; } // Ignore excess semicolons. @@ -371,7 +371,7 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, // FIXME: as the name implies, this rule allows function definitions. // We could pass a flag or check for functions during semantic analysis. - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(attrs)); continue; } @@ -439,11 +439,10 @@ void Parser::ParseObjCInterfaceDeclList(Decl *interfaceDecl, OCDS, AtLoc, MethodImplKind); // Parse all the comma separated declarators. - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseStructDeclaration(DS, Callback); - ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list, "", - tok::at); + ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list); break; } } @@ -582,12 +581,14 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl) { /// __attribute__((deprecated)) /// Decl *Parser::ParseObjCMethodPrototype(Decl *IDecl, - tok::ObjCKeywordKind MethodImplKind) { + tok::ObjCKeywordKind MethodImplKind, + bool MethodDefinition) { assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-"); tok::TokenKind methodType = Tok.getKind(); SourceLocation mLoc = ConsumeToken(); - Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, IDecl,MethodImplKind); + Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, IDecl,MethodImplKind, + MethodDefinition); // Since this rule is used for both method declarations and definitions, // the caller is (optionally) responsible for consuming the ';'. return MDecl; @@ -720,10 +721,12 @@ bool Parser::isTokIdentifier_in() const { /// objc-type-qualifier /// objc-type-qualifiers objc-type-qualifier /// -void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, bool IsParameter) { +void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, + ObjCTypeNameContext Context) { while (1) { if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCPassingType(getCurScope(), DS, IsParameter); + Actions.CodeCompleteObjCPassingType(getCurScope(), DS, + Context == OTN_ParameterType); ConsumeCodeCompletionToken(); } @@ -760,18 +763,19 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, bool IsParameter) { /// '(' objc-type-qualifiers[opt] type-name ')' /// '(' objc-type-qualifiers[opt] ')' /// -ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, bool IsParameter) { +ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, + ObjCTypeNameContext Context) { assert(Tok.is(tok::l_paren) && "expected ("); SourceLocation LParenLoc = ConsumeParen(); SourceLocation TypeStartLoc = Tok.getLocation(); // Parse type qualifiers, in, inout, etc. - ParseObjCTypeQualifierList(DS, IsParameter); + ParseObjCTypeQualifierList(DS, Context); ParsedType Ty; if (isTypeSpecifierQualifier()) { - TypeResult TypeSpec = ParseTypeName(); + TypeResult TypeSpec = ParseTypeName(0, Declarator::ObjCPrototypeContext); if (!TypeSpec.isInvalid()) Ty = TypeSpec.get(); } @@ -821,7 +825,8 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, bool IsParameter) { Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType, Decl *IDecl, - tok::ObjCKeywordKind MethodImplKind) { + tok::ObjCKeywordKind MethodImplKind, + bool MethodDefinition) { ParsingDeclRAIIObject PD(*this); if (Tok.is(tok::code_completion)) { @@ -834,12 +839,12 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ParsedType ReturnType; ObjCDeclSpec DSRet; if (Tok.is(tok::l_paren)) - ReturnType = ParseObjCTypeName(DSRet, false); + ReturnType = ParseObjCTypeName(DSRet, OTN_ResultType); // If attributes exist before the method, parse them. - ParsedAttributes attrs; + ParsedAttributes methodAttrs(AttrFactory); if (getLang().ObjC2) - MaybeParseGNUAttributes(attrs); + MaybeParseGNUAttributes(methodAttrs); if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, @@ -864,7 +869,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, if (Tok.isNot(tok::colon)) { // If attributes exist after the method, parse them. if (getLang().ObjC2) - MaybeParseGNUAttributes(attrs); + MaybeParseGNUAttributes(methodAttrs); Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent); Decl *Result @@ -872,7 +877,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, mType, IDecl, DSRet, ReturnType, Sel, 0, CParamInfo.data(), CParamInfo.size(), - attrs.getList(), MethodImplKind); + methodAttrs.getList(), MethodImplKind, + false, MethodDefinition); PD.complete(Result); return Result; } @@ -881,8 +887,11 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, llvm::SmallVector<Sema::ObjCArgInfo, 12> ArgInfos; ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope|Scope::DeclScope); + + AttributePool allParamAttrs(AttrFactory); while (1) { + ParsedAttributes paramAttrs(AttrFactory); Sema::ObjCArgInfo ArgInfo; // Each iteration parses a single keyword argument. @@ -894,14 +903,13 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ArgInfo.Type = ParsedType(); if (Tok.is(tok::l_paren)) // Parse the argument type if present. - ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec, true); + ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec, OTN_ParameterType); // If attributes exist before the argument name, parse them. ArgInfo.ArgAttrs = 0; if (getLang().ObjC2) { - ParsedAttributes attrs; - MaybeParseGNUAttributes(attrs); - ArgInfo.ArgAttrs = attrs.getList(); + MaybeParseGNUAttributes(paramAttrs); + ArgInfo.ArgAttrs = paramAttrs.getList(); } // Code completion for the next piece of the selector. @@ -930,6 +938,9 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ArgInfos.push_back(ArgInfo); KeyIdents.push_back(SelIdent); + // Make sure the attributes persist. + allParamAttrs.takeAllFrom(paramAttrs.getPool()); + // Code completion for the next piece of the selector. if (Tok.is(tok::code_completion)) { ConsumeCodeCompletionToken(); @@ -960,7 +971,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ConsumeToken(); break; } - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseDeclarationSpecifiers(DS); // Parse the declarator. Declarator ParmDecl(DS, Declarator::PrototypeContext); @@ -977,7 +988,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // FIXME: Add support for optional parameter list... // If attributes exist after the method, parse them. if (getLang().ObjC2) - MaybeParseGNUAttributes(attrs); + MaybeParseGNUAttributes(methodAttrs); if (KeyIdents.size() == 0) { // Leave prototype scope. @@ -992,8 +1003,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, mType, IDecl, DSRet, ReturnType, Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), - attrs.getList(), - MethodImplKind, isVariadic); + methodAttrs.getList(), + MethodImplKind, isVariadic, MethodDefinition); // Leave prototype scope. PrototypeScope.Exit(); @@ -1165,7 +1176,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, } Callback(*this, interfaceDecl, visibility, AllIvarDecls); // Parse all the comma separated declarators. - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseStructDeclaration(DS, Callback); if (Tok.is(tok::semi)) { @@ -1376,7 +1387,7 @@ Decl *Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) { } else { // missing @implementation - Diag(atEnd.getBegin(), diag::warn_expected_implementation); + Diag(atEnd.getBegin(), diag::err_expected_implementation); } return Result; } @@ -1609,7 +1620,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { ConsumeParen(); ParseScope CatchScope(this, Scope::DeclScope|Scope::AtCatchScope); if (Tok.isNot(tok::ellipsis)) { - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseDeclarationSpecifiers(DS); // For some odd reason, the name of the exception variable is // optional. As a result, we need to use "PrototypeContext", because @@ -1717,9 +1728,12 @@ Decl *Parser::ParseObjCMethodDefinition() { // specified Declarator for the method. Actions.ActOnStartOfObjCMethodDef(getCurScope(), MDecl); - if (PP.isCodeCompletionEnabled()) - if (trySkippingFunctionBodyForCodeCompletion()) + if (PP.isCodeCompletionEnabled()) { + if (trySkippingFunctionBodyForCodeCompletion()) { + BodyScope.Exit(); return Actions.ActOnFinishFunctionBody(MDecl, 0); + } + } StmtResult FnBody(ParseCompoundStatementBody()); @@ -1728,12 +1742,11 @@ Decl *Parser::ParseObjCMethodDefinition() { FnBody = Actions.ActOnCompoundStmt(BraceLoc, BraceLoc, MultiStmtArg(Actions), false); - // TODO: Pass argument information. - Actions.ActOnFinishFunctionBody(MDecl, FnBody.take()); - // Leave the function body scope. BodyScope.Exit(); - + + // TODO: Pass argument information. + Actions.ActOnFinishFunctionBody(MDecl, FnBody.take()); return MDecl; } @@ -1839,7 +1852,7 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) { // typename-specifier // simple-type-specifier // expression (that starts with one of the above) - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseCXXSimpleTypeSpecifier(DS); if (Tok.is(tok::l_paren)) { @@ -2337,7 +2350,7 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { return ExprError(Diag(Tok, diag::err_expected_colon)); ++nColons; - ConsumeToken(); // Eat the ':'. + ConsumeToken(); // Eat the ':' or '::'. if (Tok.is(tok::r_paren)) break; @@ -2353,7 +2366,7 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { SourceLocation Loc; SelIdent = ParseObjCSelectorPiece(Loc); KeyIdents.push_back(SelIdent); - if (!SelIdent && Tok.isNot(tok::colon)) + if (!SelIdent && Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon)) break; } } |