clang  7.0.0svn
ConstructionContext.cpp
Go to the documentation of this file.
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 
18 
19 using namespace clang;
20 
25  C.getAllocator().Allocate<ConstructionContextLayer>();
26  return new (CC) ConstructionContextLayer(Trigger, Parent);
27 }
28 
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 
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  return create<SimpleVariableConstructionContext>(C, DS);
52  }
53  if (const auto *NE = dyn_cast<CXXNewExpr>(S)) {
54  assert(TopLayer->isLast());
55  return create<NewAllocatedObjectConstructionContext>(C, NE);
56  }
57  if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(S)) {
58  const MaterializeTemporaryExpr *MTE = nullptr;
59  assert(BTE->getType().getCanonicalType()
60  ->getAsCXXRecordDecl()->hasNonTrivialDestructor());
61  // For temporaries with destructors, there may or may not be
62  // lifetime extension on the parent layer.
63  if (const ConstructionContextLayer *ParentLayer = TopLayer->getParent()) {
64  assert(ParentLayer->isLast());
65  // C++17 *requires* elision of the constructor at the return site
66  // and at variable/member initialization site, while previous standards
67  // were allowing an optional elidable constructor.
68  // This is the C++17 copy-elided construction into a ctor initializer.
69  if (const CXXCtorInitializer *I = ParentLayer->getTriggerInit()) {
70  return create<
72  I, BTE);
73  }
74  assert(ParentLayer->getTriggerStmt() &&
75  "Non-statement-based layers have been handled above!");
76  // This is the normal, non-C++17 case: a temporary object which has
77  // both destruction and materialization info attached to it in the AST.
78  if ((MTE = dyn_cast<MaterializeTemporaryExpr>(
79  ParentLayer->getTriggerStmt()))) {
80  return create<TemporaryObjectConstructionContext>(C, BTE, MTE);
81  }
82  // This is a constructor into a function argument. Not implemented yet.
83  if (isa<CallExpr>(ParentLayer->getTriggerStmt()))
84  return nullptr;
85  // This is C++17 copy-elided construction into return statement.
86  if (auto *RS = dyn_cast<ReturnStmt>(ParentLayer->getTriggerStmt())) {
87  assert(!RS->getRetValue()->getType().getCanonicalType()
88  ->getAsCXXRecordDecl()->hasTrivialDestructor());
89  return create<CXX17ElidedCopyReturnedValueConstructionContext>(C,
90  RS, BTE);
91  }
92  // This is C++17 copy-elided construction into a simple variable.
93  if (auto *DS = dyn_cast<DeclStmt>(ParentLayer->getTriggerStmt())) {
94  assert(!cast<VarDecl>(DS->getSingleDecl())->getType()
95  .getCanonicalType()->getAsCXXRecordDecl()
96  ->hasTrivialDestructor());
97  return create<CXX17ElidedCopyVariableConstructionContext>(C, DS, BTE);
98  }
99  llvm_unreachable("Unexpected construction context with destructor!");
100  }
101  // A temporary object that doesn't require materialization.
102  return create<TemporaryObjectConstructionContext>(C, BTE, /*MTE=*/nullptr);
103  }
104  if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(S)) {
105  // If the object requires destruction and is not lifetime-extended,
106  // then it must have a BTE within its MTE.
107  // FIXME: This should be an assertion.
108  if (!(MTE->getType().getCanonicalType()
109  ->getAsCXXRecordDecl()->hasTrivialDestructor() ||
110  MTE->getStorageDuration() != SD_FullExpression))
111  return nullptr;
112 
113  assert(TopLayer->isLast());
114  return create<TemporaryObjectConstructionContext>(C, nullptr, MTE);
115  }
116  if (const auto *RS = dyn_cast<ReturnStmt>(S)) {
117  assert(TopLayer->isLast());
118  return create<SimpleReturnedValueConstructionContext>(C, RS);
119  }
120  // This is a constructor into a function argument. Not implemented yet.
121  if (isa<CallExpr>(TopLayer->getTriggerStmt()))
122  return nullptr;
123  llvm_unreachable("Unexpected construction context with statement!");
124  } else if (const CXXCtorInitializer *I = TopLayer->getTriggerInit()) {
125  assert(TopLayer->isLast());
126  return create<SimpleConstructorInitializerConstructionContext>(C, I);
127  }
128  llvm_unreachable("Unexpected construction context!");
129 }
Stmt - This represents one statement.
Definition: Stmt.h:66
bool isSameLayer(const ConstructionContextLayer *Other) const
Returns true if these layers are equal as individual layers, even if their parents are different...
bool isStrictlyMoreSpecificThan(const ConstructionContextLayer *Other) const
See if Other is a proper initial segment of this construction context in terms of the parent chain - ...
Represents a prvalue temporary that is written into memory so that a reference can bind to it...
Definition: ExprCXX.h:4039
llvm::BumpPtrAllocator & getAllocator()
Definition: BumpVector.h:56
const CXXCtorInitializer * getTriggerInit() const
const ConstructionContextLayer * getParent() const
NodeId Parent
Definition: ASTDiff.cpp:192
static const ConstructionContext * createFromLayers(BumpVectorContext &C, const ConstructionContextLayer *TopLayer)
Consume the construction context layer, together with its parent layers, and wrap it up into a comple...
Construction context is a linked list of multiple layers.
Dataflow Directional Tag Classes.
Represents a C++ base or member initializer.
Definition: DeclCXX.h:2238
static const ConstructionContextLayer * create(BumpVectorContext &C, TriggerTy Trigger, const ConstructionContextLayer *Parent=nullptr)
ConstructionContext&#39;s subclasses describe different ways of constructing an object in C++...
Represents construction into a field or a base class within a bigger object via a constructor initial...
Full-expression storage duration (for temporaries).
Definition: Specifiers.h:277
llvm::PointerUnion< Stmt *, CXXCtorInitializer * > TriggerTy