1 //===- ConstructionContext.h - CFG constructor information ------*- C++ -*-===//
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 #ifndef LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
18 #define LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
19 
20 #include "clang/Analysis/Support/BumpVector.h"
21 #include "clang/AST/ExprCXX.h"
22 #include "clang/AST/ExprObjC.h"
23 
24 namespace clang {
25 
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 {
30 public:
31   enum ItemKind {
32     VariableKind,
33     NewAllocatorKind,
34     ReturnKind,
35     MaterializationKind,
36     TemporaryDestructorKind,
37     ElidedDestructorKind,
38     ElidableConstructorKind,
39     ArgumentKind,
40     STATEMENT_WITH_INDEX_KIND_BEGIN=ArgumentKind,
41     STATEMENT_WITH_INDEX_KIND_END=ArgumentKind,
42     STATEMENT_KIND_BEGIN = VariableKind,
43     STATEMENT_KIND_END = ArgumentKind,
44     InitializerKind,
45     INITIALIZER_KIND_BEGIN=InitializerKind,
46     INITIALIZER_KIND_END=InitializerKind
47   };
48 
getKindAsString(ItemKind K)49   LLVM_DUMP_METHOD static StringRef getKindAsString(ItemKind K) {
50     switch (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";
60     };
61     llvm_unreachable("Unknown ItemKind");
62   }
63 
64 private:
65   const void *const Data;
66   const ItemKind Kind;
67   const unsigned Index = 0;
68 
hasStatement()69   bool hasStatement() const {
70     return Kind >= STATEMENT_KIND_BEGIN &&
71            Kind <= STATEMENT_KIND_END;
72   }
73 
hasIndex()74   bool hasIndex() const {
75     return Kind >= STATEMENT_WITH_INDEX_KIND_BEGIN &&
76            Kind >= STATEMENT_WITH_INDEX_KIND_END;
77   }
78 
hasInitializer()79   bool hasInitializer() const {
80     return Kind >= INITIALIZER_KIND_BEGIN &&
81            Kind <= INITIALIZER_KIND_END;
82   }
83 
84 public:
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.
ConstructionContextItem(const DeclStmt * DS)88   ConstructionContextItem(const DeclStmt *DS)
89       : Data(DS), Kind(VariableKind) {}
90 
ConstructionContextItem(const CXXNewExpr * NE)91   ConstructionContextItem(const CXXNewExpr *NE)
92       : Data(NE), Kind(NewAllocatorKind) {}
93 
ConstructionContextItem(const ReturnStmt * RS)94   ConstructionContextItem(const ReturnStmt *RS)
95       : Data(RS), Kind(ReturnKind) {}
96 
ConstructionContextItem(const MaterializeTemporaryExpr * MTE)97   ConstructionContextItem(const MaterializeTemporaryExpr *MTE)
98       : Data(MTE), Kind(MaterializationKind) {}
99 
100   ConstructionContextItem(const CXXBindTemporaryExpr *BTE,
101                           bool IsElided = false)
Data(BTE)102       : Data(BTE),
103         Kind(IsElided ? ElidedDestructorKind : TemporaryDestructorKind) {}
104 
ConstructionContextItem(const CXXConstructExpr * CE)105   ConstructionContextItem(const CXXConstructExpr *CE)
106       : Data(CE), Kind(ElidableConstructorKind) {}
107 
ConstructionContextItem(const CallExpr * CE,unsigned Index)108   ConstructionContextItem(const CallExpr *CE, unsigned Index)
109       : Data(CE), Kind(ArgumentKind), Index(Index) {}
110 
ConstructionContextItem(const CXXConstructExpr * CE,unsigned Index)111   ConstructionContextItem(const CXXConstructExpr *CE, unsigned Index)
112       : Data(CE), Kind(ArgumentKind), Index(Index) {}
113 
ConstructionContextItem(const ObjCMessageExpr * ME,unsigned Index)114   ConstructionContextItem(const ObjCMessageExpr *ME, unsigned Index)
115       : Data(ME), Kind(ArgumentKind), Index(Index) {}
116 
117   // A polymorphic version of the previous calls with dynamic type check.
ConstructionContextItem(const Expr * E,unsigned Index)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));
122   }
123 
ConstructionContextItem(const CXXCtorInitializer * Init)124   ConstructionContextItem(const CXXCtorInitializer *Init)
125       : Data(Init), Kind(InitializerKind), Index(0) {}
126 
getKind()127   ItemKind getKind() const { return Kind; }
128 
getKindAsString()129   LLVM_DUMP_METHOD StringRef getKindAsString() const {
130     return getKindAsString(getKind());
131   }
132 
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).
getStmt()137   const Stmt *getStmt() const {
138     assert(hasStatement());
139     return static_cast<const Stmt *>(Data);
140   }
141 
getStmtOrNull()142   const Stmt *getStmtOrNull() const {
143     return hasStatement() ? getStmt() : nullptr;
144   }
145 
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.
getCXXCtorInitializer()149   const CXXCtorInitializer *getCXXCtorInitializer() const {
150     assert(hasInitializer());
151     return static_cast<const CXXCtorInitializer *>(Data);
152   }
153 
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.
getIndex()158   unsigned getIndex() const {
159     // This is a fairly specific request. Let's make sure the user knows
160     // what he's doing.
161     assert(hasIndex());
162     return Index;
163   }
164 
Profile(llvm::FoldingSetNodeID & ID)165   void Profile(llvm::FoldingSetNodeID &ID) const {
166     ID.AddPointer(Data);
167     ID.AddInteger(Kind);
168     ID.AddInteger(Index);
169   }
170 
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);
177   }
178 
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);
182   }
183 };
184 
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;
207 
ConstructionContextLayer(ConstructionContextItem Item,const ConstructionContextLayer * Parent)208   ConstructionContextLayer(ConstructionContextItem Item,
209                            const ConstructionContextLayer *Parent)
210       : Parent(Parent), Item(Item) {}
211 
212 public:
213   static const ConstructionContextLayer *
214   create(BumpVectorContext &C, const ConstructionContextItem &Item,
215          const ConstructionContextLayer *Parent = nullptr);
216 
getItem()217   const ConstructionContextItem &getItem() const { return Item; }
getParent()218   const ConstructionContextLayer *getParent() const { return Parent; }
isLast()219   bool isLast() const { return !Parent; }
220 
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;
227 };
228 
229 
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 {
235 public:
236   enum Kind {
237     SimpleVariableKind,
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,
254     ArgumentKind
255   };
256 
257 protected:
258   Kind K;
259 
260   // Do not make public! These need to only be constructed
261   // via createFromLayers().
ConstructionContext(Kind K)262   explicit ConstructionContext(Kind K) : K(K) {}
263 
264 private:
265   // A helper function for constructing an instance into a bump vector context.
266   template <typename T, typename... ArgTypes>
create(BumpVectorContext & C,ArgTypes...Args)267   static T *create(BumpVectorContext &C, ArgTypes... Args) {
268     auto *CC = C.getAllocator().Allocate<T>();
269     return new (CC) T(Args...);
270   }
271 
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);
279 
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);
288 
289 public:
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);
296 
getKind()297   Kind getKind() const { return K; }
298 };
299 
300 /// An abstract base class for local variable constructors.
301 class VariableConstructionContext : public ConstructionContext {
302   const DeclStmt *DS;
303 
304 protected:
VariableConstructionContext(ConstructionContext::Kind K,const DeclStmt * DS)305   VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS)
306       : ConstructionContext(K), DS(DS) {
307     assert(classof(this));
308     assert(DS);
309   }
310 
311 public:
getDeclStmt()312   const DeclStmt *getDeclStmt() const { return DS; }
313 
classof(const ConstructionContext * CC)314   static bool classof(const ConstructionContext *CC) {
315     return CC->getKind() >= VARIABLE_BEGIN &&
316            CC->getKind() <= VARIABLE_END;
317   }
318 };
319 
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.
326 
SimpleVariableConstructionContext(const DeclStmt * DS)327   explicit SimpleVariableConstructionContext(const DeclStmt *DS)
328       : VariableConstructionContext(ConstructionContext::SimpleVariableKind,
329                                     DS) {}
330 
331 public:
classof(const ConstructionContext * CC)332   static bool classof(const ConstructionContext *CC) {
333     return CC->getKind() == SimpleVariableKind;
334   }
335 };
336 
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;
349 
350   friend class ConstructionContext; // Allows to create<>() itself.
351 
CXX17ElidedCopyVariableConstructionContext(const DeclStmt * DS,const CXXBindTemporaryExpr * BTE)352   explicit CXX17ElidedCopyVariableConstructionContext(
353       const DeclStmt *DS, const CXXBindTemporaryExpr *BTE)
354       : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) {
355     assert(BTE);
356   }
357 
358 public:
getCXXBindTemporaryExpr()359   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
360 
classof(const ConstructionContext * CC)361   static bool classof(const ConstructionContext *CC) {
362     return CC->getKind() == CXX17ElidedCopyVariableKind;
363   }
364 };
365 
366 // An abstract base class for constructor-initializer-based constructors.
367 class ConstructorInitializerConstructionContext : public ConstructionContext {
368   const CXXCtorInitializer *I;
369 
370 protected:
ConstructorInitializerConstructionContext(ConstructionContext::Kind K,const CXXCtorInitializer * I)371   explicit ConstructorInitializerConstructionContext(
372       ConstructionContext::Kind K, const CXXCtorInitializer *I)
373       : ConstructionContext(K), I(I) {
374     assert(classof(this));
375     assert(I);
376   }
377 
378 public:
getCXXCtorInitializer()379   const CXXCtorInitializer *getCXXCtorInitializer() const { return I; }
380 
classof(const ConstructionContext * CC)381   static bool classof(const ConstructionContext *CC) {
382     return CC->getKind() >= INITIALIZER_BEGIN &&
383            CC->getKind() <= INITIALIZER_END;
384   }
385 };
386 
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.
392 
SimpleConstructorInitializerConstructionContext(const CXXCtorInitializer * I)393   explicit SimpleConstructorInitializerConstructionContext(
394       const CXXCtorInitializer *I)
395       : ConstructorInitializerConstructionContext(
396             ConstructionContext::SimpleConstructorInitializerKind, I) {}
397 
398 public:
classof(const ConstructionContext * CC)399   static bool classof(const ConstructionContext *CC) {
400     return CC->getKind() == SimpleConstructorInitializerKind;
401   }
402 };
403 
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;
417 
418   friend class ConstructionContext; // Allows to create<>() itself.
419 
CXX17ElidedCopyConstructorInitializerConstructionContext(const CXXCtorInitializer * I,const CXXBindTemporaryExpr * BTE)420   explicit CXX17ElidedCopyConstructorInitializerConstructionContext(
421       const CXXCtorInitializer *I, const CXXBindTemporaryExpr *BTE)
422       : ConstructorInitializerConstructionContext(
423             CXX17ElidedCopyConstructorInitializerKind, I),
424         BTE(BTE) {
425     assert(BTE);
426   }
427 
428 public:
getCXXBindTemporaryExpr()429   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
430 
classof(const ConstructionContext * CC)431   static bool classof(const ConstructionContext *CC) {
432     return CC->getKind() == CXX17ElidedCopyConstructorInitializerKind;
433   }
434 };
435 
436 /// Represents immediate initialization of memory allocated by operator new,
437 /// eg. new T(123);.
438 class NewAllocatedObjectConstructionContext : public ConstructionContext {
439   const CXXNewExpr *NE;
440 
441   friend class ConstructionContext; // Allows to create<>() itself.
442 
NewAllocatedObjectConstructionContext(const CXXNewExpr * NE)443   explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE)
444       : ConstructionContext(ConstructionContext::NewAllocatedObjectKind),
445         NE(NE) {
446     assert(NE);
447   }
448 
449 public:
getCXXNewExpr()450   const CXXNewExpr *getCXXNewExpr() const { return NE; }
451 
classof(const ConstructionContext * CC)452   static bool classof(const ConstructionContext *CC) {
453     return CC->getKind() == NewAllocatedObjectKind;
454   }
455 };
456 
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;
464 
465 protected:
TemporaryObjectConstructionContext(ConstructionContext::Kind K,const CXXBindTemporaryExpr * BTE,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).
474   }
475 
476 public:
477   /// CXXBindTemporaryExpr here is non-null as long as the temporary has
478   /// a non-trivial destructor.
getCXXBindTemporaryExpr()479   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const {
480     return BTE;
481   }
482 
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.
getMaterializedTemporaryExpr()488   const MaterializeTemporaryExpr *getMaterializedTemporaryExpr() const {
489     return MTE;
490   }
491 
classof(const ConstructionContext * CC)492   static bool classof(const ConstructionContext *CC) {
493     return CC->getKind() >= TEMPORARY_BEGIN && CC->getKind() <= TEMPORARY_END;
494   }
495 };
496 
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.
504 
SimpleTemporaryObjectConstructionContext(const CXXBindTemporaryExpr * BTE,const MaterializeTemporaryExpr * MTE)505   explicit SimpleTemporaryObjectConstructionContext(
506       const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE)
507       : TemporaryObjectConstructionContext(
508             ConstructionContext::SimpleTemporaryObjectKind, BTE, MTE) {}
509 
510 public:
classof(const ConstructionContext * CC)511   static bool classof(const ConstructionContext *CC) {
512     return CC->getKind() == SimpleTemporaryObjectKind;
513   }
514 };
515 
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;
528 
529   friend class ConstructionContext; // Allows to create<>() itself.
530 
ElidedTemporaryObjectConstructionContext(const CXXBindTemporaryExpr * BTE,const MaterializeTemporaryExpr * MTE,const CXXConstructExpr * ElidedCE,const ConstructionContext * ElidedCC)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
539     // elidable.
540     assert(ElidedCE && ElidedCE->isElidable() && ElidedCC);
541   }
542 
543 public:
getConstructorAfterElision()544   const CXXConstructExpr *getConstructorAfterElision() const {
545     return ElidedCE;
546   }
547 
getConstructionContextAfterElision()548   const ConstructionContext *getConstructionContextAfterElision() const {
549     return ElidedCC;
550   }
551 
classof(const ConstructionContext * CC)552   static bool classof(const ConstructionContext *CC) {
553     return CC->getKind() == ElidedTemporaryObjectKind;
554   }
555 };
556 
557 class ReturnedValueConstructionContext : public ConstructionContext {
558   const ReturnStmt *RS;
559 
560 protected:
ReturnedValueConstructionContext(ConstructionContext::Kind K,const ReturnStmt * RS)561   explicit ReturnedValueConstructionContext(ConstructionContext::Kind K,
562                                             const ReturnStmt *RS)
563       : ConstructionContext(K), RS(RS) {
564     assert(classof(this));
565     assert(RS);
566   }
567 
568 public:
getReturnStmt()569   const ReturnStmt *getReturnStmt() const { return RS; }
570 
classof(const ConstructionContext * CC)571   static bool classof(const ConstructionContext *CC) {
572     return CC->getKind() >= RETURNED_VALUE_BEGIN &&
573            CC->getKind() <= RETURNED_VALUE_END;
574   }
575 };
576 
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.
585 
SimpleReturnedValueConstructionContext(const ReturnStmt * RS)586   explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS)
587       : ReturnedValueConstructionContext(
588             ConstructionContext::SimpleReturnedValueKind, RS) {}
589 
590 public:
classof(const ConstructionContext * CC)591   static bool classof(const ConstructionContext *CC) {
592     return CC->getKind() == SimpleReturnedValueKind;
593   }
594 };
595 
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;
607 
608   friend class ConstructionContext; // Allows to create<>() itself.
609 
CXX17ElidedCopyReturnedValueConstructionContext(const ReturnStmt * RS,const CXXBindTemporaryExpr * BTE)610   explicit CXX17ElidedCopyReturnedValueConstructionContext(
611       const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE)
612       : ReturnedValueConstructionContext(
613             ConstructionContext::CXX17ElidedCopyReturnedValueKind, RS),
614         BTE(BTE) {
615     assert(BTE);
616   }
617 
618 public:
getCXXBindTemporaryExpr()619   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
620 
classof(const ConstructionContext * CC)621   static bool classof(const ConstructionContext *CC) {
622     return CC->getKind() == CXX17ElidedCopyReturnedValueKind;
623   }
624 };
625 
626 class ArgumentConstructionContext : public ConstructionContext {
627   // The call of which the context is an argument.
628   const Expr *CE;
629 
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.
633   unsigned Index;
634 
635   // Whether the object needs to be destroyed.
636   const CXXBindTemporaryExpr *BTE;
637 
638   friend class ConstructionContext; // Allows to create<>() itself.
639 
ArgumentConstructionContext(const Expr * CE,unsigned Index,const CXXBindTemporaryExpr * BTE)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));
646     // BTE is optional.
647   }
648 
649 public:
getCallLikeExpr()650   const Expr *getCallLikeExpr() const { return CE; }
getIndex()651   unsigned getIndex() const { return Index; }
getCXXBindTemporaryExpr()652   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
653 
classof(const ConstructionContext * CC)654   static bool classof(const ConstructionContext *CC) {
655     return CC->getKind() == ArgumentKind;
656   }
657 };
658 
659 } // end namespace clang
660 
661 #endif // LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
662