summaryrefslogtreecommitdiffstats
path: root/clang/lib/Analysis/ConstructionContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Analysis/ConstructionContext.cpp')
-rw-r--r--clang/lib/Analysis/ConstructionContext.cpp92
1 files changed, 92 insertions, 0 deletions
diff --git a/clang/lib/Analysis/ConstructionContext.cpp b/clang/lib/Analysis/ConstructionContext.cpp
new file mode 100644
index 00000000000..aea329b1fea
--- /dev/null
+++ b/clang/lib/Analysis/ConstructionContext.cpp
@@ -0,0 +1,92 @@
+//===- ConstructionContext.cpp - CFG constructor information --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ConstructionContext class and its sub-classes,
+// which represent various different ways of constructing C++ objects
+// with the additional information the users may want to know about
+// the constructor.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/ConstructionContext.h"
+
+using namespace clang;
+
+const ConstructionContextLayer *
+ConstructionContextLayer::create(BumpVectorContext &C, TriggerTy Trigger,
+ const ConstructionContextLayer *Parent) {
+ ConstructionContextLayer *CC =
+ C.getAllocator().Allocate<ConstructionContextLayer>();
+ return new (CC) ConstructionContextLayer(Trigger, Parent);
+}
+
+bool ConstructionContextLayer::isStrictlyMoreSpecificThan(
+ const ConstructionContextLayer *Other) const {
+ const ConstructionContextLayer *Self = this;
+ while (true) {
+ if (!Other)
+ return Self;
+ if (!Self || !Self->isSameLayer(Other))
+ return false;
+ Self = Self->getParent();
+ Other = Other->getParent();
+ }
+ llvm_unreachable("The above loop can only be terminated via return!");
+}
+
+const ConstructionContext *ConstructionContext::createFromLayers(
+ BumpVectorContext &C, const ConstructionContextLayer *TopLayer) {
+ // Before this point all we've had was a stockpile of arbitrary layers.
+ // Now validate that it is shaped as one of the finite amount of expected
+ // patterns.
+ 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)) {
+ assert(TopLayer->isLast());
+ auto *CC =
+ C.getAllocator().Allocate<NewAllocatedObjectConstructionContext>();
+ return new (CC) NewAllocatedObjectConstructionContext(NE);
+ } else if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(S)) {
+ const MaterializeTemporaryExpr *MTE = nullptr;
+ assert(BTE->getType().getCanonicalType()
+ ->getAsCXXRecordDecl()->hasNonTrivialDestructor());
+ // For temporaries with destructors, there may or may not be
+ // lifetime extension on the parent layer.
+ if (const ConstructionContextLayer *ParentLayer = TopLayer->getParent()) {
+ assert(ParentLayer->isLast());
+ MTE = cast<MaterializeTemporaryExpr>(ParentLayer->getTriggerStmt());
+ }
+ auto *CC =
+ C.getAllocator().Allocate<TemporaryObjectConstructionContext>();
+ return new (CC) TemporaryObjectConstructionContext(BTE, MTE);
+ } else if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(S)) {
+ assert(MTE->getType().getCanonicalType()
+ ->getAsCXXRecordDecl()->hasTrivialDestructor());
+ 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<ReturnedValueConstructionContext>();
+ return new (CC) ReturnedValueConstructionContext(RS);
+ }
+ } else if (const CXXCtorInitializer *I = TopLayer->getTriggerInit()) {
+ assert(TopLayer->isLast());
+ auto *CC =
+ C.getAllocator().Allocate<ConstructorInitializerConstructionContext>();
+ return new (CC) ConstructorInitializerConstructionContext(I);
+ }
+ llvm_unreachable("Unexpected construction context!");
+}
OpenPOWER on IntegriCloud