1 //===- 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 
19 using namespace clang;
20 
21 const ConstructionContextLayer *
22 ConstructionContextLayer::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 
29 bool 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 
43 const 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       // If the object requires destruction and is not lifetime-extended,
74       // then it must have a BTE within its MTE.
75       assert(MTE->getType().getCanonicalType()
76                 ->getAsCXXRecordDecl()->hasTrivialDestructor() ||
77              MTE->getStorageDuration() != SD_FullExpression);
78       assert(TopLayer->isLast());
79       auto *CC =
80           C.getAllocator().Allocate<TemporaryObjectConstructionContext>();
81       return new (CC) TemporaryObjectConstructionContext(nullptr, MTE);
82     } else if (const auto *RS = dyn_cast<ReturnStmt>(S)) {
83       assert(TopLayer->isLast());
84       auto *CC =
85           C.getAllocator().Allocate<ReturnedValueConstructionContext>();
86       return new (CC) ReturnedValueConstructionContext(RS);
87     }
88   } else if (const CXXCtorInitializer *I = TopLayer->getTriggerInit()) {
89     assert(TopLayer->isLast());
90     auto *CC =
91         C.getAllocator().Allocate<ConstructorInitializerConstructionContext>();
92     return new (CC) ConstructorInitializerConstructionContext(I);
93   }
94   llvm_unreachable("Unexpected construction context!");
95 }
96