If we flow off the end of a value-returning function:

- outside C++, return undef (behavior is not undefined unless the value is used)
 - in C++, with -fcatch-undefined-behavior, perform an appropriate trap
 - in C++, produce an 'unreachable' (behavior is undefined immediately)

llvm-svn: 165273
This commit is contained in:
Richard Smith 2012-10-04 23:52:29 +00:00
parent 4d6cd886f5
commit 9f9e5826f2
4 changed files with 34 additions and 0 deletions

View File

@ -535,6 +535,20 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
else
EmitFunctionBody(Args);
// C++11 [stmt.return]p2:
// Flowing off the end of a function [...] results in undefined behavior in
// a value-returning function.
// C11 6.9.1p12:
// If the '}' that terminates a function is reached, and the value of the
// function call is used by the caller, the behavior is undefined.
if (getContext().getLangOpts().CPlusPlus && !FD->hasImplicitReturnZero() &&
!FD->getResultType()->isVoidType() && Builder.GetInsertBlock()) {
if (CatchUndefined)
EmitCheck(Builder.getFalse());
Builder.CreateUnreachable();
Builder.ClearInsertionPoint();
}
// Emit the standard function epilogue.
FinishFunction(BodyRange.getEnd());

View File

@ -44,3 +44,11 @@ int rsh_inbounds(int a, int b) {
// CHECK-NEXT: ret i32 %[[RET]]
return a >> b;
}
// CHECK: @no_return
int no_return() {
// Reaching the end of a noreturn function is fine in C.
// CHECK-NOT: call
// CHECK-NOT: unreachable
// CHECK: ret i32
}

View File

@ -86,3 +86,9 @@ int lsh_overflow(int a, int b) {
// CHECK-NEXT: ret i32 %[[RET]]
return a << b;
}
// CHECK: @_Z9no_return
int no_return() {
// CHECK: call void @llvm.trap
// CHECK: unreachable
}

View File

@ -0,0 +1,6 @@
// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
// CHECK: @_Z9no_return
int no_return() {
// CHECK: unreachable
}