summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2018-08-04 01:25:06 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2018-08-04 01:25:06 +0000
commitaa140bf164a3f248bc7b892fb73054d8185bef4c (patch)
tree37f712114302dab504cce310892580c6fe13cb11 /clang/lib/CodeGen
parente07b3b737bba5d629965a49470e6fd87f7df8b16 (diff)
downloadbcm5719-llvm-aa140bf164a3f248bc7b892fb73054d8185bef4c.tar.gz
bcm5719-llvm-aa140bf164a3f248bc7b892fb73054d8185bef4c.zip
Avoid creating conditional cleanup blocks that contain only @llvm.lifetime.end calls
When a non-extended temporary object is created in a conditional branch, the lifetime of that temporary ends outside the conditional (at the end of the full-expression). If we're inserting lifetime markers, this means we could end up generating if (some_cond) { lifetime.start(&tmp); Tmp::Tmp(&tmp); } // ... if (some_cond) { lifetime.end(&tmp); } ... for a full-expression containing a subexpression of the form `some_cond ? Tmp().x : 0`. This patch moves the lifetime start for such a temporary out of the conditional branch so that we don't need to generate an additional basic block to hold the lifetime end marker. This is disabled if we want precise lifetime markers (for asan's stack-use-after-scope checks) or of the temporary has a non-trivial destructor (in which case we'd generate an extra basic block anyway to hold the destructor call). Differential Revision: https://reviews.llvm.org/D50286 llvm-svn: 338945
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp47
1 files changed, 40 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index f168dd02ead..c8ba352e233 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -498,18 +498,51 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
} else {
switch (M->getStorageDuration()) {
case SD_Automatic:
- case SD_FullExpression:
if (auto *Size = EmitLifetimeStart(
CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()),
Alloca.getPointer())) {
- if (M->getStorageDuration() == SD_Automatic)
- pushCleanupAfterFullExpr<CallLifetimeEnd>(NormalEHLifetimeMarker,
- Alloca, Size);
- else
- pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Alloca,
- Size);
+ pushCleanupAfterFullExpr<CallLifetimeEnd>(NormalEHLifetimeMarker,
+ Alloca, Size);
}
break;
+
+ case SD_FullExpression: {
+ if (!ShouldEmitLifetimeMarkers)
+ break;
+
+ // Avoid creating a conditional cleanup just to hold an llvm.lifetime.end
+ // marker. Instead, start the lifetime of a conditional temporary earlier
+ // so that it's unconditional. Don't do this in ASan's use-after-scope
+ // mode so that it gets the more precise lifetime marks. If the type has
+ // a non-trivial destructor, we'll have a cleanup block for it anyway,
+ // so this typically doesn't help; skip it in that case.
+ ConditionalEvaluation *OldConditional = nullptr;
+ CGBuilderTy::InsertPoint OldIP;
+ if (isInConditionalBranch() && !E->getType().isDestructedType() &&
+ !CGM.getCodeGenOpts().SanitizeAddressUseAfterScope) {
+ OldConditional = OutermostConditional;
+ OutermostConditional = nullptr;
+
+ OldIP = Builder.saveIP();
+ llvm::BasicBlock *Block = OldConditional->getStartingBlock();
+ Builder.restoreIP(CGBuilderTy::InsertPoint(
+ Block, llvm::BasicBlock::iterator(Block->back())));
+ }
+
+ if (auto *Size = EmitLifetimeStart(
+ CGM.getDataLayout().getTypeAllocSize(Alloca.getElementType()),
+ Alloca.getPointer())) {
+ pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Alloca,
+ Size);
+ }
+
+ if (OldConditional) {
+ OutermostConditional = OldConditional;
+ Builder.restoreIP(OldIP);
+ }
+ break;
+ }
+
default:
break;
}
OpenPOWER on IntegriCloud