Allow functions to be marked "implicit return zero" and so mark main().
authorJohn McCall <rjmccall@apple.com>
Tue, 28 Jul 2009 01:00:58 +0000 (01:00 +0000)
committerJohn McCall <rjmccall@apple.com>
Tue, 28 Jul 2009 01:00:58 +0000 (01:00 +0000)
Codegen by initializing the return value with its LLVM type's null value.

llvm-svn: 77288

clang/include/clang/AST/Decl.h
clang/lib/CodeGen/CGCall.cpp
clang/lib/Sema/SemaDecl.cpp

index f8ee70b..3214b65 100644 (file)
@@ -682,6 +682,7 @@ private:
   bool HasWrittenPrototype : 1;
   bool IsDeleted : 1;
   bool IsTrivial : 1; // sunk from CXXMethodDecl
+  bool HasImplicitReturnZero : 1;
 
   // Move to DeclGroup when it is implemented.
   SourceLocation TypeSpecStartLoc;
@@ -722,6 +723,7 @@ protected:
       SClass(S), IsInline(isInline), C99InlineDefinition(false), 
       IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), 
       HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false),
+      HasImplicitReturnZero(false),
       TypeSpecStartLoc(TSSL), EndRangeLoc(L), TemplateOrSpecialization() {}
 
   virtual ~FunctionDecl() {}
@@ -798,6 +800,12 @@ public:
   bool isTrivial() const { return IsTrivial; }
   void setTrivial(bool IT) { IsTrivial = IT; }
 
+  /// Whether falling off this function implicitly returns null/zero.
+  /// If a more specific implicit return value is required, front-ends
+  /// should synthesize the appropriate return statements.
+  bool hasImplicitReturnZero() const { return HasImplicitReturnZero; }
+  void setHasImplicitReturnZero(bool IRZ) { HasImplicitReturnZero = IRZ; }
+
   /// \brief Whether this function has a prototype, either because one
   /// was explicitly written or because it was "inherited" by merging
   /// a declaration without a prototype with a declaration that has a
index 88a5eeb..d7019b6 100644 (file)
@@ -505,6 +505,19 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
 void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
                                          llvm::Function *Fn,
                                          const FunctionArgList &Args) {
+  // If this is an implicit-return-zero function, go ahead and
+  // initialize the return value.  TODO: it might be nice to have
+  // a more general mechanism for this that didn't require synthesized
+  // return statements.
+  if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(CurFuncDecl)) {
+    if (FD->hasImplicitReturnZero()) {
+      QualType RetTy = FD->getResultType().getUnqualifiedType();
+      const llvm::Type* LLVMTy = CGM.getTypes().ConvertType(RetTy);
+      llvm::Constant* Zero = CGM.getLLVMContext().getNullValue(LLVMTy);
+      Builder.CreateStore(Zero, ReturnValue);
+    }
+  }
+
   // FIXME: We no longer need the types from FunctionArgList; lift up and
   // simplify.
 
index 7ab7356..9b6de12 100644 (file)
@@ -3501,8 +3501,11 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg,
   Stmt *Body = BodyArg.takeAs<Stmt>();
   if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(dcl)) {
     FD->setBody(Body);
-    if (!FD->isMain())
+    if (FD->isMain())
       // C and C++ allow for main to automagically return 0.
+      // Implements C++ [basic.start.main]p5 and C99 5.1.2.2.3.
+      FD->setHasImplicitReturnZero(true);
+    else
       CheckFallThroughForFunctionDef(FD, Body);
     
     if (!FD->isInvalidDecl())