Represent method definitions as separate AST nodes. Pretty print will come next.

llvm-svn: 43979
This commit is contained in:
Fariborz Jahanian 2007-11-10 16:31:34 +00:00
parent d2c16ff905
commit 85e1d0d807
7 changed files with 67 additions and 20 deletions

View File

@ -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) {

View File

@ -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

View File

@ -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);

View File

@ -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<ObjcMethodDecl*>(D);
FD->setBody((Stmt*)Body);
CurFunctionDecl = 0;
// Verify and clean out per-function state.
// Check goto/label use.
for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::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<CompoundStmt>((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) {

View File

@ -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; }

View File

@ -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.

View File

@ -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.