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 /// Represents a single point (AST node) in the program that requires attention
26 /// during construction of an object. ConstructionContext would be represented
27 /// as a list of such items.
28 class ConstructionContextItem {
35 TemporaryDestructorKind,
37 ElidableConstructorKind,
39 STATEMENT_WITH_INDEX_KIND_BEGIN=ArgumentKind,
40 STATEMENT_WITH_INDEX_KIND_END=ArgumentKind,
41 STATEMENT_KIND_BEGIN = VariableKind,
42 STATEMENT_KIND_END = ArgumentKind,
44 INITIALIZER_KIND_BEGIN=InitializerKind,
45 INITIALIZER_KIND_END=InitializerKind
48 LLVM_DUMP_METHOD static StringRef getKindAsString(ItemKind K) {
50 case VariableKind: return "construct into local variable";
51 case NewAllocatorKind: return "construct into new-allocator";
52 case ReturnKind: return "construct into return address";
53 case MaterializationKind: return "materialize temporary";
54 case TemporaryDestructorKind: return "destroy temporary";
55 case ElidedDestructorKind: return "elide destructor";
56 case ElidableConstructorKind: return "elide constructor";
57 case ArgumentKind: return "construct into argument";
58 case InitializerKind: return "construct into member variable";
60 llvm_unreachable("Unknown ItemKind");
64 const void *const Data;
66 const unsigned Index = 0;
68 bool hasStatement() const {
69 return Kind >= STATEMENT_KIND_BEGIN &&
70 Kind <= STATEMENT_KIND_END;
73 bool hasIndex() const {
74 return Kind >= STATEMENT_WITH_INDEX_KIND_BEGIN &&
75 Kind >= STATEMENT_WITH_INDEX_KIND_END;
78 bool hasInitializer() const {
79 return Kind >= INITIALIZER_KIND_BEGIN &&
80 Kind <= INITIALIZER_KIND_END;
84 // ConstructionContextItem should be simple enough so that it was easy to
85 // re-construct it from the AST node it captures. For that reason we provide
86 // simple implicit conversions from all sorts of supported AST nodes.
87 ConstructionContextItem(const DeclStmt *DS)
88 : Data(DS), Kind(VariableKind) {}
90 ConstructionContextItem(const CXXNewExpr *NE)
91 : Data(NE), Kind(NewAllocatorKind) {}
93 ConstructionContextItem(const ReturnStmt *RS)
94 : Data(RS), Kind(ReturnKind) {}
96 ConstructionContextItem(const MaterializeTemporaryExpr *MTE)
97 : Data(MTE), Kind(MaterializationKind) {}
99 ConstructionContextItem(const CXXBindTemporaryExpr *BTE,
100 bool IsElided = false)
102 Kind(IsElided ? ElidedDestructorKind : TemporaryDestructorKind) {}
104 ConstructionContextItem(const CXXConstructExpr *CE)
105 : Data(CE), Kind(ElidableConstructorKind) {}
107 ConstructionContextItem(const CallExpr *CE, unsigned Index)
108 : Data(CE), Kind(ArgumentKind), Index(Index) {}
110 ConstructionContextItem(const CXXConstructExpr *CE, unsigned Index)
111 : Data(CE), Kind(ArgumentKind), Index(Index) {}
113 ConstructionContextItem(const ObjCMessageExpr *ME, unsigned Index)
114 : Data(ME), Kind(ArgumentKind), Index(Index) {}
116 // A polymorphic version of the previous calls with dynamic type check.
117 ConstructionContextItem(const Expr *E, unsigned Index)
118 : Data(E), Kind(ArgumentKind), Index(Index) {
119 assert(isa<CallExpr>(E) || isa<CXXConstructExpr>(E) ||
120 isa<ObjCMessageExpr>(E));
123 ConstructionContextItem(const CXXCtorInitializer *Init)
124 : Data(Init), Kind(InitializerKind), Index(0) {}
126 ItemKind getKind() const { return Kind; }
128 LLVM_DUMP_METHOD StringRef getKindAsString() const {
129 return getKindAsString(getKind());
132 /// The construction site - the statement that triggered the construction
133 /// for one of its parts. For instance, stack variable declaration statement
134 /// triggers construction of itself or its elements if it's an array,
135 /// new-expression triggers construction of the newly allocated object(s).
136 const Stmt *getStmt() const {
137 assert(hasStatement());
138 return static_cast<const Stmt *>(Data);
141 const Stmt *getStmtOrNull() const {
142 return hasStatement() ? getStmt() : nullptr;
145 /// The construction site is not necessarily a statement. It may also be a
146 /// CXXCtorInitializer, which means that a member variable is being
147 /// constructed during initialization of the object that contains it.
148 const CXXCtorInitializer *getCXXCtorInitializer() const {
149 assert(hasInitializer());
150 return static_cast<const CXXCtorInitializer *>(Data);
153 /// If a single trigger statement triggers multiple constructors, they are
154 /// usually being enumerated. This covers function argument constructors
155 /// triggered by a call-expression and items in an initializer list triggered
156 /// by an init-list-expression.
157 unsigned getIndex() const {
158 // This is a fairly specific request. Let's make sure the user knows
164 void Profile(llvm::FoldingSetNodeID &ID) const {
167 ID.AddInteger(Index);
170 bool operator==(const ConstructionContextItem &Other) const {
171 // For most kinds the Index comparison is trivially true, but
172 // checking kind separately doesn't seem to be less expensive
173 // than checking Index. Same in operator<().
174 return std::make_tuple(Data, Kind, Index) ==
175 std::make_tuple(Other.Data, Other.Kind, Other.Index);
178 bool operator<(const ConstructionContextItem &Other) const {
179 return std::make_tuple(Data, Kind, Index) <
180 std::make_tuple(Other.Data, Other.Kind, Other.Index);
184 /// Construction context can be seen as a linked list of multiple layers.
185 /// Sometimes a single trigger is not enough to describe the construction
186 /// site. That's what causing us to have a chain of "partial" construction
187 /// context layers. Some examples:
188 /// - A constructor within in an aggregate initializer list within a variable
189 /// would have a construction context of the initializer list with
190 /// the parent construction context of a variable.
191 /// - A constructor for a temporary that needs to be both destroyed
192 /// and materialized into an elidable copy constructor would have a
193 /// construction context of a CXXBindTemporaryExpr with the parent
194 /// construction context of a MaterializeTemproraryExpr.
195 /// Not all of these are currently supported.
196 /// Layers are created gradually while traversing the AST, and layers that
197 /// represent the outmost AST nodes are built first, while the node that
198 /// immediately contains the constructor would be built last and capture the
199 /// previous layers as its parents. Construction context captures the last layer
200 /// (which has links to the previous layers) and classifies the seemingly
201 /// arbitrary chain of layers into one of the possible ways of constructing
202 /// an object in C++ for user-friendly experience.
203 class ConstructionContextLayer {
204 const ConstructionContextLayer *Parent = nullptr;
205 ConstructionContextItem Item;
207 ConstructionContextLayer(ConstructionContextItem Item,
208 const ConstructionContextLayer *Parent)
209 : Parent(Parent), Item(Item) {}
212 static const ConstructionContextLayer *
213 create(BumpVectorContext &C, const ConstructionContextItem &Item,
214 const ConstructionContextLayer *Parent = nullptr);
216 const ConstructionContextItem &getItem() const { return Item; }
217 const ConstructionContextLayer *getParent() const { return Parent; }
218 bool isLast() const { return !Parent; }
220 /// See if Other is a proper initial segment of this construction context
221 /// in terms of the parent chain - i.e. a few first parents coincide and
222 /// then the other context terminates but our context goes further - i.e.,
223 /// we are providing the same context that the other context provides,
224 /// and a bit more above that.
225 bool isStrictlyMoreSpecificThan(const ConstructionContextLayer *Other) const;
229 /// ConstructionContext's subclasses describe different ways of constructing
230 /// an object in C++. The context re-captures the essential parent AST nodes
231 /// of the CXXConstructExpr it is assigned to and presents these nodes
232 /// through easy-to-understand accessor methods.
233 class ConstructionContext {
237 CXX17ElidedCopyVariableKind,
238 VARIABLE_BEGIN = SimpleVariableKind,
239 VARIABLE_END = CXX17ElidedCopyVariableKind,
240 SimpleConstructorInitializerKind,
241 CXX17ElidedCopyConstructorInitializerKind,
242 INITIALIZER_BEGIN = SimpleConstructorInitializerKind,
243 INITIALIZER_END = CXX17ElidedCopyConstructorInitializerKind,
244 NewAllocatedObjectKind,
245 SimpleTemporaryObjectKind,
246 ElidedTemporaryObjectKind,
247 TEMPORARY_BEGIN = SimpleTemporaryObjectKind,
248 TEMPORARY_END = ElidedTemporaryObjectKind,
249 SimpleReturnedValueKind,
250 CXX17ElidedCopyReturnedValueKind,
251 RETURNED_VALUE_BEGIN = SimpleReturnedValueKind,
252 RETURNED_VALUE_END = CXX17ElidedCopyReturnedValueKind,
259 // Do not make public! These need to only be constructed
260 // via createFromLayers().
261 explicit ConstructionContext(Kind K) : K(K) {}
264 // A helper function for constructing an instance into a bump vector context.
265 template <typename T, typename... ArgTypes>
266 static T *create(BumpVectorContext &C, ArgTypes... Args) {
267 auto *CC = C.getAllocator().Allocate<T>();
268 return new (CC) T(Args...);
271 // A sub-routine of createFromLayers() that deals with temporary objects
272 // that need to be materialized. The BTE argument is for the situation when
273 // the object also needs to be bound for destruction.
274 static const ConstructionContext *createMaterializedTemporaryFromLayers(
275 BumpVectorContext &C, const MaterializeTemporaryExpr *MTE,
276 const CXXBindTemporaryExpr *BTE,
277 const ConstructionContextLayer *ParentLayer);
279 // A sub-routine of createFromLayers() that deals with temporary objects
280 // that need to be bound for destruction. Automatically finds out if the
281 // object also needs to be materialized and delegates to
282 // createMaterializedTemporaryFromLayers() if necessary.
283 static const ConstructionContext *
284 createBoundTemporaryFromLayers(
285 BumpVectorContext &C, const CXXBindTemporaryExpr *BTE,
286 const ConstructionContextLayer *ParentLayer);
289 /// Consume the construction context layer, together with its parent layers,
290 /// and wrap it up into a complete construction context. May return null
291 /// if layers do not form any supported construction context.
292 static const ConstructionContext *
293 createFromLayers(BumpVectorContext &C,
294 const ConstructionContextLayer *TopLayer);
296 Kind getKind() const { return K; }
299 /// An abstract base class for local variable constructors.
300 class VariableConstructionContext : public ConstructionContext {
304 VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS)
305 : ConstructionContext(K), DS(DS) {
306 assert(classof(this));
311 const DeclStmt *getDeclStmt() const { return DS; }
313 static bool classof(const ConstructionContext *CC) {
314 return CC->getKind() >= VARIABLE_BEGIN &&
315 CC->getKind() <= VARIABLE_END;
319 /// Represents construction into a simple local variable, eg. T var(123);.
320 /// If a variable has an initializer, eg. T var = makeT();, then the final
321 /// elidable copy-constructor from makeT() into var would also be a simple
322 /// variable constructor handled by this class.
323 class SimpleVariableConstructionContext : public VariableConstructionContext {
324 friend class ConstructionContext; // Allows to create<>() itself.
326 explicit SimpleVariableConstructionContext(const DeclStmt *DS)
327 : VariableConstructionContext(ConstructionContext::SimpleVariableKind,
331 static bool classof(const ConstructionContext *CC) {
332 return CC->getKind() == SimpleVariableKind;
336 /// Represents construction into a simple variable with an initializer syntax,
337 /// with a single constructor, eg. T var = makeT();. Such construction context
338 /// may only appear in C++17 because previously it was split into a temporary
339 /// object constructor and an elidable simple variable copy-constructor and
340 /// we were producing separate construction contexts for these constructors.
341 /// In C++17 we have a single construction context that combines both.
342 /// Note that if the object has trivial destructor, then this code is
343 /// indistinguishable from a simple variable constructor on the AST level;
344 /// in this case we provide a simple variable construction context.
345 class CXX17ElidedCopyVariableConstructionContext
346 : public VariableConstructionContext {
347 const CXXBindTemporaryExpr *BTE;
349 friend class ConstructionContext; // Allows to create<>() itself.
351 explicit CXX17ElidedCopyVariableConstructionContext(
352 const DeclStmt *DS, const CXXBindTemporaryExpr *BTE)
353 : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) {
358 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
360 static bool classof(const ConstructionContext *CC) {
361 return CC->getKind() == CXX17ElidedCopyVariableKind;
365 // An abstract base class for constructor-initializer-based constructors.
366 class ConstructorInitializerConstructionContext : public ConstructionContext {
367 const CXXCtorInitializer *I;
370 explicit ConstructorInitializerConstructionContext(
371 ConstructionContext::Kind K, const CXXCtorInitializer *I)
372 : ConstructionContext(K), I(I) {
373 assert(classof(this));
378 const CXXCtorInitializer *getCXXCtorInitializer() const { return I; }
380 static bool classof(const ConstructionContext *CC) {
381 return CC->getKind() >= INITIALIZER_BEGIN &&
382 CC->getKind() <= INITIALIZER_END;
386 /// Represents construction into a field or a base class within a bigger object
387 /// via a constructor initializer, eg. T(): field(123) { ... }.
388 class SimpleConstructorInitializerConstructionContext
389 : public ConstructorInitializerConstructionContext {
390 friend class ConstructionContext; // Allows to create<>() itself.
392 explicit SimpleConstructorInitializerConstructionContext(
393 const CXXCtorInitializer *I)
394 : ConstructorInitializerConstructionContext(
395 ConstructionContext::SimpleConstructorInitializerKind, I) {}
398 static bool classof(const ConstructionContext *CC) {
399 return CC->getKind() == SimpleConstructorInitializerKind;
403 /// Represents construction into a field or a base class within a bigger object
404 /// via a constructor initializer, with a single constructor, eg.
405 /// T(): field(Field(123)) { ... }. Such construction context may only appear
406 /// in C++17 because previously it was split into a temporary object constructor
407 /// and an elidable simple constructor-initializer copy-constructor and we were
408 /// producing separate construction contexts for these constructors. In C++17
409 /// we have a single construction context that combines both. Note that if the
410 /// object has trivial destructor, then this code is indistinguishable from
411 /// a simple constructor-initializer constructor on the AST level; in this case
412 /// we provide a simple constructor-initializer construction context.
413 class CXX17ElidedCopyConstructorInitializerConstructionContext
414 : public ConstructorInitializerConstructionContext {
415 const CXXBindTemporaryExpr *BTE;
417 friend class ConstructionContext; // Allows to create<>() itself.
419 explicit CXX17ElidedCopyConstructorInitializerConstructionContext(
420 const CXXCtorInitializer *I, const CXXBindTemporaryExpr *BTE)
421 : ConstructorInitializerConstructionContext(
422 CXX17ElidedCopyConstructorInitializerKind, I),
428 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
430 static bool classof(const ConstructionContext *CC) {
431 return CC->getKind() == CXX17ElidedCopyConstructorInitializerKind;
435 /// Represents immediate initialization of memory allocated by operator new,
437 class NewAllocatedObjectConstructionContext : public ConstructionContext {
438 const CXXNewExpr *NE;
440 friend class ConstructionContext; // Allows to create<>() itself.
442 explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE)
443 : ConstructionContext(ConstructionContext::NewAllocatedObjectKind),
449 const CXXNewExpr *getCXXNewExpr() const { return NE; }
451 static bool classof(const ConstructionContext *CC) {
452 return CC->getKind() == NewAllocatedObjectKind;
456 /// Represents a temporary object, eg. T(123), that does not immediately cross
457 /// function boundaries "by value"; constructors that construct function
458 /// value-type arguments or values that are immediately returned from the
459 /// function that returns a value receive separate construction context kinds.
460 class TemporaryObjectConstructionContext : public ConstructionContext {
461 const CXXBindTemporaryExpr *BTE;
462 const MaterializeTemporaryExpr *MTE;
465 explicit TemporaryObjectConstructionContext(
466 ConstructionContext::Kind K, const CXXBindTemporaryExpr *BTE,
467 const MaterializeTemporaryExpr *MTE)
468 : ConstructionContext(K), BTE(BTE), MTE(MTE) {
469 // Both BTE and MTE can be null here, all combinations possible.
470 // Even though for now at least one should be non-null, we simply haven't
471 // implemented the other case yet (this would be a temporary in the middle
472 // of nowhere that doesn't have a non-trivial destructor).
476 /// CXXBindTemporaryExpr here is non-null as long as the temporary has
477 /// a non-trivial destructor.
478 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const {
482 /// MaterializeTemporaryExpr is non-null as long as the temporary is actually
483 /// used after construction, eg. by binding to a reference (lifetime
484 /// extension), accessing a field, calling a method, or passing it into
485 /// a function (an elidable copy or move constructor would be a common
486 /// example) by reference.
487 const MaterializeTemporaryExpr *getMaterializedTemporaryExpr() const {
491 static bool classof(const ConstructionContext *CC) {
492 return CC->getKind() >= TEMPORARY_BEGIN && CC->getKind() <= TEMPORARY_END;
496 /// Represents a temporary object that is not constructed for the purpose of
497 /// being immediately copied/moved by an elidable copy/move-constructor.
498 /// This includes temporary objects "in the middle of nowhere" like T(123) and
499 /// lifetime-extended temporaries.
500 class SimpleTemporaryObjectConstructionContext
501 : public TemporaryObjectConstructionContext {
502 friend class ConstructionContext; // Allows to create<>() itself.
504 explicit SimpleTemporaryObjectConstructionContext(
505 const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE)
506 : TemporaryObjectConstructionContext(
507 ConstructionContext::SimpleTemporaryObjectKind, BTE, MTE) {}
510 static bool classof(const ConstructionContext *CC) {
511 return CC->getKind() == SimpleTemporaryObjectKind;
515 /// Represents a temporary object that is constructed for the sole purpose
516 /// of being immediately copied by an elidable copy/move constructor.
517 /// For example, T t = T(123); includes a temporary T(123) that is immediately
518 /// copied to variable t. In such cases the elidable copy can (but not
519 /// necessarily should) be omitted ("elided") accodring to the rules of the
520 /// language; the constructor would then construct variable t directly.
521 /// This construction context contains information of the elidable constructor
522 /// and its respective construction context.
523 class ElidedTemporaryObjectConstructionContext
524 : public TemporaryObjectConstructionContext {
525 const CXXConstructExpr *ElidedCE;
526 const ConstructionContext *ElidedCC;
528 friend class ConstructionContext; // Allows to create<>() itself.
530 explicit ElidedTemporaryObjectConstructionContext(
531 const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE,
532 const CXXConstructExpr *ElidedCE, const ConstructionContext *ElidedCC)
533 : TemporaryObjectConstructionContext(
534 ConstructionContext::ElidedTemporaryObjectKind, BTE, MTE),
535 ElidedCE(ElidedCE), ElidedCC(ElidedCC) {
536 // Elided constructor and its context should be either both specified
537 // or both unspecified. In the former case, the constructor must be
539 assert(ElidedCE && ElidedCE->isElidable() && ElidedCC);
543 const CXXConstructExpr *getConstructorAfterElision() const {
547 const ConstructionContext *getConstructionContextAfterElision() const {
551 static bool classof(const ConstructionContext *CC) {
552 return CC->getKind() == ElidedTemporaryObjectKind;
556 class ReturnedValueConstructionContext : public ConstructionContext {
557 const ReturnStmt *RS;
560 explicit ReturnedValueConstructionContext(ConstructionContext::Kind K,
561 const ReturnStmt *RS)
562 : ConstructionContext(K), RS(RS) {
563 assert(classof(this));
568 const ReturnStmt *getReturnStmt() const { return RS; }
570 static bool classof(const ConstructionContext *CC) {
571 return CC->getKind() >= RETURNED_VALUE_BEGIN &&
572 CC->getKind() <= RETURNED_VALUE_END;
576 /// Represents a temporary object that is being immediately returned from a
577 /// function by value, eg. return t; or return T(123);. In this case there is
578 /// always going to be a constructor at the return site. However, the usual
579 /// temporary-related bureaucracy (CXXBindTemporaryExpr,
580 /// MaterializeTemporaryExpr) is normally located in the caller function's AST.
581 class SimpleReturnedValueConstructionContext
582 : public ReturnedValueConstructionContext {
583 friend class ConstructionContext; // Allows to create<>() itself.
585 explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS)
586 : ReturnedValueConstructionContext(
587 ConstructionContext::SimpleReturnedValueKind, RS) {}
590 static bool classof(const ConstructionContext *CC) {
591 return CC->getKind() == SimpleReturnedValueKind;
595 /// Represents a temporary object that is being immediately returned from a
596 /// function by value, eg. return t; or return T(123); in C++17.
597 /// In C++17 there is not going to be an elidable copy constructor at the
598 /// return site. However, the usual temporary-related bureaucracy (CXXBindTemporaryExpr,
599 /// MaterializeTemporaryExpr) is normally located in the caller function's AST.
600 /// Note that if the object has trivial destructor, then this code is
601 /// indistinguishable from a simple returned value constructor on the AST level;
602 /// in this case we provide a simple returned value construction context.
603 class CXX17ElidedCopyReturnedValueConstructionContext
604 : public ReturnedValueConstructionContext {
605 const CXXBindTemporaryExpr *BTE;
607 friend class ConstructionContext; // Allows to create<>() itself.
609 explicit CXX17ElidedCopyReturnedValueConstructionContext(
610 const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE)
611 : ReturnedValueConstructionContext(
612 ConstructionContext::CXX17ElidedCopyReturnedValueKind, RS),
618 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
620 static bool classof(const ConstructionContext *CC) {
621 return CC->getKind() == CXX17ElidedCopyReturnedValueKind;
625 class ArgumentConstructionContext : public ConstructionContext {
626 const Expr *CE; // The call of which the context is an argument.
627 unsigned Index; // Which argument we're constructing.
628 const CXXBindTemporaryExpr *BTE; // Whether the object needs to be destroyed.
630 friend class ConstructionContext; // Allows to create<>() itself.
632 explicit ArgumentConstructionContext(const Expr *CE, unsigned Index,
633 const CXXBindTemporaryExpr *BTE)
634 : ConstructionContext(ArgumentKind), CE(CE),
635 Index(Index), BTE(BTE) {
636 assert(isa<CallExpr>(CE) || isa<CXXConstructExpr>(CE) ||
637 isa<ObjCMessageExpr>(CE));
642 const Expr *getCallLikeExpr() const { return CE; }
643 unsigned getIndex() const { return Index; }
644 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
646 static bool classof(const ConstructionContext *CC) {
647 return CC->getKind() == ArgumentKind;
651 } // end namespace clang
653 #endif // LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H