1 //===- ConstructionContext.h - CFG constructor information ------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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
15 //===----------------------------------------------------------------------===//
17 #ifndef LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
18 #define LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
20 #include "clang/Analysis/Support/BumpVector.h"
21 #include "clang/AST/ExprCXX.h"
25 /// Construction context is a linked list of multiple layers. Layers are
26 /// created gradually while traversing the AST, and layers that represent
27 /// the outmost AST nodes are built first, while the node that immediately
28 /// contains the constructor would be built last and capture the previous
29 /// layers as its parents. Construction context captures the last layer
30 /// (which has links to the previous layers) and classifies the seemingly
31 /// arbitrary chain of layers into one of the possible ways of constructing
32 /// an object in C++ for user-friendly experience.
33 class ConstructionContextLayer {
35 typedef llvm::PointerUnion<Stmt *, CXXCtorInitializer *> TriggerTy;
38 /// The construction site - the statement that triggered the construction
39 /// for one of its parts. For instance, stack variable declaration statement
40 /// triggers construction of itself or its elements if it's an array,
41 /// new-expression triggers construction of the newly allocated object(s).
44 /// Sometimes a single trigger is not enough to describe the construction
45 /// site. In this case we'd have a chain of "partial" construction context
48 /// - A constructor within in an aggregate initializer list within a variable
49 /// would have a construction context of the initializer list with
50 /// the parent construction context of a variable.
51 /// - A constructor for a temporary that needs to be both destroyed
52 /// and materialized into an elidable copy constructor would have a
53 /// construction context of a CXXBindTemporaryExpr with the parent
54 /// construction context of a MaterializeTemproraryExpr.
55 /// Not all of these are currently supported.
56 const ConstructionContextLayer *Parent = nullptr;
58 ConstructionContextLayer(TriggerTy Trigger,
59 const ConstructionContextLayer *Parent)
60 : Trigger(Trigger), Parent(Parent) {}
63 static const ConstructionContextLayer *
64 create(BumpVectorContext &C, TriggerTy Trigger,
65 const ConstructionContextLayer *Parent = nullptr);
67 const ConstructionContextLayer *getParent() const { return Parent; }
68 bool isLast() const { return !Parent; }
70 const Stmt *getTriggerStmt() const {
71 return Trigger.dyn_cast<Stmt *>();
74 const CXXCtorInitializer *getTriggerInit() const {
75 return Trigger.dyn_cast<CXXCtorInitializer *>();
78 /// Returns true if these layers are equal as individual layers, even if
79 /// their parents are different.
80 bool isSameLayer(const ConstructionContextLayer *Other) const {
82 return (Trigger == Other->Trigger);
85 /// See if Other is a proper initial segment of this construction context
86 /// in terms of the parent chain - i.e. a few first parents coincide and
87 /// then the other context terminates but our context goes further - i.e.,
88 /// we are providing the same context that the other context provides,
89 /// and a bit more above that.
90 bool isStrictlyMoreSpecificThan(const ConstructionContextLayer *Other) const;
94 /// ConstructionContext's subclasses describe different ways of constructing
95 /// an object in C++. The context re-captures the essential parent AST nodes
96 /// of the CXXConstructExpr it is assigned to and presents these nodes
97 /// through easy-to-understand accessor methods.
98 class ConstructionContext {
102 CXX17ElidedCopyVariableKind,
103 VARIABLE_BEGIN = SimpleVariableKind,
104 VARIABLE_END = CXX17ElidedCopyVariableKind,
105 SimpleConstructorInitializerKind,
106 CXX17ElidedCopyConstructorInitializerKind,
107 INITIALIZER_BEGIN = SimpleConstructorInitializerKind,
108 INITIALIZER_END = CXX17ElidedCopyConstructorInitializerKind,
109 NewAllocatedObjectKind,
110 SimpleTemporaryObjectKind,
111 ElidedTemporaryObjectKind,
112 TEMPORARY_BEGIN = SimpleTemporaryObjectKind,
113 TEMPORARY_END = ElidedTemporaryObjectKind,
114 SimpleReturnedValueKind,
115 CXX17ElidedCopyReturnedValueKind,
116 RETURNED_VALUE_BEGIN = SimpleReturnedValueKind,
117 RETURNED_VALUE_END = CXX17ElidedCopyReturnedValueKind
123 // Do not make public! These need to only be constructed
124 // via createFromLayers().
125 explicit ConstructionContext(Kind K) : K(K) {}
128 // A helper function for constructing an instance into a bump vector context.
129 template <typename T, typename... ArgTypes>
130 static T *create(BumpVectorContext &C, ArgTypes... Args) {
131 auto *CC = C.getAllocator().Allocate<T>();
132 return new (CC) T(Args...);
136 /// Consume the construction context layer, together with its parent layers,
137 /// and wrap it up into a complete construction context. May return null
138 /// if layers do not form any supported construction context.
139 static const ConstructionContext *
140 createFromLayers(BumpVectorContext &C,
141 const ConstructionContextLayer *TopLayer);
143 Kind getKind() const { return K; }
146 /// An abstract base class for local variable constructors.
147 class VariableConstructionContext : public ConstructionContext {
151 VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS)
152 : ConstructionContext(K), DS(DS) {
153 assert(classof(this));
158 const DeclStmt *getDeclStmt() const { return DS; }
160 static bool classof(const ConstructionContext *CC) {
161 return CC->getKind() >= VARIABLE_BEGIN &&
162 CC->getKind() <= VARIABLE_END;
166 /// Represents construction into a simple local variable, eg. T var(123);.
167 /// If a variable has an initializer, eg. T var = makeT();, then the final
168 /// elidable copy-constructor from makeT() into var would also be a simple
169 /// variable constructor handled by this class.
170 class SimpleVariableConstructionContext : public VariableConstructionContext {
171 friend class ConstructionContext; // Allows to create<>() itself.
173 explicit SimpleVariableConstructionContext(const DeclStmt *DS)
174 : VariableConstructionContext(ConstructionContext::SimpleVariableKind,
178 static bool classof(const ConstructionContext *CC) {
179 return CC->getKind() == SimpleVariableKind;
183 /// Represents construction into a simple variable with an initializer syntax,
184 /// with a single constructor, eg. T var = makeT();. Such construction context
185 /// may only appear in C++17 because previously it was split into a temporary
186 /// object constructor and an elidable simple variable copy-constructor and
187 /// we were producing separate construction contexts for these constructors.
188 /// In C++17 we have a single construction context that combines both.
189 /// Note that if the object has trivial destructor, then this code is
190 /// indistinguishable from a simple variable constructor on the AST level;
191 /// in this case we provide a simple variable construction context.
192 class CXX17ElidedCopyVariableConstructionContext
193 : public VariableConstructionContext {
194 const CXXBindTemporaryExpr *BTE;
196 friend class ConstructionContext; // Allows to create<>() itself.
198 explicit CXX17ElidedCopyVariableConstructionContext(
199 const DeclStmt *DS, const CXXBindTemporaryExpr *BTE)
200 : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) {
205 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
207 static bool classof(const ConstructionContext *CC) {
208 return CC->getKind() == CXX17ElidedCopyVariableKind;
212 // An abstract base class for constructor-initializer-based constructors.
213 class ConstructorInitializerConstructionContext : public ConstructionContext {
214 const CXXCtorInitializer *I;
217 explicit ConstructorInitializerConstructionContext(
218 ConstructionContext::Kind K, const CXXCtorInitializer *I)
219 : ConstructionContext(K), I(I) {
220 assert(classof(this));
225 const CXXCtorInitializer *getCXXCtorInitializer() const { return I; }
227 static bool classof(const ConstructionContext *CC) {
228 return CC->getKind() >= INITIALIZER_BEGIN &&
229 CC->getKind() <= INITIALIZER_END;
233 /// Represents construction into a field or a base class within a bigger object
234 /// via a constructor initializer, eg. T(): field(123) { ... }.
235 class SimpleConstructorInitializerConstructionContext
236 : public ConstructorInitializerConstructionContext {
237 friend class ConstructionContext; // Allows to create<>() itself.
239 explicit SimpleConstructorInitializerConstructionContext(
240 const CXXCtorInitializer *I)
241 : ConstructorInitializerConstructionContext(
242 ConstructionContext::SimpleConstructorInitializerKind, I) {}
245 static bool classof(const ConstructionContext *CC) {
246 return CC->getKind() == SimpleConstructorInitializerKind;
250 /// Represents construction into a field or a base class within a bigger object
251 /// via a constructor initializer, with a single constructor, eg.
252 /// T(): field(Field(123)) { ... }. Such construction context may only appear
253 /// in C++17 because previously it was split into a temporary object constructor
254 /// and an elidable simple constructor-initializer copy-constructor and we were
255 /// producing separate construction contexts for these constructors. In C++17
256 /// we have a single construction context that combines both. Note that if the
257 /// object has trivial destructor, then this code is indistinguishable from
258 /// a simple constructor-initializer constructor on the AST level; in this case
259 /// we provide a simple constructor-initializer construction context.
260 class CXX17ElidedCopyConstructorInitializerConstructionContext
261 : public ConstructorInitializerConstructionContext {
262 const CXXBindTemporaryExpr *BTE;
264 friend class ConstructionContext; // Allows to create<>() itself.
266 explicit CXX17ElidedCopyConstructorInitializerConstructionContext(
267 const CXXCtorInitializer *I, const CXXBindTemporaryExpr *BTE)
268 : ConstructorInitializerConstructionContext(
269 CXX17ElidedCopyConstructorInitializerKind, I),
275 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
277 static bool classof(const ConstructionContext *CC) {
278 return CC->getKind() == CXX17ElidedCopyConstructorInitializerKind;
282 /// Represents immediate initialization of memory allocated by operator new,
284 class NewAllocatedObjectConstructionContext : public ConstructionContext {
285 const CXXNewExpr *NE;
287 friend class ConstructionContext; // Allows to create<>() itself.
289 explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE)
290 : ConstructionContext(ConstructionContext::NewAllocatedObjectKind),
296 const CXXNewExpr *getCXXNewExpr() const { return NE; }
298 static bool classof(const ConstructionContext *CC) {
299 return CC->getKind() == NewAllocatedObjectKind;
303 /// Represents a temporary object, eg. T(123), that does not immediately cross
304 /// function boundaries "by value"; constructors that construct function
305 /// value-type arguments or values that are immediately returned from the
306 /// function that returns a value receive separate construction context kinds.
307 class TemporaryObjectConstructionContext : public ConstructionContext {
308 const CXXBindTemporaryExpr *BTE;
309 const MaterializeTemporaryExpr *MTE;
312 explicit TemporaryObjectConstructionContext(
313 ConstructionContext::Kind K, const CXXBindTemporaryExpr *BTE,
314 const MaterializeTemporaryExpr *MTE)
315 : ConstructionContext(K), BTE(BTE), MTE(MTE) {
316 // Both BTE and MTE can be null here, all combinations possible.
317 // Even though for now at least one should be non-null, we simply haven't
318 // implemented the other case yet (this would be a temporary in the middle
319 // of nowhere that doesn't have a non-trivial destructor).
323 /// CXXBindTemporaryExpr here is non-null as long as the temporary has
324 /// a non-trivial destructor.
325 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const {
329 /// MaterializeTemporaryExpr is non-null as long as the temporary is actually
330 /// used after construction, eg. by binding to a reference (lifetime
331 /// extension), accessing a field, calling a method, or passing it into
332 /// a function (an elidable copy or move constructor would be a common
333 /// example) by reference.
334 const MaterializeTemporaryExpr *getMaterializedTemporaryExpr() const {
338 static bool classof(const ConstructionContext *CC) {
339 return CC->getKind() >= TEMPORARY_BEGIN && CC->getKind() <= TEMPORARY_END;
343 /// Represents a temporary object that is not constructed for the purpose of
344 /// being immediately copied/moved by an elidable copy/move-constructor.
345 /// This includes temporary objects "in the middle of nowhere" like T(123) and
346 /// lifetime-extended temporaries.
347 class SimpleTemporaryObjectConstructionContext
348 : public TemporaryObjectConstructionContext {
349 friend class ConstructionContext; // Allows to create<>() itself.
351 explicit SimpleTemporaryObjectConstructionContext(
352 const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE)
353 : TemporaryObjectConstructionContext(
354 ConstructionContext::SimpleTemporaryObjectKind, BTE, MTE) {}
357 static bool classof(const ConstructionContext *CC) {
358 return CC->getKind() == SimpleTemporaryObjectKind;
362 /// Represents a temporary object that is constructed for the sole purpose
363 /// of being immediately copied by an elidable copy/move constructor.
364 /// For example, T t = T(123); includes a temporary T(123) that is immediately
365 /// copied to variable t. In such cases the elidable copy can (but not
366 /// necessarily should) be omitted ("elided") accodring to the rules of the
367 /// language; the constructor would then construct variable t directly.
368 /// This construction context contains information of the elidable constructor
369 /// and its respective construction context.
370 class ElidedTemporaryObjectConstructionContext
371 : public TemporaryObjectConstructionContext {
372 const CXXConstructExpr *ElidedCE;
373 const ConstructionContext *ElidedCC;
375 friend class ConstructionContext; // Allows to create<>() itself.
377 explicit ElidedTemporaryObjectConstructionContext(
378 const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE,
379 const CXXConstructExpr *ElidedCE, const ConstructionContext *ElidedCC)
380 : TemporaryObjectConstructionContext(
381 ConstructionContext::ElidedTemporaryObjectKind, BTE, MTE),
382 ElidedCE(ElidedCE), ElidedCC(ElidedCC) {
383 // Elided constructor and its context should be either both specified
384 // or both unspecified. In the former case, the constructor must be
386 assert(ElidedCE && ElidedCE->isElidable() && ElidedCC);
390 const CXXConstructExpr *getConstructorAfterElision() const {
394 const ConstructionContext *getConstructionContextAfterElision() const {
398 static bool classof(const ConstructionContext *CC) {
399 return CC->getKind() == ElidedTemporaryObjectKind;
403 class ReturnedValueConstructionContext : public ConstructionContext {
404 const ReturnStmt *RS;
407 explicit ReturnedValueConstructionContext(ConstructionContext::Kind K,
408 const ReturnStmt *RS)
409 : ConstructionContext(K), RS(RS) {
410 assert(classof(this));
415 const ReturnStmt *getReturnStmt() const { return RS; }
417 static bool classof(const ConstructionContext *CC) {
418 return CC->getKind() >= RETURNED_VALUE_BEGIN &&
419 CC->getKind() <= RETURNED_VALUE_END;
423 /// Represents a temporary object that is being immediately returned from a
424 /// function by value, eg. return t; or return T(123);. In this case there is
425 /// always going to be a constructor at the return site. However, the usual
426 /// temporary-related bureaucracy (CXXBindTemporaryExpr,
427 /// MaterializeTemporaryExpr) is normally located in the caller function's AST.
428 class SimpleReturnedValueConstructionContext
429 : public ReturnedValueConstructionContext {
430 friend class ConstructionContext; // Allows to create<>() itself.
432 explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS)
433 : ReturnedValueConstructionContext(
434 ConstructionContext::SimpleReturnedValueKind, RS) {}
437 static bool classof(const ConstructionContext *CC) {
438 return CC->getKind() == SimpleReturnedValueKind;
442 /// Represents a temporary object that is being immediately returned from a
443 /// function by value, eg. return t; or return T(123); in C++17.
444 /// In C++17 there is not going to be an elidable copy constructor at the
445 /// return site. However, the usual temporary-related bureaucracy (CXXBindTemporaryExpr,
446 /// MaterializeTemporaryExpr) is normally located in the caller function's AST.
447 /// Note that if the object has trivial destructor, then this code is
448 /// indistinguishable from a simple returned value constructor on the AST level;
449 /// in this case we provide a simple returned value construction context.
450 class CXX17ElidedCopyReturnedValueConstructionContext
451 : public ReturnedValueConstructionContext {
452 const CXXBindTemporaryExpr *BTE;
454 friend class ConstructionContext; // Allows to create<>() itself.
456 explicit CXX17ElidedCopyReturnedValueConstructionContext(
457 const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE)
458 : ReturnedValueConstructionContext(
459 ConstructionContext::CXX17ElidedCopyReturnedValueKind, RS),
465 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
467 static bool classof(const ConstructionContext *CC) {
468 return CC->getKind() == CXX17ElidedCopyReturnedValueKind;
472 } // end namespace clang
474 #endif // LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H