[CFG] [analyzer] NFC: Move construction context allocation into a helper method.

Improve readability of ConstructionContext::createFromLayers().

Differential Revision: https://reviews.llvm.org/D44725

llvm-svn: 328249
This commit is contained in:
Artem Dergachev 2018-03-22 21:40:24 +00:00
parent 317291e340
commit 2c2344e327
2 changed files with 49 additions and 44 deletions

View File

@ -118,6 +118,14 @@ protected:
// via createFromLayers().
explicit ConstructionContext(Kind K) : K(K) {}
private:
// A helper function for constructing an instance into a bump vector context.
template <typename T, typename... ArgTypes>
static T *create(BumpVectorContext &C, ArgTypes... Args) {
auto *CC = C.getAllocator().Allocate<T>();
return new (CC) T(Args...);
}
public:
/// Consume the construction context layer, together with its parent layers,
/// and wrap it up into a complete construction context.
@ -153,11 +161,13 @@ public:
/// elidable copy-constructor from makeT() into var would also be a simple
/// variable constructor handled by this class.
class SimpleVariableConstructionContext : public VariableConstructionContext {
public:
friend class ConstructionContext; // Allows to create<>() itself.
explicit SimpleVariableConstructionContext(const DeclStmt *DS)
: VariableConstructionContext(ConstructionContext::SimpleVariableKind,
DS) {}
public:
static bool classof(const ConstructionContext *CC) {
return CC->getKind() == SimpleVariableKind;
}
@ -176,13 +186,15 @@ class CXX17ElidedCopyVariableConstructionContext
: public VariableConstructionContext {
const CXXBindTemporaryExpr *BTE;
public:
friend class ConstructionContext; // Allows to create<>() itself.
explicit CXX17ElidedCopyVariableConstructionContext(
const DeclStmt *DS, const CXXBindTemporaryExpr *BTE)
: VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) {
assert(BTE);
}
public:
const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
static bool classof(const ConstructionContext *CC) {
@ -195,7 +207,8 @@ public:
class ConstructorInitializerConstructionContext : public ConstructionContext {
const CXXCtorInitializer *I;
public:
friend class ConstructionContext; // Allows to create<>() itself.
explicit ConstructorInitializerConstructionContext(
const CXXCtorInitializer *I)
: ConstructionContext(ConstructionContext::ConstructorInitializerKind),
@ -203,6 +216,7 @@ public:
assert(I);
}
public:
const CXXCtorInitializer *getCXXCtorInitializer() const { return I; }
static bool classof(const ConstructionContext *CC) {
@ -215,13 +229,15 @@ public:
class NewAllocatedObjectConstructionContext : public ConstructionContext {
const CXXNewExpr *NE;
public:
friend class ConstructionContext; // Allows to create<>() itself.
explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE)
: ConstructionContext(ConstructionContext::NewAllocatedObjectKind),
NE(NE) {
assert(NE);
}
public:
const CXXNewExpr *getCXXNewExpr() const { return NE; }
static bool classof(const ConstructionContext *CC) {
@ -237,7 +253,8 @@ class TemporaryObjectConstructionContext : public ConstructionContext {
const CXXBindTemporaryExpr *BTE;
const MaterializeTemporaryExpr *MTE;
public:
friend class ConstructionContext; // Allows to create<>() itself.
explicit TemporaryObjectConstructionContext(
const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE)
: ConstructionContext(ConstructionContext::TemporaryObjectKind),
@ -248,6 +265,7 @@ public:
// nowhere that doesn't have a non-trivial destructor).
}
public:
/// CXXBindTemporaryExpr here is non-null as long as the temporary has
/// a non-trivial destructor.
const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const {
@ -295,11 +313,13 @@ public:
/// MaterializeTemporaryExpr) is normally located in the caller function's AST.
class SimpleReturnedValueConstructionContext
: public ReturnedValueConstructionContext {
public:
friend class ConstructionContext; // Allows to create<>() itself.
explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS)
: ReturnedValueConstructionContext(
ConstructionContext::SimpleReturnedValueKind, RS) {}
public:
static bool classof(const ConstructionContext *CC) {
return CC->getKind() == SimpleReturnedValueKind;
}
@ -317,7 +337,8 @@ class CXX17ElidedCopyReturnedValueConstructionContext
: public ReturnedValueConstructionContext {
const CXXBindTemporaryExpr *BTE;
public:
friend class ConstructionContext; // Allows to create<>() itself.
explicit CXX17ElidedCopyReturnedValueConstructionContext(
const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE)
: ReturnedValueConstructionContext(
@ -326,6 +347,7 @@ public:
assert(BTE);
}
public:
const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
static bool classof(const ConstructionContext *CC) {

View File

@ -48,15 +48,13 @@ const ConstructionContext *ConstructionContext::createFromLayers(
if (const Stmt *S = TopLayer->getTriggerStmt()) {
if (const auto *DS = dyn_cast<DeclStmt>(S)) {
assert(TopLayer->isLast());
auto *CC =
C.getAllocator().Allocate<SimpleVariableConstructionContext>();
return new (CC) SimpleVariableConstructionContext(DS);
} else if (const auto *NE = dyn_cast<CXXNewExpr>(S)) {
return create<SimpleVariableConstructionContext>(C, DS);
}
if (const auto *NE = dyn_cast<CXXNewExpr>(S)) {
assert(TopLayer->isLast());
auto *CC =
C.getAllocator().Allocate<NewAllocatedObjectConstructionContext>();
return new (CC) NewAllocatedObjectConstructionContext(NE);
} else if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(S)) {
return create<NewAllocatedObjectConstructionContext>(C, NE);
}
if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(S)) {
const MaterializeTemporaryExpr *MTE = nullptr;
assert(BTE->getType().getCanonicalType()
->getAsCXXRecordDecl()->hasNonTrivialDestructor());
@ -68,9 +66,7 @@ const ConstructionContext *ConstructionContext::createFromLayers(
ParentLayer->getTriggerStmt()))) {
// A temporary object which has both destruction and
// materialization info.
auto *CC =
C.getAllocator().Allocate<TemporaryObjectConstructionContext>();
return new (CC) TemporaryObjectConstructionContext(BTE, MTE);
return create<TemporaryObjectConstructionContext>(C, BTE, MTE);
}
// C++17 *requires* elision of the constructor at the return site
// and at variable initialization site, while previous standards
@ -78,50 +74,37 @@ const ConstructionContext *ConstructionContext::createFromLayers(
if (auto *RS = dyn_cast<ReturnStmt>(ParentLayer->getTriggerStmt())) {
assert(!RS->getRetValue()->getType().getCanonicalType()
->getAsCXXRecordDecl()->hasTrivialDestructor());
auto *CC =
C.getAllocator()
.Allocate<
CXX17ElidedCopyReturnedValueConstructionContext>();
return new (CC)
CXX17ElidedCopyReturnedValueConstructionContext(RS, BTE);
return create<CXX17ElidedCopyReturnedValueConstructionContext>(C,
RS, BTE);
}
if (auto *DS = dyn_cast<DeclStmt>(ParentLayer->getTriggerStmt())) {
assert(!cast<VarDecl>(DS->getSingleDecl())->getType()
.getCanonicalType()->getAsCXXRecordDecl()
->hasTrivialDestructor());
auto *CC =
C.getAllocator()
.Allocate<CXX17ElidedCopyVariableConstructionContext>();
return new (CC) CXX17ElidedCopyVariableConstructionContext(DS, BTE);
return create<CXX17ElidedCopyVariableConstructionContext>(C, DS, BTE);
}
llvm_unreachable("Unexpected construction context with destructor!");
}
// A temporary object that doesn't require materialization.
auto *CC =
C.getAllocator().Allocate<TemporaryObjectConstructionContext>();
return new (CC)
TemporaryObjectConstructionContext(BTE, /*MTE=*/nullptr);
} else if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(S)) {
return create<TemporaryObjectConstructionContext>(C, BTE, /*MTE=*/nullptr);
}
if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(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<TemporaryObjectConstructionContext>();
return new (CC) TemporaryObjectConstructionContext(nullptr, MTE);
} else if (const auto *RS = dyn_cast<ReturnStmt>(S)) {
assert(TopLayer->isLast());
auto *CC =
C.getAllocator().Allocate<SimpleReturnedValueConstructionContext>();
return new (CC) SimpleReturnedValueConstructionContext(RS);
return create<TemporaryObjectConstructionContext>(C, nullptr, MTE);
}
if (const auto *RS = dyn_cast<ReturnStmt>(S)) {
assert(TopLayer->isLast());
return create<SimpleReturnedValueConstructionContext>(C, RS);
}
llvm_unreachable("Unexpected construction context with statement!");
} else if (const CXXCtorInitializer *I = TopLayer->getTriggerInit()) {
assert(TopLayer->isLast());
auto *CC =
C.getAllocator().Allocate<ConstructorInitializerConstructionContext>();
return new (CC) ConstructorInitializerConstructionContext(I);
return create<ConstructorInitializerConstructionContext>(C, I);
}
llvm_unreachable("Unexpected construction context!");
}