[cfe-commits] r159626 - in /cfe/trunk: include/clang/Parse/Parser.h include/clang/Sema/Sema.h lib/Parse/ParseDecl.cpp lib/Parse/ParseObjc.cpp lib/Parse/Parser.cpp lib/Sema/SemaDeclObjC.cpp test/SemaObjC/delay-parsing-cfunctions.m
Jean-Daniel Dupas
devlists at shadowlab.org
Tue Jul 3 15:02:32 PDT 2012
This commit broke the Obj-C++11 parser:
---- 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
> +
> + at interface MyClass
> +- (void)someMethod;
> + at end
> +
> + at 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;
> +
> + at end
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
-- Jean-Daniel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20120704/980013c9/attachment.html>
More information about the cfe-commits
mailing list