Extract out function-body code generation into its own method.  No functionality
change.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96564 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index d803a05..ddf4e64 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -241,6 +241,53 @@
   }
 }
 
+void CodeGenFunction::GenerateBody(GlobalDecl GD, llvm::Function *Fn, 
+                                   FunctionArgList &Args) {
+  const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
+
+  Stmt *Body = FD->getBody();
+  assert((Body || FD->isImplicit()) && "non-implicit function def has no body");
+
+  // Emit special ctor/dtor prologues.
+  llvm::BasicBlock *DtorEpilogue = 0;
+  if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
+    EmitCtorPrologue(CD, GD.getCtorType());
+  } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
+    DtorEpilogue = createBasicBlock("dtor.epilogue");
+    PushCleanupBlock(DtorEpilogue);
+
+    InitializeVtablePtrs(DD->getParent());
+  }
+
+  // Emit the body of the function.
+  if (!Body)
+    SynthesizeImplicitFunctionBody(GD, Fn, Args);
+  else {
+    if (isa<CXXTryStmt>(Body))
+      OuterTryBlock = cast<CXXTryStmt>(Body);
+
+    EmitStmt(Body);
+  }
+
+  // Emit special ctor/ctor epilogues.
+  if (isa<CXXConstructorDecl>(FD)) {
+    // If any of the member initializers are temporaries bound to references
+    // make sure to emit their destructors.
+    EmitCleanupBlocks(0);
+  } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
+    CleanupBlockInfo Info = PopCleanupBlock();
+    assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!");
+
+    EmitBlock(DtorEpilogue);
+    EmitDtorEpilogue(DD, GD.getDtorType());
+      
+    if (Info.SwitchBlock)
+      EmitBlock(Info.SwitchBlock);
+    if (Info.EndBlock)
+      EmitBlock(Info.EndBlock);
+  }
+}
+
 void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) {
   const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
   
@@ -284,80 +331,17 @@
                                     FProto->getArgType(i)));
   }
 
-  if (const CompoundStmt *S = FD->getCompoundBody()) {
-    StartFunction(GD, FD->getResultType(), Fn, Args, S->getLBracLoc());
+  SourceRange BodyRange;
+  if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange();
 
-    if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
-      EmitCtorPrologue(CD, GD.getCtorType());
-      EmitStmt(S);
-      
-      // If any of the member initializers are temporaries bound to references
-      // make sure to emit their destructors.
-      EmitCleanupBlocks(0);
-      
-    } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
-      llvm::BasicBlock *DtorEpilogue  = createBasicBlock("dtor.epilogue");
-      PushCleanupBlock(DtorEpilogue);
+  // Emit the standard function prologue.
+  StartFunction(GD, FD->getResultType(), Fn, Args, BodyRange.getBegin());
 
-      InitializeVtablePtrs(DD->getParent());
+  // Generate the body of the function.
+  GenerateBody(GD, Fn, Args);
 
-      EmitStmt(S);
-      
-      CleanupBlockInfo Info = PopCleanupBlock();
-
-      assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!");
-      EmitBlock(DtorEpilogue);
-      EmitDtorEpilogue(DD, GD.getDtorType());
-      
-      if (Info.SwitchBlock)
-        EmitBlock(Info.SwitchBlock);
-      if (Info.EndBlock)
-        EmitBlock(Info.EndBlock);
-    } else {
-      // Just a regular function, emit its body.
-      EmitStmt(S);
-    }
-    
-    FinishFunction(S->getRBracLoc());
-  } else if (FD->isImplicit()) {
-    const CXXRecordDecl *ClassDecl =
-      cast<CXXRecordDecl>(FD->getDeclContext());
-    (void) ClassDecl;
-    if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
-      // FIXME: For C++0x, we want to look for implicit *definitions* of
-      // these special member functions, rather than implicit *declarations*.
-      if (CD->isCopyConstructor()) {
-        assert(!ClassDecl->hasUserDeclaredCopyConstructor() &&
-               "Cannot synthesize a non-implicit copy constructor");
-        SynthesizeCXXCopyConstructor(CD, GD.getCtorType(), Fn, Args);
-      } else if (CD->isDefaultConstructor()) {
-        assert(!ClassDecl->hasUserDeclaredConstructor() &&
-               "Cannot synthesize a non-implicit default constructor.");
-        SynthesizeDefaultConstructor(CD, GD.getCtorType(), Fn, Args);
-      } else {
-        assert(false && "Implicit constructor cannot be synthesized");
-      }
-    } else if (const CXXDestructorDecl *CD = dyn_cast<CXXDestructorDecl>(FD)) {
-      assert(!ClassDecl->hasUserDeclaredDestructor() &&
-             "Cannot synthesize a non-implicit destructor");
-      SynthesizeDefaultDestructor(CD, GD.getDtorType(), Fn, Args);
-    } else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
-      assert(MD->isCopyAssignment() && 
-             !ClassDecl->hasUserDeclaredCopyAssignment() &&
-             "Cannot synthesize a method that is not an implicit-defined "
-             "copy constructor");
-      SynthesizeCXXCopyAssignment(MD, Fn, Args);
-    } else {
-      assert(false && "Cannot synthesize unknown implicit function");
-    }
-  } else if (const Stmt *S = FD->getBody()) {
-    if (const CXXTryStmt *TS = dyn_cast<CXXTryStmt>(S)) {
-      OuterTryBlock = TS;
-      StartFunction(GD, FD->getResultType(), Fn, Args, TS->getTryLoc());
-      EmitStmt(TS);
-      FinishFunction(TS->getEndLoc());
-    }
-  }
+  // Emit the standard function epilogue.
+  FinishFunction(BodyRange.getEnd());
 
   // Destroy the 'this' declaration.
   if (CXXThisDecl)