This also caused http://llvm.org/bugs/show_bug.cgi?id=13418 . Can you take a look? This is a bit tricky to revert by now.
On Tue, Jul 3, 2012 at 3:55 PM, jahanian <[email protected]> wrote: > > On Jul 3, 2012, at 3:02 PM, Jean-Daniel Dupas wrote: > > This commit broke the Obj-C++11 parser: > > > Fixed in r159691. > > - Fariborz > > > ---- foo.mm > @interface Foo > @end > > @implementation Foo > > static int test() { > return 0; > } > > @end > > ---------- > clang++ -fsyntax-only -std=c++11 foo.mm > foo.mm:8:2: error: expected expression > return 0; > ^ > foo.mm:9:2: error: expected ';' after top level declarator > } > ^ > ; > foo.mm:12:1: error: missing '@end' > ^ > > @end > > foo.mm:5:1: note: implementation started here > @implementation Foo > ^ > 3 errors generated. > > > > Le 3 juil. 2012 à 01:37, Fariborz Jahanian a écrit : > > Author: fjahanian > Date: Mon Jul 2 18:37:09 2012 > New Revision: 159626 > > URL: http://llvm.org/viewvc/llvm-project?rev=159626&view=rev > Log: > objective-c: just as we have done for method definitions, > c-functions declared in implementation should have their > parsing delayed until the end so, they can access forward > declared private methods. // rdar://10387088 > > Added: > cfe/trunk/test/SemaObjC/delay-parsing-cfunctions.m > Modified: > cfe/trunk/include/clang/Parse/Parser.h > cfe/trunk/include/clang/Sema/Sema.h > cfe/trunk/lib/Parse/ParseDecl.cpp > cfe/trunk/lib/Parse/ParseObjc.cpp > cfe/trunk/lib/Parse/Parser.cpp > cfe/trunk/lib/Sema/SemaDeclObjC.cpp > > Modified: cfe/trunk/include/clang/Parse/Parser.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=159626&r1=159625&r2=159626&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Parse/Parser.h (original) > +++ cfe/trunk/include/clang/Parse/Parser.h Mon Jul 2 18:37:09 2012 > @@ -1019,7 +1019,7 @@ > void ParseLexedMethodDef(LexedMethod &LM); > void ParseLexedMemberInitializers(ParsingClass &Class); > void ParseLexedMemberInitializer(LateParsedMemberInitializer &MI); > - Decl *ParseLexedObjCMethodDefs(LexedMethod &LM); > + void ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod); > bool ConsumeAndStoreFunctionPrologue(CachedTokens &Toks); > bool ConsumeAndStoreUntil(tok::TokenKind T1, > CachedTokens &Toks, > @@ -1084,11 +1084,12 @@ > struct ObjCImplParsingDataRAII { > Parser &P; > Decl *Dcl; > + bool HasCFunction; > typedef SmallVector<LexedMethod*, 8> LateParsedObjCMethodContainer; > LateParsedObjCMethodContainer LateParsedObjCMethods; > > ObjCImplParsingDataRAII(Parser &parser, Decl *D) > - : P(parser), Dcl(D) { > + : P(parser), Dcl(D), HasCFunction(false) { > P.CurParsedObjCImpl = this; > Finished = false; > } > @@ -1101,6 +1102,7 @@ > bool Finished; > }; > ObjCImplParsingDataRAII *CurParsedObjCImpl; > + void StashAwayMethodOrFunctionBodyTokens(Decl *MDecl); > > DeclGroupPtrTy ParseObjCAtImplementationDeclaration(SourceLocation AtLoc); > DeclGroupPtrTy ParseObjCAtEndDeclaration(SourceRange atEnd); > > Modified: cfe/trunk/include/clang/Sema/Sema.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=159626&r1=159625&r2=159626&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Sema/Sema.h (original) > +++ cfe/trunk/include/clang/Sema/Sema.h Mon Jul 2 18:37:09 2012 > @@ -1317,7 +1317,11 @@ > void CheckForFunctionRedefinition(FunctionDecl *FD); > Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D); > Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D); > - void ActOnStartOfObjCMethodDef(Scope *S, Decl *D); > + void ActOnStartOfObjCMethodOrCFunctionDef(Scope *S, Decl *D, > + bool parseMethod); > + bool isObjCMethodDecl(Decl *D) { > + return D && isa<ObjCMethodDecl>(D); > + } > > void computeNRVO(Stmt *Body, sema::FunctionScopeInfo *Scope); > Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body); > > Modified: cfe/trunk/lib/Parse/ParseDecl.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=159626&r1=159625&r2=159626&view=diff > ============================================================================== > --- cfe/trunk/lib/Parse/ParseDecl.cpp (original) > +++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Jul 2 18:37:09 2012 > @@ -1379,6 +1379,14 @@ > > 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)) { > > Modified: cfe/trunk/lib/Parse/ParseObjc.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=159626&r1=159625&r2=159626&view=diff > ============================================================================== > --- cfe/trunk/lib/Parse/ParseObjc.cpp (original) > +++ cfe/trunk/lib/Parse/ParseObjc.cpp Mon Jul 2 18:37:09 2012 > @@ -1575,10 +1575,16 @@ > 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 @@ > 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 @@ > > 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 @@ > 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 @@ > 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 @@ > // 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 @@ > ConsumeAnyToken(); > } > > - return MDecl; > + return; > } > > Modified: cfe/trunk/lib/Parse/Parser.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=159626&r1=159625&r2=159626&view=diff > ============================================================================== > --- cfe/trunk/lib/Parse/Parser.cpp (original) > +++ cfe/trunk/lib/Parse/Parser.cpp Mon Jul 2 18:37:09 2012 > @@ -766,14 +766,16 @@ > 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 > > Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=159626&r1=159625&r2=159626&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original) > +++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Mon Jul 2 18:37:09 2012 > @@ -265,12 +265,36 @@ > 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; > > Added: cfe/trunk/test/SemaObjC/delay-parsing-cfunctions.m > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/delay-parsing-cfunctions.m?rev=159626&view=auto > ============================================================================== > --- cfe/trunk/test/SemaObjC/delay-parsing-cfunctions.m (added) > +++ cfe/trunk/test/SemaObjC/delay-parsing-cfunctions.m Mon Jul 2 18:37:09 > 2012 > @@ -0,0 +1,32 @@ > +// RUN: %clang_cc1 -fsyntax-only -Werror -verify -Wno-objc-root-class %s > +// RUN: %clang_cc1 -x objective-c++ -fsyntax-only -Werror -verify > -Wno-objc-root-class %s > +// rdar://10387088 > + > +@interface MyClass > +- (void)someMethod; > +@end > + > +@implementation MyClass > +- (void)someMethod { > + [self privateMethod]; // clang already does not warn here > +} > + > +int bar(MyClass * myObject) { > + [myObject privateMethod]; > + return gorfbar(myObject); > +} > +- (void)privateMethod { } > + > +int gorfbar(MyClass * myObject) { > + [myObject privateMethod]; > + [myObject privateMethod1]; > + return getMe + bar(myObject); > +} > + > +- (void)privateMethod1 { > + getMe = getMe+1; > +} > + > +static int getMe; > + > +@end > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > > > -- Jean-Daniel > > > > > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
