aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-07-28 01:00:58 +0000
committerJohn McCall <rjmccall@apple.com>2009-07-28 01:00:58 +0000
commit0cfeb63f532973777f6fe75d3468c3acad4adfe3 (patch)
tree246a78d6e341750300ff051bed028a52cd6c1ea0
parent41ef0c3472a3d09c29bc1792f3d26842f2b8a695 (diff)
Allow functions to be marked "implicit return zero" and so mark main().
Codegen by initializing the return value with its LLVM type's null value. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77288 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Decl.h8
-rw-r--r--lib/CodeGen/CGCall.cpp13
-rw-r--r--lib/Sema/SemaDecl.cpp5
3 files changed, 25 insertions, 1 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index f8ee70b752..3214b653b9 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -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
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 88a5eeb68e..d7019b605d 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -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.
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 7ab7356aa0..9b6de12bb2 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -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())