diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 8 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 63 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 34 |
4 files changed, 82 insertions, 29 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index c61f5543a6..ac221117b5 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1379,6 +1379,14 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, bool ExpectSemi = Context != Declarator::ForContext; + if (CurParsedObjCImpl && D.isFunctionDeclarator() && + Tok.is(tok::l_brace)) { + // Consume the tokens and store them for later parsing. + StashAwayMethodOrFunctionBodyTokens(FirstDecl); + CurParsedObjCImpl->HasCFunction = true; + ExpectSemi = false; + } + // If we don't have a comma, it is either the end of the list (a ';') or an // error, bail out. while (Tok.is(tok::comma)) { diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 2540ad940d..35e4222c52 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -1575,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(), @@ -1915,6 +1921,19 @@ 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 '{' token. + Toks.push_back(Tok); + ConsumeBrace(); + // Consume everything up to (and including) the matching right brace. + ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); +} + /// objc-method-def: objc-method-proto ';'[opt] '{' body '}' /// Decl *Parser::ParseObjCMethodDefinition() { @@ -1955,15 +1974,7 @@ Decl *Parser::ParseObjCMethodDefinition() { 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); - + StashAwayMethodOrFunctionBodyTokens(MDecl); } else { ConsumeBrace(); SkipUntil(tok::r_brace, /*StopAtSemi=*/false); @@ -2821,8 +2832,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(); @@ -2832,24 +2850,25 @@ 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. + // Enter a scope for the method or c-fucntion body. ParseScope BodyScope(this, - Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope); + parseMethod + ? Scope::ObjCMethodScope|Scope::FnScope|Scope::DeclScope + : 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); + // Tell the actions module that we have entered a method or c-function definition + // with the specified Declarator for the method/function. + Actions.ActOnStartOfObjCMethodOrCFunctionDef(getCurScope(), MCDecl, parseMethod); if (SkipFunctionBodies && trySkippingFunctionBody()) { BodyScope.Exit(); - return Actions.ActOnFinishFunctionBody(MDecl, 0); + (void)Actions.ActOnFinishFunctionBody(MCDecl, 0); + return; } StmtResult FnBody(ParseCompoundStatementBody()); @@ -2864,7 +2883,7 @@ Decl *Parser::ParseLexedObjCMethodDefs(LexedMethod &LM) { // Leave the function body scope. BodyScope.Exit(); - MDecl = Actions.ActOnFinishFunctionBody(MDecl, FnBody.take()); + (void)Actions.ActOnFinishFunctionBody(MCDecl, FnBody.take()); if (Tok.getLocation() != OrigLoc) { // Due to parsing error, we either went over the cached tokens or @@ -2878,5 +2897,5 @@ Decl *Parser::ParseLexedObjCMethodDefs(LexedMethod &LM) { ConsumeAnyToken(); } - return MDecl; + return; } diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index bec6dd717c..c2c4c90090 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -766,14 +766,16 @@ bool Parser::isDeclarationAfterDeclarator() { if (KW.is(tok::kw_default) || KW.is(tok::kw_delete)) return false; } - + return Tok.is(tok::equal) || // int X()= -> not a function def Tok.is(tok::comma) || // int X(), -> not a function def Tok.is(tok::semi) || // int X(); -> not a function def Tok.is(tok::kw_asm) || // int X() __asm__ -> not a function def Tok.is(tok::kw___attribute) || // int X() __attr__ -> not a function def (getLangOpts().CPlusPlus && - Tok.is(tok::l_paren)); // int X(0) -> not a function def [C++] + Tok.is(tok::l_paren)) || // int X(0) -> not a function def [C++] + (CurParsedObjCImpl && + Tok.is(tok::l_brace)); // C-function nested in an @implementation } /// \brief Determine whether the current token, if it occurs after a diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index a673d247ed..7342128715 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -265,12 +265,36 @@ void Sema::AddAnyMethodToGlobalPool(Decl *D) { AddFactoryMethodToGlobalPool(MDecl, true); } -/// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible -/// and user declared, in the method definition's AST. -void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { - assert(getCurMethodDecl() == 0 && "Method parsing confused"); +/// ActOnStartOfObjCMethodOrCFunctionDef - This routine sets up parameters; invisible +/// and user declared, in the method definition's AST. This routine is also called +/// for C-functions defined in an Objective-c class implementation. +void Sema::ActOnStartOfObjCMethodOrCFunctionDef(Scope *FnBodyScope, Decl *D, + bool parseMethod) { + assert((getCurMethodDecl() == 0 && getCurFunctionDecl() == 0) && + "Method/c-function parsing confused"); + if (!parseMethod) { + FunctionDecl *FDecl = FDecl = dyn_cast_or_null<FunctionDecl>(D); + // If we don't have a valid c-function decl, simply return. + if (!FDecl) + return; + PushDeclContext(FnBodyScope, FDecl); + PushFunctionScope(); + + for (FunctionDecl::param_const_iterator PI = FDecl->param_begin(), + E = FDecl->param_end(); PI != E; ++PI) { + ParmVarDecl *Param = (*PI); + if (!Param->isInvalidDecl() && + RequireCompleteType(Param->getLocation(), Param->getType(), + diag::err_typecheck_decl_incomplete_type)) + Param->setInvalidDecl(); + if ((*PI)->getIdentifier()) + PushOnScopeChains(*PI, FnBodyScope); + } + return; + } + ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D); - + // If we don't have a valid method decl, simply return. if (!MDecl) return; |