]> granicus.if.org Git - clang/commitdiff
Represent method definitions as separate AST nodes. Pretty print will come next.
authorFariborz Jahanian <fjahanian@apple.com>
Sat, 10 Nov 2007 16:31:34 +0000 (16:31 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Sat, 10 Nov 2007 16:31:34 +0000 (16:31 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43979 91177308-0d34-0410-b5e6-96231b3b80d8

Parse/ParseObjc.cpp
Parse/Parser.cpp
Sema/Sema.h
Sema/SemaDecl.cpp
include/clang/AST/DeclObjC.h
include/clang/Parse/Action.h
include/clang/Parse/Parser.h

index b8b5b913ee8c421e7e93e3ebbccfaf4b444a2467..b5f742961dce30be0875dc977d94e0630d48aea6 100644 (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) {
index cfa92e102077239488355489e94bcbe200ac3e16..1f8e016bfe686ab1a3dbb27f6dbbbfbfc3fc9794 100644 (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
index 9816e810095af44aa917ef8927df6ee2fa581ecc..31b54106dbe2c009376eea90a50abfee7e47ef1d 100644 (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);
index 1fb221931afd9a04c439972ed8640122945e53d5..65e7af53210dd646082af9b8da3d2a74cdb1ff3f 100644 (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) {
index fcc1dbf2f6d7e01e6af4aeca264c4117e4f8312a..550b64791acf5ef66b8e9767a4ee3bc488ffd1bd 100644 (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; }
index c91caded273e1558e1374429f532852d12e86c2f..ec9d4e30dd74dcdc0a369daf625e4ea43e777cee 100644 (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.
index 3a1e7d18cef4b0c324925204d071316fa1f2b4a4..89ebfd84377891ac58d2d450e99a2f1e28373330 100644 (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.