Index: lib/Analysis/ConstructionContext.cpp =================================================================== --- lib/Analysis/ConstructionContext.cpp +++ lib/Analysis/ConstructionContext.cpp @@ -40,6 +40,14 @@ llvm_unreachable("The above loop can only be terminated via return!"); } +// A helper - create a construction context in the given bump pointer allocator +// with given arguments. +template +static T *make(BumpVectorContext &C, ArgTypes... Args) { + auto *CC = C.getAllocator().Allocate(); + return new (CC) T(Args...); +} + const ConstructionContext *ConstructionContext::createFromLayers( BumpVectorContext &C, const ConstructionContextLayer *TopLayer) { // Before this point all we've had was a stockpile of arbitrary layers. @@ -48,15 +56,13 @@ if (const Stmt *S = TopLayer->getTriggerStmt()) { if (const auto *DS = dyn_cast(S)) { assert(TopLayer->isLast()); - auto *CC = - C.getAllocator().Allocate(); - return new (CC) SimpleVariableConstructionContext(DS); - } else if (const auto *NE = dyn_cast(S)) { + return make(C, DS); + } + if (const auto *NE = dyn_cast(S)) { assert(TopLayer->isLast()); - auto *CC = - C.getAllocator().Allocate(); - return new (CC) NewAllocatedObjectConstructionContext(NE); - } else if (const auto *BTE = dyn_cast(S)) { + return make(C, NE); + } + if (const auto *BTE = dyn_cast(S)) { const MaterializeTemporaryExpr *MTE = nullptr; assert(BTE->getType().getCanonicalType() ->getAsCXXRecordDecl()->hasNonTrivialDestructor()); @@ -68,9 +74,7 @@ ParentLayer->getTriggerStmt()))) { // A temporary object which has both destruction and // materialization info. - auto *CC = - C.getAllocator().Allocate(); - return new (CC) TemporaryObjectConstructionContext(BTE, MTE); + return make(C, BTE, MTE); } // C++17 *requires* elision of the constructor at the return site // and at variable initialization site, while previous standards @@ -78,50 +82,37 @@ if (auto *RS = dyn_cast(ParentLayer->getTriggerStmt())) { assert(!RS->getRetValue()->getType().getCanonicalType() ->getAsCXXRecordDecl()->hasTrivialDestructor()); - auto *CC = - C.getAllocator() - .Allocate< - CXX17ElidedCopyReturnedValueConstructionContext>(); - return new (CC) - CXX17ElidedCopyReturnedValueConstructionContext(RS, BTE); + return make(C, + RS, BTE); } if (auto *DS = dyn_cast(ParentLayer->getTriggerStmt())) { assert(!cast(DS->getSingleDecl())->getType() .getCanonicalType()->getAsCXXRecordDecl() ->hasTrivialDestructor()); - auto *CC = - C.getAllocator() - .Allocate(); - return new (CC) CXX17ElidedCopyVariableConstructionContext(DS, BTE); + return make(C, DS, BTE); } llvm_unreachable("Unexpected construction context with destructor!"); } // A temporary object that doesn't require materialization. - auto *CC = - C.getAllocator().Allocate(); - return new (CC) - TemporaryObjectConstructionContext(BTE, /*MTE=*/nullptr); - } else if (const auto *MTE = dyn_cast(S)) { + return make(C, BTE, /*MTE=*/nullptr); + } + if (const auto *MTE = dyn_cast(S)) { // If the object requires destruction and is not lifetime-extended, // then it must have a BTE within its MTE. assert(MTE->getType().getCanonicalType() ->getAsCXXRecordDecl()->hasTrivialDestructor() || MTE->getStorageDuration() != SD_FullExpression); assert(TopLayer->isLast()); - auto *CC = - C.getAllocator().Allocate(); - return new (CC) TemporaryObjectConstructionContext(nullptr, MTE); - } else if (const auto *RS = dyn_cast(S)) { + return make(C, nullptr, MTE); + } + if (const auto *RS = dyn_cast(S)) { assert(TopLayer->isLast()); - auto *CC = - C.getAllocator().Allocate(); - return new (CC) SimpleReturnedValueConstructionContext(RS); + return make(C, RS); } + llvm_unreachable("Unexpected construction context with statement!"); } else if (const CXXCtorInitializer *I = TopLayer->getTriggerInit()) { assert(TopLayer->isLast()); - auto *CC = - C.getAllocator().Allocate(); - return new (CC) ConstructorInitializerConstructionContext(I); + return make(C, I); } llvm_unreachable("Unexpected construction context!"); }