[CFG] NFC: Refactor ConstructionContext into a finite set of cases.

ConstructionContext is moved into a separate translation unit and is separated
into multiple classes. The "old" "raw" ConstructionContext is renamed into
ConstructionContextLayer - which corresponds to the idea of building the context
gradually layer-by-layer, but it isn't easy to use in the clients. Once
CXXConstructExpr is reached, layers that we've gathered so far are transformed
into the actual, "new-style" "flat" ConstructionContext, which is put into the
CFGConstructor element and has no layers whatsoever (until it actually needs
them, eg. aggregate initialization). The new-style ConstructionContext is
instead presented as a variety of sub-classes that enumerate different ways of
constructing an object in C++. There are 5 of these supported for now,
which is around a half of what needs to be supported.

The layer-by-layer buildup process is still a little bit weird, but it hides
all the weirdness in one place, that sounds like a good thing.

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

llvm-svn: 326238
diff --git a/clang/lib/Analysis/ConstructionContext.cpp b/clang/lib/Analysis/ConstructionContext.cpp
new file mode 100644
index 0000000..aea329b
--- /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!");
+}