Represent method definitions as separate AST nodes. Pretty print will come next.
llvm-svn: 43979
This commit is contained in:
parent
d2c16ff905
commit
85e1d0d807
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue