aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-10-04 23:52:29 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-10-04 23:52:29 +0000
commit36ef0d54cfddf31cd48816e78ab4db73b31a6c1d (patch)
treea7b58d06715aadcfe6ff90abdf525f2ab1dfdbef
parentc339393067438596599b142a8950f0e8694e2f1a (diff)
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) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@165273 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp14
-rw-r--r--test/CodeGen/catch-undef-behavior.c8
-rw-r--r--test/CodeGenCXX/catch-undef-behavior.cpp6
-rw-r--r--test/CodeGenCXX/return.cpp6
4 files changed, 34 insertions, 0 deletions
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index 1d02861ed7..5c0247a33f 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -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());
diff --git a/test/CodeGen/catch-undef-behavior.c b/test/CodeGen/catch-undef-behavior.c
index 5832b6c830..53dda5c8b2 100644
--- a/test/CodeGen/catch-undef-behavior.c
+++ b/test/CodeGen/catch-undef-behavior.c
@@ -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
+}
diff --git a/test/CodeGenCXX/catch-undef-behavior.cpp b/test/CodeGenCXX/catch-undef-behavior.cpp
index 0ec1cc1e05..fdc2b00bcb 100644
--- a/test/CodeGenCXX/catch-undef-behavior.cpp
+++ b/test/CodeGenCXX/catch-undef-behavior.cpp
@@ -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
+}
diff --git a/test/CodeGenCXX/return.cpp b/test/CodeGenCXX/return.cpp
new file mode 100644
index 0000000000..2af1a5266e
--- /dev/null
+++ b/test/CodeGenCXX/return.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+
+// CHECK: @_Z9no_return
+int no_return() {
+ // CHECK: unreachable
+}