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"
22 #include "clang/AST/ExprObjC.h"
26 /// Represents a single point (AST node) in the program that requires attention
27 /// during construction of an object. ConstructionContext would be represented
28 /// as a list of such items.
29 class ConstructionContextItem {
36 TemporaryDestructorKind,
38 ElidableConstructorKind,
40 STATEMENT_WITH_INDEX_KIND_BEGIN=ArgumentKind,
41 STATEMENT_WITH_INDEX_KIND_END=ArgumentKind,
42 STATEMENT_KIND_BEGIN = VariableKind,
43 STATEMENT_KIND_END = ArgumentKind,
45 INITIALIZER_KIND_BEGIN=InitializerKind,
46 INITIALIZER_KIND_END=InitializerKind
49 LLVM_DUMP_METHOD static StringRef getKindAsString(ItemKind K) {
51 case VariableKind: return "construct into local variable";
52 case NewAllocatorKind: return "construct into new-allocator";
53 case ReturnKind: return "construct into return address";
54 case MaterializationKind: return "materialize temporary";
55 case TemporaryDestructorKind: return "destroy temporary";
56 case ElidedDestructorKind: return "elide destructor";
57 case ElidableConstructorKind: return "elide constructor";
58 case ArgumentKind: return "construct into argument";
59 case InitializerKind: return "construct into member variable";
61 llvm_unreachable("Unknown ItemKind");
65 const void *const Data;
67 const unsigned Index = 0;
69 bool hasStatement() const {
70 return Kind >= STATEMENT_KIND_BEGIN &&
71 Kind <= STATEMENT_KIND_END;
74 bool hasIndex() const {
75 return Kind >= STATEMENT_WITH_INDEX_KIND_BEGIN &&
76 Kind >= STATEMENT_WITH_INDEX_KIND_END;
79 bool hasInitializer() const {
80 return Kind >= INITIALIZER_KIND_BEGIN &&
81 Kind <= INITIALIZER_KIND_END;
85 // ConstructionContextItem should be simple enough so that it was easy to
86 // re-construct it from the AST node it captures. For that reason we provide
87 // simple implicit conversions from all sorts of supported AST nodes.
88 ConstructionContextItem(const DeclStmt *DS)
89 : Data(DS), Kind(VariableKind) {}
91 ConstructionContextItem(const CXXNewExpr *NE)
92 : Data(NE), Kind(NewAllocatorKind) {}
94 ConstructionContextItem(const ReturnStmt *RS)
95 : Data(RS), Kind(ReturnKind) {}
97 ConstructionContextItem(const MaterializeTemporaryExpr *MTE)
98 : Data(MTE), Kind(MaterializationKind) {}
100 ConstructionContextItem(const CXXBindTemporaryExpr *BTE,
101 bool IsElided = false)
103 Kind(IsElided ? ElidedDestructorKind : TemporaryDestructorKind) {}
105 ConstructionContextItem(const CXXConstructExpr *CE)
106 : Data(CE), Kind(ElidableConstructorKind) {}
108 ConstructionContextItem(const CallExpr *CE, unsigned Index)
109 : Data(CE), Kind(ArgumentKind), Index(Index) {}
111 ConstructionContextItem(const CXXConstructExpr *CE, unsigned Index)
112 : Data(CE), Kind(ArgumentKind), Index(Index) {}
114 ConstructionContextItem(const ObjCMessageExpr *ME, unsigned Index)
115 : Data(ME), Kind(ArgumentKind), Index(Index) {}
117 // A polymorphic version of the previous calls with dynamic type check.
118 ConstructionContextItem(const Expr *E, unsigned Index)
119 : Data(E), Kind(ArgumentKind), Index(Index) {
120 assert(isa<CallExpr>(E) || isa<CXXConstructExpr>(E) ||
121 isa<ObjCMessageExpr>(E));
124 ConstructionContextItem(const CXXCtorInitializer *Init)
125 : Data(Init), Kind(InitializerKind), Index(0) {}
127 ItemKind getKind() const { return Kind; }
129 LLVM_DUMP_METHOD StringRef getKindAsString() const {
130 return getKindAsString(getKind());
133 /// The construction site - the statement that triggered the construction
134 /// for one of its parts. For instance, stack variable declaration statement
135 /// triggers construction of itself or its elements if it's an array,
136 /// new-expression triggers construction of the newly allocated object(s).
137 const Stmt *getStmt() const {
138 assert(hasStatement());
139 return static_cast<const Stmt *>(Data);
142 const Stmt *getStmtOrNull() const {
143 return hasStatement() ? getStmt() : nullptr;
146 /// The construction site is not necessarily a statement. It may also be a
147 /// CXXCtorInitializer, which means that a member variable is being
148 /// constructed during initialization of the object that contains it.
149 const CXXCtorInitializer *getCXXCtorInitializer() const {
150 assert(hasInitializer());
151 return static_cast<const CXXCtorInitializer *>(Data);
154 /// If a single trigger statement triggers multiple constructors, they are
155 /// usually being enumerated. This covers function argument constructors
156 /// triggered by a call-expression and items in an initializer list triggered
157 /// by an init-list-expression.
158 unsigned getIndex() const {
159 // This is a fairly specific request. Let's make sure the user knows
165 void Profile(llvm::FoldingSetNodeID &ID) const {
168 ID.AddInteger(Index);
171 bool operator==(const ConstructionContextItem &Other) const {
172 // For most kinds the Index comparison is trivially true, but
173 // checking kind separately doesn't seem to be less expensive
174 // than checking Index. Same in operator<().
175 return std::make_tuple(Data, Kind, Index) ==
176 std::make_tuple(Other.Data, Other.Kind, Other.Index);
179 bool operator<(const ConstructionContextItem &Other) const {
180 return std::make_tuple(Data, Kind, Index) <
181 std::make_tuple(Other.Data, Other.Kind, Other.Index);
185 /// Construction context can be seen as a linked list of multiple layers.
186 /// Sometimes a single trigger is not enough to describe the construction
187 /// site. That's what causing us to have a chain of "partial" construction
188 /// context layers. Some examples:
189 /// - A constructor within in an aggregate initializer list within a variable
190 /// would have a construction context of the initializer list with
191 /// the parent construction context of a variable.
192 /// - A constructor for a temporary that needs to be both destroyed
193 /// and materialized into an elidable copy constructor would have a
194 /// construction context of a CXXBindTemporaryExpr with the parent
195 /// construction context of a MaterializeTemproraryExpr.
196 /// Not all of these are currently supported.
197 /// Layers are created gradually while traversing the AST, and layers that
198 /// represent the outmost AST nodes are built first, while the node that
199 /// immediately contains the constructor would be built last and capture the
200 /// previous layers as its parents. Construction context captures the last layer
201 /// (which has links to the previous layers) and classifies the seemingly
202 /// arbitrary chain of layers into one of the possible ways of constructing
203 /// an object in C++ for user-friendly experience.
204 class ConstructionContextLayer {
205 const ConstructionContextLayer *Parent = nullptr;
206 ConstructionContextItem Item;
208 ConstructionContextLayer(ConstructionContextItem Item,
209 const ConstructionContextLayer *Parent)
210 : Parent(Parent), Item(Item) {}
213 static const ConstructionContextLayer *
214 create(BumpVectorContext &C, const ConstructionContextItem &Item,
215 const ConstructionContextLayer *Parent = nullptr);
217 const ConstructionContextItem &getItem() const { return Item; }
218 const ConstructionContextLayer *getParent() const { return Parent; }
219 bool isLast() const { return !Parent; }
221 /// See if Other is a proper initial segment of this construction context
222 /// in terms of the parent chain - i.e. a few first parents coincide and
223 /// then the other context terminates but our context goes further - i.e.,
224 /// we are providing the same context that the other context provides,
225 /// and a bit more above that.
226 bool isStrictlyMoreSpecificThan(const ConstructionContextLayer *Other) const;
230 /// ConstructionContext's subclasses describe different ways of constructing
231 /// an object in C++. The context re-captures the essential parent AST nodes
232 /// of the CXXConstructExpr it is assigned to and presents these nodes
233 /// through easy-to-understand accessor methods.
234 class ConstructionContext {
238 CXX17ElidedCopyVariableKind,
239 VARIABLE_BEGIN = SimpleVariableKind,
240 VARIABLE_END = CXX17ElidedCopyVariableKind,
241 SimpleConstructorInitializerKind,
242 CXX17ElidedCopyConstructorInitializerKind,
243 INITIALIZER_BEGIN = SimpleConstructorInitializerKind,
244 INITIALIZER_END = CXX17ElidedCopyConstructorInitializerKind,
245 NewAllocatedObjectKind,
246 SimpleTemporaryObjectKind,
247 ElidedTemporaryObjectKind,
248 TEMPORARY_BEGIN = SimpleTemporaryObjectKind,
249 TEMPORARY_END = ElidedTemporaryObjectKind,
250 SimpleReturnedValueKind,
251 CXX17ElidedCopyReturnedValueKind,
252 RETURNED_VALUE_BEGIN = SimpleReturnedValueKind,
253 RETURNED_VALUE_END = CXX17ElidedCopyReturnedValueKind,
260 // Do not make public! These need to only be constructed
261 // via createFromLayers().
262 explicit ConstructionContext(Kind K) : K(K) {}
265 // A helper function for constructing an instance into a bump vector context.
266 template <typename T, typename... ArgTypes>
267 static T *create(BumpVectorContext &C, ArgTypes... Args) {
268 auto *CC = C.getAllocator().Allocate<T>();
269 return new (CC) T(Args...);
272 // A sub-routine of createFromLayers() that deals with temporary objects
273 // that need to be materialized. The BTE argument is for the situation when
274 // the object also needs to be bound for destruction.
275 static const ConstructionContext *createMaterializedTemporaryFromLayers(
276 BumpVectorContext &C, const MaterializeTemporaryExpr *MTE,
277 const CXXBindTemporaryExpr *BTE,
278 const ConstructionContextLayer *ParentLayer);
280 // A sub-routine of createFromLayers() that deals with temporary objects
281 // that need to be bound for destruction. Automatically finds out if the
282 // object also needs to be materialized and delegates to
283 // createMaterializedTemporaryFromLayers() if necessary.
284 static const ConstructionContext *
285 createBoundTemporaryFromLayers(
286 BumpVectorContext &C, const CXXBindTemporaryExpr *BTE,
287 const ConstructionContextLayer *ParentLayer);
290 /// Consume the construction context layer, together with its parent layers,
291 /// and wrap it up into a complete construction context. May return null
292 /// if layers do not form any supported construction context.
293 static const ConstructionContext *
294 createFromLayers(BumpVectorContext &C,
295 const ConstructionContextLayer *TopLayer);
297 Kind getKind() const { return K; }
300 /// An abstract base class for local variable constructors.
301 class VariableConstructionContext : public ConstructionContext {
305 VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS)
306 : ConstructionContext(K), DS(DS) {
307 assert(classof(this));
312 const DeclStmt *getDeclStmt() const { return DS; }
314 static bool classof(const ConstructionContext *CC) {
315 return CC->getKind() >= VARIABLE_BEGIN &&
316 CC->getKind() <= VARIABLE_END;
320 /// Represents construction into a simple local variable, eg. T var(123);.
321 /// If a variable has an initializer, eg. T var = makeT();, then the final
322 /// elidable copy-constructor from makeT() into var would also be a simple
323 /// variable constructor handled by this class.
324 class SimpleVariableConstructionContext : public VariableConstructionContext {
325 friend class ConstructionContext; // Allows to create<>() itself.
327 explicit SimpleVariableConstructionContext(const DeclStmt *DS)
328 : VariableConstructionContext(ConstructionContext::SimpleVariableKind,
332 static bool classof(const ConstructionContext *CC) {
333 return CC->getKind() == SimpleVariableKind;
337 /// Represents construction into a simple variable with an initializer syntax,
338 /// with a single constructor, eg. T var = makeT();. Such construction context
339 /// may only appear in C++17 because previously it was split into a temporary
340 /// object constructor and an elidable simple variable copy-constructor and
341 /// we were producing separate construction contexts for these constructors.
342 /// In C++17 we have a single construction context that combines both.
343 /// Note that if the object has trivial destructor, then this code is
344 /// indistinguishable from a simple variable constructor on the AST level;
345 /// in this case we provide a simple variable construction context.
346 class CXX17ElidedCopyVariableConstructionContext
347 : public VariableConstructionContext {
348 const CXXBindTemporaryExpr *BTE;
350 friend class ConstructionContext; // Allows to create<>() itself.
352 explicit CXX17ElidedCopyVariableConstructionContext(
353 const DeclStmt *DS, const CXXBindTemporaryExpr *BTE)
354 : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) {
359 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
361 static bool classof(const ConstructionContext *CC) {
362 return CC->getKind() == CXX17ElidedCopyVariableKind;
366 // An abstract base class for constructor-initializer-based constructors.
367 class ConstructorInitializerConstructionContext : public ConstructionContext {
368 const CXXCtorInitializer *I;
371 explicit ConstructorInitializerConstructionContext(
372 ConstructionContext::Kind K, const CXXCtorInitializer *I)
373 : ConstructionContext(K), I(I) {
374 assert(classof(this));
379 const CXXCtorInitializer *getCXXCtorInitializer() const { return I; }
381 static bool classof(const ConstructionContext *CC) {
382 return CC->getKind() >= INITIALIZER_BEGIN &&
383 CC->getKind() <= INITIALIZER_END;
387 /// Represents construction into a field or a base class within a bigger object
388 /// via a constructor initializer, eg. T(): field(123) { ... }.
389 class SimpleConstructorInitializerConstructionContext
390 : public ConstructorInitializerConstructionContext {
391 friend class ConstructionContext; // Allows to create<>() itself.
393 explicit SimpleConstructorInitializerConstructionContext(
394 const CXXCtorInitializer *I)
395 : ConstructorInitializerConstructionContext(
396 ConstructionContext::SimpleConstructorInitializerKind, I) {}
399 static bool classof(const ConstructionContext *CC) {
400 return CC->getKind() == SimpleConstructorInitializerKind;
404 /// Represents construction into a field or a base class within a bigger object
405 /// via a constructor initializer, with a single constructor, eg.
406 /// T(): field(Field(123)) { ... }. Such construction context may only appear
407 /// in C++17 because previously it was split into a temporary object constructor
408 /// and an elidable simple constructor-initializer copy-constructor and we were
409 /// producing separate construction contexts for these constructors. In C++17
410 /// we have a single construction context that combines both. Note that if the
411 /// object has trivial destructor, then this code is indistinguishable from
412 /// a simple constructor-initializer constructor on the AST level; in this case
413 /// we provide a simple constructor-initializer construction context.
414 class CXX17ElidedCopyConstructorInitializerConstructionContext
415 : public ConstructorInitializerConstructionContext {
416 const CXXBindTemporaryExpr *BTE;
418 friend class ConstructionContext; // Allows to create<>() itself.
420 explicit CXX17ElidedCopyConstructorInitializerConstructionContext(
421 const CXXCtorInitializer *I, const CXXBindTemporaryExpr *BTE)
422 : ConstructorInitializerConstructionContext(
423 CXX17ElidedCopyConstructorInitializerKind, I),
429 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
431 static bool classof(const ConstructionContext *CC) {
432 return CC->getKind() == CXX17ElidedCopyConstructorInitializerKind;
436 /// Represents immediate initialization of memory allocated by operator new,
438 class NewAllocatedObjectConstructionContext : public ConstructionContext {
439 const CXXNewExpr *NE;
441 friend class ConstructionContext; // Allows to create<>() itself.
443 explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE)
444 : ConstructionContext(ConstructionContext::NewAllocatedObjectKind),
450 const CXXNewExpr *getCXXNewExpr() const { return NE; }
452 static bool classof(const ConstructionContext *CC) {
453 return CC->getKind() == NewAllocatedObjectKind;
457 /// Represents a temporary object, eg. T(123), that does not immediately cross
458 /// function boundaries "by value"; constructors that construct function
459 /// value-type arguments or values that are immediately returned from the
460 /// function that returns a value receive separate construction context kinds.
461 class TemporaryObjectConstructionContext : public ConstructionContext {
462 const CXXBindTemporaryExpr *BTE;
463 const MaterializeTemporaryExpr *MTE;
466 explicit TemporaryObjectConstructionContext(
467 ConstructionContext::Kind K, const CXXBindTemporaryExpr *BTE,
468 const MaterializeTemporaryExpr *MTE)
469 : ConstructionContext(K), BTE(BTE), MTE(MTE) {
470 // Both BTE and MTE can be null here, all combinations possible.
471 // Even though for now at least one should be non-null, we simply haven't
472 // implemented the other case yet (this would be a temporary in the middle
473 // of nowhere that doesn't have a non-trivial destructor).
477 /// CXXBindTemporaryExpr here is non-null as long as the temporary has
478 /// a non-trivial destructor.
479 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const {
483 /// MaterializeTemporaryExpr is non-null as long as the temporary is actually
484 /// used after construction, eg. by binding to a reference (lifetime
485 /// extension), accessing a field, calling a method, or passing it into
486 /// a function (an elidable copy or move constructor would be a common
487 /// example) by reference.
488 const MaterializeTemporaryExpr *getMaterializedTemporaryExpr() const {
492 static bool classof(const ConstructionContext *CC) {
493 return CC->getKind() >= TEMPORARY_BEGIN && CC->getKind() <= TEMPORARY_END;
497 /// Represents a temporary object that is not constructed for the purpose of
498 /// being immediately copied/moved by an elidable copy/move-constructor.
499 /// This includes temporary objects "in the middle of nowhere" like T(123) and
500 /// lifetime-extended temporaries.
501 class SimpleTemporaryObjectConstructionContext
502 : public TemporaryObjectConstructionContext {
503 friend class ConstructionContext; // Allows to create<>() itself.
505 explicit SimpleTemporaryObjectConstructionContext(
506 const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE)
507 : TemporaryObjectConstructionContext(
508 ConstructionContext::SimpleTemporaryObjectKind, BTE, MTE) {}
511 static bool classof(const ConstructionContext *CC) {
512 return CC->getKind() == SimpleTemporaryObjectKind;
516 /// Represents a temporary object that is constructed for the sole purpose
517 /// of being immediately copied by an elidable copy/move constructor.
518 /// For example, T t = T(123); includes a temporary T(123) that is immediately
519 /// copied to variable t. In such cases the elidable copy can (but not
520 /// necessarily should) be omitted ("elided") accodring to the rules of the
521 /// language; the constructor would then construct variable t directly.
522 /// This construction context contains information of the elidable constructor
523 /// and its respective construction context.
524 class ElidedTemporaryObjectConstructionContext
525 : public TemporaryObjectConstructionContext {
526 const CXXConstructExpr *ElidedCE;
527 const ConstructionContext *ElidedCC;
529 friend class ConstructionContext; // Allows to create<>() itself.
531 explicit ElidedTemporaryObjectConstructionContext(
532 const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE,
533 const CXXConstructExpr *ElidedCE, const ConstructionContext *ElidedCC)
534 : TemporaryObjectConstructionContext(
535 ConstructionContext::ElidedTemporaryObjectKind, BTE, MTE),
536 ElidedCE(ElidedCE), ElidedCC(ElidedCC) {
537 // Elided constructor and its context should be either both specified
538 // or both unspecified. In the former case, the constructor must be
540 assert(ElidedCE && ElidedCE->isElidable() && ElidedCC);
544 const CXXConstructExpr *getConstructorAfterElision() const {
548 const ConstructionContext *getConstructionContextAfterElision() const {
552 static bool classof(const ConstructionContext *CC) {
553 return CC->getKind() == ElidedTemporaryObjectKind;
557 class ReturnedValueConstructionContext : public ConstructionContext {
558 const ReturnStmt *RS;
561 explicit ReturnedValueConstructionContext(ConstructionContext::Kind K,
562 const ReturnStmt *RS)
563 : ConstructionContext(K), RS(RS) {
564 assert(classof(this));
569 const ReturnStmt *getReturnStmt() const { return RS; }
571 static bool classof(const ConstructionContext *CC) {
572 return CC->getKind() >= RETURNED_VALUE_BEGIN &&
573 CC->getKind() <= RETURNED_VALUE_END;
577 /// Represents a temporary object that is being immediately returned from a
578 /// function by value, eg. return t; or return T(123);. In this case there is
579 /// always going to be a constructor at the return site. However, the usual
580 /// temporary-related bureaucracy (CXXBindTemporaryExpr,
581 /// MaterializeTemporaryExpr) is normally located in the caller function's AST.
582 class SimpleReturnedValueConstructionContext
583 : public ReturnedValueConstructionContext {
584 friend class ConstructionContext; // Allows to create<>() itself.
586 explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS)
587 : ReturnedValueConstructionContext(
588 ConstructionContext::SimpleReturnedValueKind, RS) {}
591 static bool classof(const ConstructionContext *CC) {
592 return CC->getKind() == SimpleReturnedValueKind;
596 /// Represents a temporary object that is being immediately returned from a
597 /// function by value, eg. return t; or return T(123); in C++17.
598 /// In C++17 there is not going to be an elidable copy constructor at the
599 /// return site. However, the usual temporary-related bureaucracy (CXXBindTemporaryExpr,
600 /// MaterializeTemporaryExpr) is normally located in the caller function's AST.
601 /// Note that if the object has trivial destructor, then this code is
602 /// indistinguishable from a simple returned value constructor on the AST level;
603 /// in this case we provide a simple returned value construction context.
604 class CXX17ElidedCopyReturnedValueConstructionContext
605 : public ReturnedValueConstructionContext {
606 const CXXBindTemporaryExpr *BTE;
608 friend class ConstructionContext; // Allows to create<>() itself.
610 explicit CXX17ElidedCopyReturnedValueConstructionContext(
611 const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE)
612 : ReturnedValueConstructionContext(
613 ConstructionContext::CXX17ElidedCopyReturnedValueKind, RS),
619 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
621 static bool classof(const ConstructionContext *CC) {
622 return CC->getKind() == CXX17ElidedCopyReturnedValueKind;
626 class ArgumentConstructionContext : public ConstructionContext {
627 // The call of which the context is an argument.
630 // Which argument we're constructing. Note that when numbering between
631 // arguments and parameters is inconsistent (eg., operator calls),
632 // this is the index of the argument, not of the parameter.
635 // Whether the object needs to be destroyed.
636 const CXXBindTemporaryExpr *BTE;
638 friend class ConstructionContext; // Allows to create<>() itself.
640 explicit ArgumentConstructionContext(const Expr *CE, unsigned Index,
641 const CXXBindTemporaryExpr *BTE)
642 : ConstructionContext(ArgumentKind), CE(CE),
643 Index(Index), BTE(BTE) {
644 assert(isa<CallExpr>(CE) || isa<CXXConstructExpr>(CE) ||
645 isa<ObjCMessageExpr>(CE));
650 const Expr *getCallLikeExpr() const { return CE; }
651 unsigned getIndex() const { return Index; }
652 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
654 static bool classof(const ConstructionContext *CC) {
655 return CC->getKind() == ArgumentKind;
659 } // end namespace clang
661 #endif // LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H