diff options
author | dim <dim@FreeBSD.org> | 2012-08-15 20:02:54 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2012-08-15 20:02:54 +0000 |
commit | 554bcb69c2d785a011a30e7db87a36a87fe7db10 (patch) | |
tree | 9abb1a658a297776086f4e0dfa6ca533de02104e /lib/Parse/ParseObjc.cpp | |
parent | bb67ca86b31f67faee50bd10c3b036d65751745a (diff) | |
download | FreeBSD-src-554bcb69c2d785a011a30e7db87a36a87fe7db10.zip FreeBSD-src-554bcb69c2d785a011a30e7db87a36a87fe7db10.tar.gz |
Vendor import of clang trunk r161861:
http://llvm.org/svn/llvm-project/cfe/trunk@161861
Diffstat (limited to 'lib/Parse/ParseObjc.cpp')
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 242 |
1 files changed, 161 insertions, 81 deletions
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 789a8ae..db35a38 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -308,16 +308,16 @@ public: MethodImplKind(MethodImplKind) { } - Decl *invoke(FieldDeclarator &FD) { + void invoke(ParsingFieldDeclarator &FD) { if (FD.D.getIdentifier() == 0) { P.Diag(AtLoc, diag::err_objc_property_requires_field_name) << FD.D.getSourceRange(); - return 0; + return; } if (FD.BitfieldSize) { P.Diag(AtLoc, diag::err_objc_property_bitfield) << FD.D.getSourceRange(); - return 0; + return; } // Install the property declarator into interfaceDecl. @@ -344,7 +344,7 @@ public: if (!isOverridingProperty) Props.push_back(Property); - return Property; + FD.complete(Property); } }; @@ -375,9 +375,9 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, while (1) { // If this is a method prototype, parse it. if (Tok.is(tok::minus) || Tok.is(tok::plus)) { - Decl *methodPrototype = - ParseObjCMethodPrototype(MethodImplKind, false); - allMethods.push_back(methodPrototype); + if (Decl *methodPrototype = + ParseObjCMethodPrototype(MethodImplKind, false)) + allMethods.push_back(methodPrototype); // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for // method definitions. if (ExpectAndConsumeSemi(diag::err_expected_semi_after_method_proto)) { @@ -420,7 +420,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, // erroneous r_brace would cause an infinite loop if not handled here. if (Tok.is(tok::r_brace)) break; - ParsedAttributes attrs(AttrFactory); + ParsedAttributesWithRange attrs(AttrFactory); allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(attrs)); continue; } @@ -493,7 +493,7 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, OCDS, AtLoc, LParenLoc, MethodImplKind); // Parse all the comma separated declarators. - DeclSpec DS(AttrFactory); + ParsingDeclSpec DS(*this); ParseStructDeclaration(DS, Callback); ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list); @@ -894,6 +894,7 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, DeclSpec declSpec(AttrFactory); declSpec.setObjCQualifiers(&DS); ParseSpecifierQualifierList(declSpec); + declSpec.SetRangeEnd(Tok.getLocation()); Declarator declarator(declSpec, context); ParseDeclarator(declarator); @@ -965,7 +966,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType, tok::ObjCKeywordKind MethodImplKind, bool MethodDefinition) { - ParsingDeclRAIIObject PD(*this); + ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent); if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, @@ -1000,8 +1001,8 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, if (!SelIdent && Tok.isNot(tok::colon)) { // missing selector name. Diag(Tok, diag::err_expected_selector_for_method) << SourceRange(mLoc, Tok.getLocation()); - // Skip until we get a ; or {}. - SkipUntil(tok::r_brace); + // Skip until we get a ; or @. + SkipUntil(tok::at, true /*StopAtSemi*/, true /*don't consume*/); return 0; } @@ -1105,7 +1106,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, } bool isVariadic = false; - + bool cStyleParamWarned = false; // Parse the (optional) parameter list. while (Tok.is(tok::comma)) { ConsumeToken(); @@ -1114,6 +1115,10 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ConsumeToken(); break; } + if (!cStyleParamWarned) { + Diag(Tok, diag::warn_cstyle_param); + cStyleParamWarned = true; + } DeclSpec DS(AttrFactory); ParseDeclarationSpecifiers(DS); // Parse the declarator. @@ -1125,7 +1130,6 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ParmDecl.getIdentifierLoc(), Param, 0)); - } // FIXME: Add support for optional parameter list... @@ -1258,9 +1262,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, // Check for extraneous top-level semicolon. if (Tok.is(tok::semi)) { - Diag(Tok, diag::ext_extra_ivar_semi) - << FixItHint::CreateRemoval(Tok.getLocation()); - ConsumeToken(); + ConsumeExtraSemi(InstanceVariableList); continue; } @@ -1304,7 +1306,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, P(P), IDecl(IDecl), visibility(V), AllIvarDecls(AllIvarDecls) { } - Decl *invoke(FieldDeclarator &FD) { + void invoke(ParsingFieldDeclarator &FD) { P.Actions.ActOnObjCContainerStartDefinition(IDecl); // Install the declarator into the interface decl. Decl *Field @@ -1314,12 +1316,12 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, P.Actions.ActOnObjCContainerFinishDefinition(); if (Field) AllIvarDecls.push_back(Field); - return Field; + FD.complete(Field); } } Callback(*this, interfaceDecl, visibility, AllIvarDecls); // Parse all the comma separated declarators. - DeclSpec DS(AttrFactory); + ParsingDeclSpec DS(*this); ParseStructDeclaration(DS, Callback); if (Tok.is(tok::semi)) { @@ -1348,15 +1350,15 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl, /// objc-protocol-forward-reference /// /// objc-protocol-definition: -/// @protocol identifier +/// \@protocol identifier /// objc-protocol-refs[opt] /// objc-interface-decl-list -/// @end +/// \@end /// /// objc-protocol-forward-reference: -/// @protocol identifier-list ';' +/// \@protocol identifier-list ';' /// -/// "@protocol identifier ;" should be resolved as "@protocol +/// "\@protocol identifier ;" should be resolved as "\@protocol /// identifier-list ;": objc-interface-decl-list may not start with a /// semicolon in the first alternative if objc-protocol-refs are omitted. Parser::DeclGroupPtrTy @@ -1573,10 +1575,16 @@ void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) { assert(!Finished); P.Actions.DefaultSynthesizeProperties(P.getCurScope(), Dcl); for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i) - P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i]); + P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i], + true/*Methods*/); P.Actions.ActOnAtEnd(P.getCurScope(), AtEnd); + if (HasCFunction) + for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i) + P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i], + false/*c-functions*/); + /// \brief Clear and free the cached objc methods. for (LateParsedObjCMethodContainer::iterator I = LateParsedObjCMethods.begin(), @@ -1608,8 +1616,8 @@ Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) { SourceLocation classLoc = ConsumeToken(); // consume class-name; ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@compatibility_alias"); - return Actions.ActOnCompatiblityAlias(atLoc, aliasId, aliasLoc, - classId, classLoc); + return Actions.ActOnCompatibilityAlias(atLoc, aliasId, aliasLoc, + classId, classLoc); } /// property-synthesis: @@ -1913,6 +1921,43 @@ Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) { AutoreleasePoolBody.take()); } +/// StashAwayMethodOrFunctionBodyTokens - Consume the tokens and store them +/// for later parsing. +void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) { + LexedMethod* LM = new LexedMethod(this, MDecl); + CurParsedObjCImpl->LateParsedObjCMethods.push_back(LM); + CachedTokens &Toks = LM->Toks; + // Begin by storing the '{' or 'try' or ':' token. + Toks.push_back(Tok); + if (Tok.is(tok::kw_try)) { + ConsumeToken(); + if (Tok.is(tok::colon)) { + Toks.push_back(Tok); + ConsumeToken(); + while (Tok.isNot(tok::l_brace)) { + ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false); + ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false); + } + } + Toks.push_back(Tok); // also store '{' + } + else if (Tok.is(tok::colon)) { + ConsumeToken(); + while (Tok.isNot(tok::l_brace)) { + ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false); + ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false); + } + Toks.push_back(Tok); // also store '{' + } + ConsumeBrace(); + // Consume everything up to (and including) the matching right brace. + ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); + while (Tok.is(tok::kw_catch)) { + ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false); + ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); + } +} + /// objc-method-def: objc-method-proto ';'[opt] '{' body '}' /// Decl *Parser::ParseObjCMethodDefinition() { @@ -1950,23 +1995,10 @@ Decl *Parser::ParseObjCMethodDefinition() { // Allow the rest of sema to find private method decl implementations. Actions.AddAnyMethodToGlobalPool(MDecl); - - if (CurParsedObjCImpl) { - // Consume the tokens and store them for later parsing. - LexedMethod* LM = new LexedMethod(this, MDecl); - CurParsedObjCImpl->LateParsedObjCMethods.push_back(LM); - CachedTokens &Toks = LM->Toks; - // Begin by storing the '{' token. - Toks.push_back(Tok); - ConsumeBrace(); - // Consume everything up to (and including) the matching right brace. - ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); - - } else { - ConsumeBrace(); - SkipUntil(tok::r_brace, /*StopAtSemi=*/false); - } - + assert (CurParsedObjCImpl + && "ParseObjCMethodDefinition - Method out of @implementation"); + // Consume the tokens and store them for later parsing. + StashAwayMethodOrFunctionBodyTokens(MDecl); return MDecl; } @@ -2066,6 +2098,10 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { // Objective-C dictionary literal return ParsePostfixExpressionSuffix(ParseObjCDictionaryLiteral(AtLoc)); + case tok::l_paren: + // Objective-C boxed expression + return ParsePostfixExpressionSuffix(ParseObjCBoxedExpr(AtLoc)); + default: if (Tok.getIdentifierInfo() == 0) return ExprError(Diag(AtLoc, diag::err_unexpected_at)); @@ -2077,8 +2113,23 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc)); case tok::objc_selector: return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc)); - default: - return ExprError(Diag(AtLoc, diag::err_unexpected_at)); + default: { + const char *str = 0; + if (GetLookAheadToken(1).is(tok::l_brace)) { + char ch = Tok.getIdentifierInfo()->getNameStart()[0]; + str = + ch == 't' ? "try" + : (ch == 'f' ? "finally" + : (ch == 'a' ? "autoreleasepool" : 0)); + } + if (str) { + SourceLocation kwLoc = Tok.getLocation(); + return ExprError(Diag(AtLoc, diag::err_unexpected_at) << + FixItHint::CreateReplacement(kwLoc, str)); + } + else + return ExprError(Diag(AtLoc, diag::err_unexpected_at)); + } } } } @@ -2112,7 +2163,7 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) { Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope)) TryAnnotateTypeOrScopeToken(); - if (!isCXXSimpleTypeSpecifier()) { + if (!Actions.isSimpleTypeSpecifier(Tok.getKind())) { // objc-receiver: // expression ExprResult Receiver = ParseExpression(); @@ -2449,10 +2500,14 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, } // Parse the, optional, argument list, comma separated. while (Tok.is(tok::comma)) { - ConsumeToken(); // Eat the ','. + SourceLocation commaLoc = ConsumeToken(); // Eat the ','. /// Parse the expression after ',' ExprResult Res(ParseAssignmentExpression()); if (Res.isInvalid()) { + if (Tok.is(tok::colon)) { + Diag(commaLoc, diag::note_extra_comma_message_arg) << + FixItHint::CreateRemoval(commaLoc); + } // We must manually skip to a ']', otherwise the expression skipper will // stop at the ']' when it skips to the ';'. We want it to skip beyond // the enclosing expression. @@ -2580,6 +2635,31 @@ ExprResult Parser::ParseObjCNumericLiteral(SourceLocation AtLoc) { return Owned(Actions.BuildObjCNumericLiteral(AtLoc, Lit.take())); } +/// ParseObjCBoxedExpr - +/// objc-box-expression: +/// @( assignment-expression ) +ExprResult +Parser::ParseObjCBoxedExpr(SourceLocation AtLoc) { + if (Tok.isNot(tok::l_paren)) + return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@"); + + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + ExprResult ValueExpr(ParseAssignmentExpression()); + if (T.consumeClose()) + return ExprError(); + + if (ValueExpr.isInvalid()) + return ExprError(); + + // Wrap the sub-expression in a parenthesized expression, to distinguish + // a boxed expression from a literal. + SourceLocation LPLoc = T.getOpenLocation(), RPLoc = T.getCloseLocation(); + ValueExpr = Actions.ActOnParenExpr(LPLoc, RPLoc, ValueExpr.take()); + return Owned(Actions.BuildObjCBoxedExpr(SourceRange(AtLoc, RPLoc), + ValueExpr.take())); +} + ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) { ExprVector ElementExprs(Actions); // array elements. ConsumeBracket(); // consume the l_square. @@ -2698,7 +2778,7 @@ Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) { } /// objc-protocol-expression -/// @protocol ( protocol-name ) +/// \@protocol ( protocol-name ) ExprResult Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) { SourceLocation ProtoLoc = ConsumeToken(); @@ -2713,12 +2793,13 @@ Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) { return ExprError(Diag(Tok, diag::err_expected_ident)); IdentifierInfo *protocolId = Tok.getIdentifierInfo(); - ConsumeToken(); + SourceLocation ProtoIdLoc = ConsumeToken(); T.consumeClose(); return Owned(Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc, T.getOpenLocation(), + ProtoIdLoc, T.getCloseLocation())); } @@ -2785,8 +2866,15 @@ ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) { T.getCloseLocation())); } -Decl *Parser::ParseLexedObjCMethodDefs(LexedMethod &LM) { - +void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { + // MCDecl might be null due to error in method or c-function prototype, etc. + Decl *MCDecl = LM.D; + bool skip = MCDecl && + ((parseMethod && !Actions.isObjCMethodDecl(MCDecl)) || + (!parseMethod && Actions.isObjCMethodDecl(MCDecl))); + if (skip) + return; + // Save the current token position. SourceLocation OrigLoc = Tok.getLocation(); @@ -2796,40 +2884,32 @@ Decl *Parser::ParseLexedObjCMethodDefs(LexedMethod &LM) { LM.Toks.push_back(Tok); PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false); - // MDecl might be null due to error in method prototype, etc. - Decl *MDecl = LM.D; // Consume the previously pushed token. ConsumeAnyToken(); - assert(Tok.is(tok::l_brace) && "Inline objective-c method not starting with '{'"); - SourceLocation BraceLoc = Tok.getLocation(); - // Enter a scope for the method body. + assert((Tok.is(tok::l_brace) || Tok.is(tok::kw_try) || + Tok.is(tok::colon)) && + "Inline objective-c method not starting with '{' or 'try' or ':'"); + // Enter a scope for the method or c-fucntion body. ParseScope BodyScope(this, - Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope); - - // Tell the actions module that we have entered a method definition with the - // specified Declarator for the method. - Actions.ActOnStartOfObjCMethodDef(getCurScope(), MDecl); - - if (SkipFunctionBodies && trySkippingFunctionBody()) { - BodyScope.Exit(); - return Actions.ActOnFinishFunctionBody(MDecl, 0); - } - - StmtResult FnBody(ParseCompoundStatementBody()); + parseMethod + ? Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope + : Scope::FnScope|Scope::DeclScope); - // If the function body could not be parsed, make a bogus compoundstmt. - if (FnBody.isInvalid()) { - Sema::CompoundScopeRAII CompoundScope(Actions); - FnBody = Actions.ActOnCompoundStmt(BraceLoc, BraceLoc, - MultiStmtArg(Actions), false); + // Tell the actions module that we have entered a method or c-function definition + // with the specified Declarator for the method/function. + if (parseMethod) + Actions.ActOnStartOfObjCMethodDef(getCurScope(), MCDecl); + else + Actions.ActOnStartOfFunctionDef(getCurScope(), MCDecl); + if (Tok.is(tok::kw_try)) + MCDecl = ParseFunctionTryBlock(MCDecl, BodyScope); + else { + if (Tok.is(tok::colon)) + ParseConstructorInitializer(MCDecl); + MCDecl = ParseFunctionStatementBody(MCDecl, BodyScope); } - - // Leave the function body scope. - BodyScope.Exit(); - - MDecl = Actions.ActOnFinishFunctionBody(MDecl, FnBody.take()); - + if (Tok.getLocation() != OrigLoc) { // Due to parsing error, we either went over the cached tokens or // there are still cached tokens left. If it's the latter case skip the @@ -2842,5 +2922,5 @@ Decl *Parser::ParseLexedObjCMethodDefs(LexedMethod &LM) { ConsumeAnyToken(); } - return MDecl; + return; } |