/// 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??
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??
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) {
// @ 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();
}
/// 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);
// If we didn't find the '{', bail out.
if (Tok.isNot(tok::l_brace))
- return 0;
+ return;
}
SourceLocation BraceLoc = Tok.getLocation();
// 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
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);
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) {
/// 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,
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; }
}
virtual DeclTy *ObjcActOnStartOfMethodDef(Scope *FnBodyScope, DeclTy *D) {
- // Default to ActOnDeclarator.
+ // Default to ObjcActOnMethodDefinition.
return ObjcActOnMethodDefinition(FnBodyScope, D, 0);
}
return Decl;
}
+ virtual void ActOnMethodDefBody(DeclTy *Decl, StmtTy *Body) {
+ return;
+ }
/// ActOnPopScope - This callback is called immediately before the specified
/// scope is popped and deleted.
DeclTy *ParseExternalDeclaration();
DeclTy *ParseDeclarationOrFunctionDefinition();
DeclTy *ParseFunctionDefinition(Declarator &D);
- DeclTy *ObjcParseMethodDefinition(DeclTy *D);
+ void ObjcParseMethodDefinition(DeclTy *D);
void ParseKNRParamDeclarations(Declarator &D);
void ParseSimpleAsm();
void ParseAsmStringLiteral();
void ParseObjCPropertyAttribute(ObjcDeclSpec &DS);
DeclTy *ParseObjCPropertyDecl(DeclTy *interfaceDecl, SourceLocation AtLoc);
- DeclTy *ParseObjCInstanceMethodDefinition();
- DeclTy *ParseObjCClassMethodDefinition();
+ void ParseObjCInstanceMethodDefinition();
+ void ParseObjCClassMethodDefinition();
//===--------------------------------------------------------------------===//
// C99 6.5: Expressions.