summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CodeGenFunction.cpp
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2017-01-04 13:40:34 +0000
committerAlex Lorenz <arphaman@gmail.com>2017-01-04 13:40:34 +0000
commitc1608f7f691438d6d457b317c681775621aeac7c (patch)
treed2c423d3ad6fefcb41862808037f0087736192fe /clang/lib/CodeGen/CodeGenFunction.cpp
parentaf16c50639289fd0875100519a1161bc7058f215 (diff)
downloadbcm5719-llvm-c1608f7f691438d6d457b317c681775621aeac7c.tar.gz
bcm5719-llvm-c1608f7f691438d6d457b317c681775621aeac7c.zip
Add -f[no-]strict-return flag that can be used to avoid undefined behaviour
in non-void functions that fall off at the end without returning a value when compiling C++. Clang uses the new compiler flag to determine when it should treat control flow paths that fall off the end of a non-void function as unreachable. If -fno-strict-return is on, the code generator emits the ureachable and trap IR only when the function returns either a record type with a non-trivial destructor or another non-trivially copyable type. The primary goal of this flag is to avoid treating falling off the end of a non-void function as undefined behaviour. The burden of undefined behaviour is placed on the caller instead: if the caller ignores the returned value then the undefined behaviour is avoided. This kind of behaviour is useful in several cases, e.g. when compiling C code in C++ mode. rdar://13102603 Differential Revision: https://reviews.llvm.org/D27163 llvm-svn: 290960
Diffstat (limited to 'clang/lib/CodeGen/CodeGenFunction.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp27
1 files changed, 23 insertions, 4 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index a954f487d1e..7cab13de923 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1049,6 +1049,19 @@ QualType CodeGenFunction::BuildFunctionArgList(GlobalDecl GD,
return ResTy;
}
+static bool
+shouldUseUndefinedBehaviorReturnOptimization(const FunctionDecl *FD,
+ const ASTContext &Context) {
+ QualType T = FD->getReturnType();
+ // Avoid the optimization for functions that return a record type with a
+ // trivial destructor or another trivially copyable type.
+ if (const RecordType *RT = T.getCanonicalType()->getAs<RecordType>()) {
+ if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl()))
+ return !ClassDecl->hasTrivialDestructor();
+ }
+ return !T.isTriviallyCopyableType(Context);
+}
+
void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
const CGFunctionInfo &FnInfo) {
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
@@ -1127,17 +1140,23 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
// function call is used by the caller, the behavior is undefined.
if (getLangOpts().CPlusPlus && !FD->hasImplicitReturnZero() && !SawAsmBlock &&
!FD->getReturnType()->isVoidType() && Builder.GetInsertBlock()) {
+ bool ShouldEmitUnreachable =
+ CGM.getCodeGenOpts().StrictReturn ||
+ shouldUseUndefinedBehaviorReturnOptimization(FD, getContext());
if (SanOpts.has(SanitizerKind::Return)) {
SanitizerScope SanScope(this);
llvm::Value *IsFalse = Builder.getFalse();
EmitCheck(std::make_pair(IsFalse, SanitizerKind::Return),
SanitizerHandler::MissingReturn,
EmitCheckSourceLocation(FD->getLocation()), None);
- } else if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
- EmitTrapCall(llvm::Intrinsic::trap);
+ } else if (ShouldEmitUnreachable) {
+ if (CGM.getCodeGenOpts().OptimizationLevel == 0)
+ EmitTrapCall(llvm::Intrinsic::trap);
+ }
+ if (SanOpts.has(SanitizerKind::Return) || ShouldEmitUnreachable) {
+ Builder.CreateUnreachable();
+ Builder.ClearInsertionPoint();
}
- Builder.CreateUnreachable();
- Builder.ClearInsertionPoint();
}
// Emit the standard function epilogue.
OpenPOWER on IntegriCloud