blob: aea329b1feaa7eb1e2846dbdf80327a6e1c91b27 [file] [log] [blame]
Artem Dergachev40684812018-02-27 20:03:35 +00001//===- ConstructionContext.cpp - CFG constructor information --------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the ConstructionContext class and its sub-classes,
11// which represent various different ways of constructing C++ objects
12// with the additional information the users may want to know about
13// the constructor.
14//
15//===----------------------------------------------------------------------===//
16
17#include "clang/Analysis/ConstructionContext.h"
18
19using namespace clang;
20
21const ConstructionContextLayer *
22ConstructionContextLayer::create(BumpVectorContext &C, TriggerTy Trigger,
23 const ConstructionContextLayer *Parent) {
24 ConstructionContextLayer *CC =
25 C.getAllocator().Allocate<ConstructionContextLayer>();
26 return new (CC) ConstructionContextLayer(Trigger, Parent);
27}
28
29bool ConstructionContextLayer::isStrictlyMoreSpecificThan(
30 const ConstructionContextLayer *Other) const {
31 const ConstructionContextLayer *Self = this;
32 while (true) {
33 if (!Other)
34 return Self;
35 if (!Self || !Self->isSameLayer(Other))
36 return false;
37 Self = Self->getParent();
38 Other = Other->getParent();
39 }
40 llvm_unreachable("The above loop can only be terminated via return!");
41}
42
43const ConstructionContext *ConstructionContext::createFromLayers(
44 BumpVectorContext &C, const ConstructionContextLayer *TopLayer) {
45 // Before this point all we've had was a stockpile of arbitrary layers.
46 // Now validate that it is shaped as one of the finite amount of expected
47 // patterns.
48 if (const Stmt *S = TopLayer->getTriggerStmt()) {
49 if (const auto *DS = dyn_cast<DeclStmt>(S)) {
50 assert(TopLayer->isLast());
51 auto *CC =
52 C.getAllocator().Allocate<SimpleVariableConstructionContext>();
53 return new (CC) SimpleVariableConstructionContext(DS);
54 } else if (const auto *NE = dyn_cast<CXXNewExpr>(S)) {
55 assert(TopLayer->isLast());
56 auto *CC =
57 C.getAllocator().Allocate<NewAllocatedObjectConstructionContext>();
58 return new (CC) NewAllocatedObjectConstructionContext(NE);
59 } else if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(S)) {
60 const MaterializeTemporaryExpr *MTE = nullptr;
61 assert(BTE->getType().getCanonicalType()
62 ->getAsCXXRecordDecl()->hasNonTrivialDestructor());
63 // For temporaries with destructors, there may or may not be
64 // lifetime extension on the parent layer.
65 if (const ConstructionContextLayer *ParentLayer = TopLayer->getParent()) {
66 assert(ParentLayer->isLast());
67 MTE = cast<MaterializeTemporaryExpr>(ParentLayer->getTriggerStmt());
68 }
69 auto *CC =
70 C.getAllocator().Allocate<TemporaryObjectConstructionContext>();
71 return new (CC) TemporaryObjectConstructionContext(BTE, MTE);
72 } else if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(S)) {
73 assert(MTE->getType().getCanonicalType()
74 ->getAsCXXRecordDecl()->hasTrivialDestructor());
75 assert(TopLayer->isLast());
76 auto *CC =
77 C.getAllocator().Allocate<TemporaryObjectConstructionContext>();
78 return new (CC) TemporaryObjectConstructionContext(nullptr, MTE);
79 } else if (const auto *RS = dyn_cast<ReturnStmt>(S)) {
80 assert(TopLayer->isLast());
81 auto *CC =
82 C.getAllocator().Allocate<ReturnedValueConstructionContext>();
83 return new (CC) ReturnedValueConstructionContext(RS);
84 }
85 } else if (const CXXCtorInitializer *I = TopLayer->getTriggerInit()) {
86 assert(TopLayer->isLast());
87 auto *CC =
88 C.getAllocator().Allocate<ConstructorInitializerConstructionContext>();
89 return new (CC) ConstructorInitializerConstructionContext(I);
90 }
91 llvm_unreachable("Unexpected construction context!");
92}