From: Fariborz Jahanian Date: Sat, 10 Nov 2007 16:31:34 +0000 (+0000) Subject: Represent method definitions as separate AST nodes. Pretty print will come next. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=60fbca0b027ff5a6579f16cb6e3abab826e0d967;p=clang Represent method definitions as separate AST nodes. Pretty print will come next. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43979 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp index b8b5b913ee..b5f742961d 100644 --- a/Parse/ParseObjc.cpp +++ b/Parse/ParseObjc.cpp @@ -1147,7 +1147,7 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { /// objc-method-def: objc-method-proto ';'[opt] '{' body '}' /// -Parser::DeclTy *Parser::ParseObjCInstanceMethodDefinition() { +void Parser::ParseObjCInstanceMethodDefinition() { assert(Tok.is(tok::minus) && "Method definitions should start with '-'"); DeclTy *MDecl = ParseObjCMethodPrototype(ObjcImpDecl); // FIXME: @optional/@protocol?? @@ -1158,14 +1158,14 @@ Parser::DeclTy *Parser::ParseObjCInstanceMethodDefinition() { if (Tok.isNot(tok::l_brace)) { Diag (Tok, diag::err_expected_lbrace); - return 0; + return; } - return ObjcParseMethodDefinition(MDecl); + ObjcParseMethodDefinition(MDecl); } /// objc-method-def: objc-method-proto ';'[opt] '{' body '}' /// -Parser::DeclTy *Parser::ParseObjCClassMethodDefinition() { +void Parser::ParseObjCClassMethodDefinition() { assert(Tok.is(tok::plus) && "Class method definitions should start with '+'"); DeclTy *MDecl = ParseObjCMethodPrototype(ObjcImpDecl); // FIXME: @optional/@protocol?? @@ -1175,9 +1175,9 @@ Parser::DeclTy *Parser::ParseObjCClassMethodDefinition() { ConsumeToken(); if (Tok.isNot(tok::l_brace)) { Diag (Tok, diag::err_expected_lbrace); - return 0; + return; } - return ObjcParseMethodDefinition(MDecl); + ObjcParseMethodDefinition(MDecl); } Parser::ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { diff --git a/Parse/Parser.cpp b/Parse/Parser.cpp index cfa92e1020..1f8e016bfe 100644 --- a/Parse/Parser.cpp +++ b/Parse/Parser.cpp @@ -330,17 +330,17 @@ Parser::DeclTy *Parser::ParseExternalDeclaration() { // @ is not a legal token unless objc is enabled, no need to check. return ParseObjCAtDirectives(); case tok::minus: - if (getLang().ObjC1) { - return ParseObjCInstanceMethodDefinition(); - } else { + if (getLang().ObjC1) + ParseObjCInstanceMethodDefinition(); + else { Diag(Tok, diag::err_expected_external_declaration); ConsumeToken(); } return 0; case tok::plus: - if (getLang().ObjC1) { - return ParseObjCClassMethodDefinition(); - } else { + if (getLang().ObjC1) + ParseObjCClassMethodDefinition(); + else { Diag(Tok, diag::err_expected_external_declaration); ConsumeToken(); } @@ -467,7 +467,7 @@ Parser::DeclTy *Parser::ParseFunctionDefinition(Declarator &D) { /// ObjcParseMethodDefinition - This routine parses a method definition and /// returns its AST. -Parser::DeclTy *Parser::ObjcParseMethodDefinition(DeclTy *D) { +void Parser::ObjcParseMethodDefinition(DeclTy *D) { // We should have an opening brace now. if (Tok.isNot(tok::l_brace)) { Diag(Tok, diag::err_expected_fn_body); @@ -477,7 +477,7 @@ Parser::DeclTy *Parser::ObjcParseMethodDefinition(DeclTy *D) { // If we didn't find the '{', bail out. if (Tok.isNot(tok::l_brace)) - return 0; + return; } SourceLocation BraceLoc = Tok.getLocation(); @@ -487,9 +487,19 @@ Parser::DeclTy *Parser::ObjcParseMethodDefinition(DeclTy *D) { // Tell the actions module that we have entered a method definition with the // specified Declarator for the method. - DeclTy *Res = Actions.ObjcActOnStartOfMethodDef(CurScope, D); + Actions.ObjcActOnStartOfMethodDef(CurScope, D); - return ParseFunctionStatementBody(Res, BraceLoc, BraceLoc); + StmtResult FnBody = ParseCompoundStatementBody(); + + // If the function body could not be parsed, make a bogus compoundstmt. + if (FnBody.isInvalid) + FnBody = Actions.ActOnCompoundStmt(BraceLoc, BraceLoc, 0, 0, false); + + // Leave the function body scope. + ExitScope(); + + // TODO: Pass argument information. + Actions.ActOnMethodDefBody(D, FnBody.Val); } /// ParseKNRParamDeclarations - Parse 'declaration-list[opt]' which provides diff --git a/Sema/Sema.h b/Sema/Sema.h index 9816e81009..31b54106db 100644 --- a/Sema/Sema.h +++ b/Sema/Sema.h @@ -192,6 +192,7 @@ private: virtual DeclTy *ActOnStartOfFunctionDef(Scope *S, Declarator &D); virtual DeclTy *ObjcActOnStartOfMethodDef(Scope *S, DeclTy *D); virtual DeclTy *ActOnFunctionDefBody(DeclTy *Decl, StmtTy *Body); + virtual void ActOnMethodDefBody(DeclTy *Decl, StmtTy *Body); /// Scope actions. virtual void ActOnPopScope(SourceLocation Loc, Scope *S); diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index 1fb221931a..65e7af5321 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -1023,6 +1023,34 @@ Sema::DeclTy *Sema::ActOnFunctionDefBody(DeclTy *D, StmtTy *Body) { return FD; } +void Sema::ActOnMethodDefBody(DeclTy *D, StmtTy *Body) { + ObjcMethodDecl *FD = static_cast(D); + FD->setBody((Stmt*)Body); + CurFunctionDecl = 0; + + // Verify and clean out per-function state. + + // Check goto/label use. + for (llvm::DenseMap::iterator + I = LabelMap.begin(), E = LabelMap.end(); I != E; ++I) { + // Verify that we have no forward references left. If so, there was a goto + // or address of a label taken, but no definition of it. Label fwd + // definitions are indicated with a null substmt. + if (I->second->getSubStmt() == 0) { + LabelStmt *L = I->second; + // Emit error. + Diag(L->getIdentLoc(), diag::err_undeclared_label_use, L->getName()); + + // At this point, we have gotos that use the bogus label. Stitch it into + // the function body so that they aren't leaked and that the AST is well + // formed. + L->setSubStmt(new NullStmt(L->getIdentLoc())); + cast((Stmt*)Body)->push_back(L); + } + } + LabelMap.clear(); +} + /// ObjcActOnStartOfMethodDef - This routine sets up parameters; invisible /// and user declared, in the method definition's AST. Sema::DeclTy *Sema::ObjcActOnStartOfMethodDef(Scope *FnBodyScope, DeclTy *D) { diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index fcc1dbf2f6..550b64791a 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -255,6 +255,8 @@ private: /// List of attributes for this method declaration. AttributeList *MethodAttrs; + Stmt *Body; // Null if a prototype. + SourceLocation EndLoc; // the location of the ';' or '{'. public: ObjcMethodDecl(SourceLocation beginLoc, SourceLocation endLoc, @@ -300,6 +302,9 @@ public: ImplementationControl getImplementationControl() const { return DeclImplementation; } + Stmt *const getBody() const { return Body; } + void setBody(Stmt *B) { Body = B; } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == ObjcMethod; } static bool classof(const ObjcMethodDecl *D) { return true; } diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index c91caded27..ec9d4e30dd 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -136,7 +136,7 @@ public: } virtual DeclTy *ObjcActOnStartOfMethodDef(Scope *FnBodyScope, DeclTy *D) { - // Default to ActOnDeclarator. + // Default to ObjcActOnMethodDefinition. return ObjcActOnMethodDefinition(FnBodyScope, D, 0); } @@ -146,6 +146,9 @@ public: return Decl; } + virtual void ActOnMethodDefBody(DeclTy *Decl, StmtTy *Body) { + return; + } /// ActOnPopScope - This callback is called immediately before the specified /// scope is popped and deleted. diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 3a1e7d18ce..89ebfd8437 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -250,7 +250,7 @@ private: DeclTy *ParseExternalDeclaration(); DeclTy *ParseDeclarationOrFunctionDefinition(); DeclTy *ParseFunctionDefinition(Declarator &D); - DeclTy *ObjcParseMethodDefinition(DeclTy *D); + void ObjcParseMethodDefinition(DeclTy *D); void ParseKNRParamDeclarations(Declarator &D); void ParseSimpleAsm(); void ParseAsmStringLiteral(); @@ -302,8 +302,8 @@ private: void ParseObjCPropertyAttribute(ObjcDeclSpec &DS); DeclTy *ParseObjCPropertyDecl(DeclTy *interfaceDecl, SourceLocation AtLoc); - DeclTy *ParseObjCInstanceMethodDefinition(); - DeclTy *ParseObjCClassMethodDefinition(); + void ParseObjCInstanceMethodDefinition(); + void ParseObjCClassMethodDefinition(); //===--------------------------------------------------------------------===// // C99 6.5: Expressions.