diff options
author | Saleem Abdulrasool <compnerd@compnerd.org> | 2019-07-25 17:59:29 +0000 |
---|---|---|
committer | Saleem Abdulrasool <compnerd@compnerd.org> | 2019-07-25 17:59:29 +0000 |
commit | 930df11a0d00c467b17c76f2b782a96bf721599b (patch) | |
tree | ae52fcdfc3035a15d5a0e44ae5a162a29bf17bbc /clang/lib/CodeGen/CGExprAgg.cpp | |
parent | baeab1fc442e2781d0d527f22b3ff4722a35f11c (diff) | |
download | bcm5719-llvm-930df11a0d00c467b17c76f2b782a96bf721599b.tar.gz bcm5719-llvm-930df11a0d00c467b17c76f2b782a96bf721599b.zip |
CodeGen: ensure placeholder instruction for cleanup is created
A placeholder instruction for use in generation of cleanup code for an
initializer list would not be emitted if the base class contained a
non-trivial destructor and the class contains no fields of its own. This
would be the case when using CTAD to deduce the template arguments for a
struct with an overloaded call operator, e.g.
```
template <class... Ts> struct ctad : Ts... {};
template <class... Ts> ctad(Ts...)->ctad<Ts...>;
```
and this class was initialized with a list of lambdas capturing by copy,
e.g.
```
ctad c {[s](short){}, [s](long){}};
```
In a release build the bug would manifest itself as a crash in the SROA
pass, however, in a debug build the following assert in CGCleanup.cpp
would fail:
```
assert(dominatingIP && "no existing variable and no dominating IP!");
```
By ensuring that a placeholder instruction is emitted even if there's no
fields in the class, neither the assert nor the crash is reproducible.
See https://bugs.llvm.org/show_bug.cgi?id=40771
Patch by Øystein Dale!
llvm-svn: 367042
Diffstat (limited to 'clang/lib/CodeGen/CGExprAgg.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 695facd50b6..0a57870a7c5 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -1495,6 +1495,13 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { // initializers throws an exception. SmallVector<EHScopeStack::stable_iterator, 16> cleanups; llvm::Instruction *cleanupDominator = nullptr; + auto addCleanup = [&](const EHScopeStack::stable_iterator &cleanup) { + cleanups.push_back(cleanup); + if (!cleanupDominator) // create placeholder once needed + cleanupDominator = CGF.Builder.CreateAlignedLoad( + CGF.Int8Ty, llvm::Constant::getNullValue(CGF.Int8PtrTy), + CharUnits::One()); + }; unsigned curInitIndex = 0; @@ -1519,7 +1526,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { if (QualType::DestructionKind dtorKind = Base.getType().isDestructedType()) { CGF.pushDestroy(dtorKind, V, Base.getType()); - cleanups.push_back(CGF.EHStack.stable_begin()); + addCleanup(CGF.EHStack.stable_begin()); } } } @@ -1596,15 +1603,9 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { = field->getType().isDestructedType()) { assert(LV.isSimple()); if (CGF.needsEHCleanup(dtorKind)) { - if (!cleanupDominator) - cleanupDominator = CGF.Builder.CreateAlignedLoad( - CGF.Int8Ty, - llvm::Constant::getNullValue(CGF.Int8PtrTy), - CharUnits::One()); // placeholder - CGF.pushDestroy(EHCleanup, LV.getAddress(), field->getType(), CGF.getDestroyer(dtorKind), false); - cleanups.push_back(CGF.EHStack.stable_begin()); + addCleanup(CGF.EHStack.stable_begin()); pushedCleanup = true; } } @@ -1620,6 +1621,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { // Deactivate all the partial cleanups in reverse order, which // generally means popping them. + assert((cleanupDominator || cleanups.empty()) && + "Missing cleanupDominator before deactivating cleanup blocks"); for (unsigned i = cleanups.size(); i != 0; --i) CGF.DeactivateCleanupBlock(cleanups[i-1], cleanupDominator); |