1 //===- ConstructionContext.h - CFG constructor information ------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the ConstructionContext class and its sub-classes,
10 // which represent various different ways of constructing C++ objects
11 // with the additional information the users may want to know about
12 // the constructor.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #ifndef LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
17 #define LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
18 
19 #include "clang/Analysis/Support/BumpVector.h"
20 #include "clang/AST/ExprCXX.h"
21 #include "clang/AST/ExprObjC.h"
22 
23 namespace clang {
24 
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 {
29 public:
30   enum ItemKind {
31     VariableKind,
32     NewAllocatorKind,
33     ReturnKind,
34     MaterializationKind,
35     TemporaryDestructorKind,
36     ElidedDestructorKind,
37     ElidableConstructorKind,
38     ArgumentKind,
39     STATEMENT_WITH_INDEX_KIND_BEGIN=ArgumentKind,
40     STATEMENT_WITH_INDEX_KIND_END=ArgumentKind,
41     STATEMENT_KIND_BEGIN = VariableKind,
42     STATEMENT_KIND_END = ArgumentKind,
43     InitializerKind,
44     INITIALIZER_KIND_BEGIN=InitializerKind,
45     INITIALIZER_KIND_END=InitializerKind
46   };
47 
48   LLVM_DUMP_METHOD static StringRef getKindAsString(ItemKind K) {
49     switch (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";
59     };
60     llvm_unreachable("Unknown ItemKind");
61   }
62 
63 private:
64   const void *const Data;
65   const ItemKind Kind;
66   const unsigned Index = 0;
67 
68   bool hasStatement() const {
69     return Kind >= STATEMENT_KIND_BEGIN &&
70            Kind <= STATEMENT_KIND_END;
71   }
72 
73   bool hasIndex() const {
74     return Kind >= STATEMENT_WITH_INDEX_KIND_BEGIN &&
75            Kind >= STATEMENT_WITH_INDEX_KIND_END;
76   }
77 
78   bool hasInitializer() const {
79     return Kind >= INITIALIZER_KIND_BEGIN &&
80            Kind <= INITIALIZER_KIND_END;
81   }
82 
83 public:
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) {}
89 
90   ConstructionContextItem(const CXXNewExpr *NE)
91       : Data(NE), Kind(NewAllocatorKind) {}
92 
93   ConstructionContextItem(const ReturnStmt *RS)
94       : Data(RS), Kind(ReturnKind) {}
95 
96   ConstructionContextItem(const MaterializeTemporaryExpr *MTE)
97       : Data(MTE), Kind(MaterializationKind) {}
98 
99   ConstructionContextItem(const CXXBindTemporaryExpr *BTE,
100                           bool IsElided = false)
101       : Data(BTE),
102         Kind(IsElided ? ElidedDestructorKind : TemporaryDestructorKind) {}
103 
104   ConstructionContextItem(const CXXConstructExpr *CE)
105       : Data(CE), Kind(ElidableConstructorKind) {}
106 
107   ConstructionContextItem(const CallExpr *CE, unsigned Index)
108       : Data(CE), Kind(ArgumentKind), Index(Index) {}
109 
110   ConstructionContextItem(const CXXConstructExpr *CE, unsigned Index)
111       : Data(CE), Kind(ArgumentKind), Index(Index) {}
112 
113   ConstructionContextItem(const CXXInheritedCtorInitExpr *CE, unsigned Index)
114       : Data(CE), Kind(ArgumentKind), Index(Index) {}
115 
116   ConstructionContextItem(const ObjCMessageExpr *ME, unsigned Index)
117       : Data(ME), Kind(ArgumentKind), Index(Index) {}
118 
119   // A polymorphic version of the previous calls with dynamic type check.
120   ConstructionContextItem(const Expr *E, unsigned Index)
121       : Data(E), Kind(ArgumentKind), Index(Index) {
122     assert(isa<CallExpr>(E) || isa<CXXConstructExpr>(E) ||
123            isa<CXXDeleteExpr>(E) || isa<CXXInheritedCtorInitExpr>(E) ||
124            isa<ObjCMessageExpr>(E));
125   }
126 
127   ConstructionContextItem(const CXXCtorInitializer *Init)
128       : Data(Init), Kind(InitializerKind), Index(0) {}
129 
130   ItemKind getKind() const { return Kind; }
131 
132   LLVM_DUMP_METHOD StringRef getKindAsString() const {
133     return getKindAsString(getKind());
134   }
135 
136   /// The construction site - the statement that triggered the construction
137   /// for one of its parts. For instance, stack variable declaration statement
138   /// triggers construction of itself or its elements if it's an array,
139   /// new-expression triggers construction of the newly allocated object(s).
140   const Stmt *getStmt() const {
141     assert(hasStatement());
142     return static_cast<const Stmt *>(Data);
143   }
144 
145   const Stmt *getStmtOrNull() const {
146     return hasStatement() ? getStmt() : nullptr;
147   }
148 
149   /// The construction site is not necessarily a statement. It may also be a
150   /// CXXCtorInitializer, which means that a member variable is being
151   /// constructed during initialization of the object that contains it.
152   const CXXCtorInitializer *getCXXCtorInitializer() const {
153     assert(hasInitializer());
154     return static_cast<const CXXCtorInitializer *>(Data);
155   }
156 
157   /// If a single trigger statement triggers multiple constructors, they are
158   /// usually being enumerated. This covers function argument constructors
159   /// triggered by a call-expression and items in an initializer list triggered
160   /// by an init-list-expression.
161   unsigned getIndex() const {
162     // This is a fairly specific request. Let's make sure the user knows
163     // what he's doing.
164     assert(hasIndex());
165     return Index;
166   }
167 
168   void Profile(llvm::FoldingSetNodeID &ID) const {
169     ID.AddPointer(Data);
170     ID.AddInteger(Kind);
171     ID.AddInteger(Index);
172   }
173 
174   bool operator==(const ConstructionContextItem &Other) const {
175     // For most kinds the Index comparison is trivially true, but
176     // checking kind separately doesn't seem to be less expensive
177     // than checking Index. Same in operator<().
178     return std::make_tuple(Data, Kind, Index) ==
179            std::make_tuple(Other.Data, Other.Kind, Other.Index);
180   }
181 
182   bool operator<(const ConstructionContextItem &Other) const {
183     return std::make_tuple(Data, Kind, Index) <
184            std::make_tuple(Other.Data, Other.Kind, Other.Index);
185   }
186 };
187 
188 /// Construction context can be seen as a linked list of multiple layers.
189 /// Sometimes a single trigger is not enough to describe the construction
190 /// site. That's what causing us to have a chain of "partial" construction
191 /// context layers. Some examples:
192 /// - A constructor within in an aggregate initializer list within a variable
193 ///   would have a construction context of the initializer list with
194 ///   the parent construction context of a variable.
195 /// - A constructor for a temporary that needs to be both destroyed
196 ///   and materialized into an elidable copy constructor would have a
197 ///   construction context of a CXXBindTemporaryExpr with the parent
198 ///   construction context of a MaterializeTemproraryExpr.
199 /// Not all of these are currently supported.
200 /// Layers are created gradually while traversing the AST, and layers that
201 /// represent the outmost AST nodes are built first, while the node that
202 /// immediately contains the constructor would be built last and capture the
203 /// previous layers as its parents. Construction context captures the last layer
204 /// (which has links to the previous layers) and classifies the seemingly
205 /// arbitrary chain of layers into one of the possible ways of constructing
206 /// an object in C++ for user-friendly experience.
207 class ConstructionContextLayer {
208   const ConstructionContextLayer *Parent = nullptr;
209   ConstructionContextItem Item;
210 
211   ConstructionContextLayer(ConstructionContextItem Item,
212                            const ConstructionContextLayer *Parent)
213       : Parent(Parent), Item(Item) {}
214 
215 public:
216   static const ConstructionContextLayer *
217   create(BumpVectorContext &C, const ConstructionContextItem &Item,
218          const ConstructionContextLayer *Parent = nullptr);
219 
220   const ConstructionContextItem &getItem() const { return Item; }
221   const ConstructionContextLayer *getParent() const { return Parent; }
222   bool isLast() const { return !Parent; }
223 
224   /// See if Other is a proper initial segment of this construction context
225   /// in terms of the parent chain - i.e. a few first parents coincide and
226   /// then the other context terminates but our context goes further - i.e.,
227   /// we are providing the same context that the other context provides,
228   /// and a bit more above that.
229   bool isStrictlyMoreSpecificThan(const ConstructionContextLayer *Other) const;
230 };
231 
232 
233 /// ConstructionContext's subclasses describe different ways of constructing
234 /// an object in C++. The context re-captures the essential parent AST nodes
235 /// of the CXXConstructExpr it is assigned to and presents these nodes
236 /// through easy-to-understand accessor methods.
237 class ConstructionContext {
238 public:
239   enum Kind {
240     SimpleVariableKind,
241     CXX17ElidedCopyVariableKind,
242     VARIABLE_BEGIN = SimpleVariableKind,
243     VARIABLE_END = CXX17ElidedCopyVariableKind,
244     SimpleConstructorInitializerKind,
245     CXX17ElidedCopyConstructorInitializerKind,
246     INITIALIZER_BEGIN = SimpleConstructorInitializerKind,
247     INITIALIZER_END = CXX17ElidedCopyConstructorInitializerKind,
248     NewAllocatedObjectKind,
249     SimpleTemporaryObjectKind,
250     ElidedTemporaryObjectKind,
251     TEMPORARY_BEGIN = SimpleTemporaryObjectKind,
252     TEMPORARY_END = ElidedTemporaryObjectKind,
253     SimpleReturnedValueKind,
254     CXX17ElidedCopyReturnedValueKind,
255     RETURNED_VALUE_BEGIN = SimpleReturnedValueKind,
256     RETURNED_VALUE_END = CXX17ElidedCopyReturnedValueKind,
257     ArgumentKind
258   };
259 
260 protected:
261   Kind K;
262 
263   // Do not make public! These need to only be constructed
264   // via createFromLayers().
265   explicit ConstructionContext(Kind K) : K(K) {}
266 
267 private:
268   // A helper function for constructing an instance into a bump vector context.
269   template <typename T, typename... ArgTypes>
270   static T *create(BumpVectorContext &C, ArgTypes... Args) {
271     auto *CC = C.getAllocator().Allocate<T>();
272     return new (CC) T(Args...);
273   }
274 
275   // A sub-routine of createFromLayers() that deals with temporary objects
276   // that need to be materialized. The BTE argument is for the situation when
277   // the object also needs to be bound for destruction.
278   static const ConstructionContext *createMaterializedTemporaryFromLayers(
279       BumpVectorContext &C, const MaterializeTemporaryExpr *MTE,
280       const CXXBindTemporaryExpr *BTE,
281       const ConstructionContextLayer *ParentLayer);
282 
283   // A sub-routine of createFromLayers() that deals with temporary objects
284   // that need to be bound for destruction. Automatically finds out if the
285   // object also needs to be materialized and delegates to
286   // createMaterializedTemporaryFromLayers() if necessary.
287   static const ConstructionContext *
288   createBoundTemporaryFromLayers(
289       BumpVectorContext &C, const CXXBindTemporaryExpr *BTE,
290       const ConstructionContextLayer *ParentLayer);
291 
292 public:
293   /// Consume the construction context layer, together with its parent layers,
294   /// and wrap it up into a complete construction context. May return null
295   /// if layers do not form any supported construction context.
296   static const ConstructionContext *
297   createFromLayers(BumpVectorContext &C,
298                    const ConstructionContextLayer *TopLayer);
299 
300   Kind getKind() const { return K; }
301 };
302 
303 /// An abstract base class for local variable constructors.
304 class VariableConstructionContext : public ConstructionContext {
305   const DeclStmt *DS;
306 
307 protected:
308   VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS)
309       : ConstructionContext(K), DS(DS) {
310     assert(classof(this));
311     assert(DS);
312   }
313 
314 public:
315   const DeclStmt *getDeclStmt() const { return DS; }
316 
317   static bool classof(const ConstructionContext *CC) {
318     return CC->getKind() >= VARIABLE_BEGIN &&
319            CC->getKind() <= VARIABLE_END;
320   }
321 };
322 
323 /// Represents construction into a simple local variable, eg. T var(123);.
324 /// If a variable has an initializer, eg. T var = makeT();, then the final
325 /// elidable copy-constructor from makeT() into var would also be a simple
326 /// variable constructor handled by this class.
327 class SimpleVariableConstructionContext : public VariableConstructionContext {
328   friend class ConstructionContext; // Allows to create<>() itself.
329 
330   explicit SimpleVariableConstructionContext(const DeclStmt *DS)
331       : VariableConstructionContext(ConstructionContext::SimpleVariableKind,
332                                     DS) {}
333 
334 public:
335   static bool classof(const ConstructionContext *CC) {
336     return CC->getKind() == SimpleVariableKind;
337   }
338 };
339 
340 /// Represents construction into a simple variable with an initializer syntax,
341 /// with a single constructor, eg. T var = makeT();. Such construction context
342 /// may only appear in C++17 because previously it was split into a temporary
343 /// object constructor and an elidable simple variable copy-constructor and
344 /// we were producing separate construction contexts for these constructors.
345 /// In C++17 we have a single construction context that combines both.
346 /// Note that if the object has trivial destructor, then this code is
347 /// indistinguishable from a simple variable constructor on the AST level;
348 /// in this case we provide a simple variable construction context.
349 class CXX17ElidedCopyVariableConstructionContext
350     : public VariableConstructionContext {
351   const CXXBindTemporaryExpr *BTE;
352 
353   friend class ConstructionContext; // Allows to create<>() itself.
354 
355   explicit CXX17ElidedCopyVariableConstructionContext(
356       const DeclStmt *DS, const CXXBindTemporaryExpr *BTE)
357       : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) {
358     assert(BTE);
359   }
360 
361 public:
362   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
363 
364   static bool classof(const ConstructionContext *CC) {
365     return CC->getKind() == CXX17ElidedCopyVariableKind;
366   }
367 };
368 
369 // An abstract base class for constructor-initializer-based constructors.
370 class ConstructorInitializerConstructionContext : public ConstructionContext {
371   const CXXCtorInitializer *I;
372 
373 protected:
374   explicit ConstructorInitializerConstructionContext(
375       ConstructionContext::Kind K, const CXXCtorInitializer *I)
376       : ConstructionContext(K), I(I) {
377     assert(classof(this));
378     assert(I);
379   }
380 
381 public:
382   const CXXCtorInitializer *getCXXCtorInitializer() const { return I; }
383 
384   static bool classof(const ConstructionContext *CC) {
385     return CC->getKind() >= INITIALIZER_BEGIN &&
386            CC->getKind() <= INITIALIZER_END;
387   }
388 };
389 
390 /// Represents construction into a field or a base class within a bigger object
391 /// via a constructor initializer, eg. T(): field(123) { ... }.
392 class SimpleConstructorInitializerConstructionContext
393     : public ConstructorInitializerConstructionContext {
394   friend class ConstructionContext; // Allows to create<>() itself.
395 
396   explicit SimpleConstructorInitializerConstructionContext(
397       const CXXCtorInitializer *I)
398       : ConstructorInitializerConstructionContext(
399             ConstructionContext::SimpleConstructorInitializerKind, I) {}
400 
401 public:
402   static bool classof(const ConstructionContext *CC) {
403     return CC->getKind() == SimpleConstructorInitializerKind;
404   }
405 };
406 
407 /// Represents construction into a field or a base class within a bigger object
408 /// via a constructor initializer, with a single constructor, eg.
409 /// T(): field(Field(123)) { ... }. Such construction context may only appear
410 /// in C++17 because previously it was split into a temporary object constructor
411 /// and an elidable simple constructor-initializer copy-constructor and we were
412 /// producing separate construction contexts for these constructors. In C++17
413 /// we have a single construction context that combines both. Note that if the
414 /// object has trivial destructor, then this code is indistinguishable from
415 /// a simple constructor-initializer constructor on the AST level; in this case
416 /// we provide a simple constructor-initializer construction context.
417 class CXX17ElidedCopyConstructorInitializerConstructionContext
418     : public ConstructorInitializerConstructionContext {
419   const CXXBindTemporaryExpr *BTE;
420 
421   friend class ConstructionContext; // Allows to create<>() itself.
422 
423   explicit CXX17ElidedCopyConstructorInitializerConstructionContext(
424       const CXXCtorInitializer *I, const CXXBindTemporaryExpr *BTE)
425       : ConstructorInitializerConstructionContext(
426             CXX17ElidedCopyConstructorInitializerKind, I),
427         BTE(BTE) {
428     assert(BTE);
429   }
430 
431 public:
432   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
433 
434   static bool classof(const ConstructionContext *CC) {
435     return CC->getKind() == CXX17ElidedCopyConstructorInitializerKind;
436   }
437 };
438 
439 /// Represents immediate initialization of memory allocated by operator new,
440 /// eg. new T(123);.
441 class NewAllocatedObjectConstructionContext : public ConstructionContext {
442   const CXXNewExpr *NE;
443 
444   friend class ConstructionContext; // Allows to create<>() itself.
445 
446   explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE)
447       : ConstructionContext(ConstructionContext::NewAllocatedObjectKind),
448         NE(NE) {
449     assert(NE);
450   }
451 
452 public:
453   const CXXNewExpr *getCXXNewExpr() const { return NE; }
454 
455   static bool classof(const ConstructionContext *CC) {
456     return CC->getKind() == NewAllocatedObjectKind;
457   }
458 };
459 
460 /// Represents a temporary object, eg. T(123), that does not immediately cross
461 /// function boundaries "by value"; constructors that construct function
462 /// value-type arguments or values that are immediately returned from the
463 /// function that returns a value receive separate construction context kinds.
464 class TemporaryObjectConstructionContext : public ConstructionContext {
465   const CXXBindTemporaryExpr *BTE;
466   const MaterializeTemporaryExpr *MTE;
467 
468 protected:
469   explicit TemporaryObjectConstructionContext(
470       ConstructionContext::Kind K, const CXXBindTemporaryExpr *BTE,
471       const MaterializeTemporaryExpr *MTE)
472       : ConstructionContext(K), BTE(BTE), MTE(MTE) {
473     // Both BTE and MTE can be null here, all combinations possible.
474     // Even though for now at least one should be non-null, we simply haven't
475     // implemented the other case yet (this would be a temporary in the middle
476     // of nowhere that doesn't have a non-trivial destructor).
477   }
478 
479 public:
480   /// CXXBindTemporaryExpr here is non-null as long as the temporary has
481   /// a non-trivial destructor.
482   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const {
483     return BTE;
484   }
485 
486   /// MaterializeTemporaryExpr is non-null as long as the temporary is actually
487   /// used after construction, eg. by binding to a reference (lifetime
488   /// extension), accessing a field, calling a method, or passing it into
489   /// a function (an elidable copy or move constructor would be a common
490   /// example) by reference.
491   const MaterializeTemporaryExpr *getMaterializedTemporaryExpr() const {
492     return MTE;
493   }
494 
495   static bool classof(const ConstructionContext *CC) {
496     return CC->getKind() >= TEMPORARY_BEGIN && CC->getKind() <= TEMPORARY_END;
497   }
498 };
499 
500 /// Represents a temporary object that is not constructed for the purpose of
501 /// being immediately copied/moved by an elidable copy/move-constructor.
502 /// This includes temporary objects "in the middle of nowhere" like T(123) and
503 /// lifetime-extended temporaries.
504 class SimpleTemporaryObjectConstructionContext
505     : public TemporaryObjectConstructionContext {
506   friend class ConstructionContext; // Allows to create<>() itself.
507 
508   explicit SimpleTemporaryObjectConstructionContext(
509       const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE)
510       : TemporaryObjectConstructionContext(
511             ConstructionContext::SimpleTemporaryObjectKind, BTE, MTE) {}
512 
513 public:
514   static bool classof(const ConstructionContext *CC) {
515     return CC->getKind() == SimpleTemporaryObjectKind;
516   }
517 };
518 
519 /// Represents a temporary object that is constructed for the sole purpose
520 /// of being immediately copied by an elidable copy/move constructor.
521 /// For example, T t = T(123); includes a temporary T(123) that is immediately
522 /// copied to variable t. In such cases the elidable copy can (but not
523 /// necessarily should) be omitted ("elided") accodring to the rules of the
524 /// language; the constructor would then construct variable t directly.
525 /// This construction context contains information of the elidable constructor
526 /// and its respective construction context.
527 class ElidedTemporaryObjectConstructionContext
528     : public TemporaryObjectConstructionContext {
529   const CXXConstructExpr *ElidedCE;
530   const ConstructionContext *ElidedCC;
531 
532   friend class ConstructionContext; // Allows to create<>() itself.
533 
534   explicit ElidedTemporaryObjectConstructionContext(
535       const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE,
536       const CXXConstructExpr *ElidedCE, const ConstructionContext *ElidedCC)
537       : TemporaryObjectConstructionContext(
538             ConstructionContext::ElidedTemporaryObjectKind, BTE, MTE),
539         ElidedCE(ElidedCE), ElidedCC(ElidedCC) {
540     // Elided constructor and its context should be either both specified
541     // or both unspecified. In the former case, the constructor must be
542     // elidable.
543     assert(ElidedCE && ElidedCE->isElidable() && ElidedCC);
544   }
545 
546 public:
547   const CXXConstructExpr *getConstructorAfterElision() const {
548     return ElidedCE;
549   }
550 
551   const ConstructionContext *getConstructionContextAfterElision() const {
552     return ElidedCC;
553   }
554 
555   static bool classof(const ConstructionContext *CC) {
556     return CC->getKind() == ElidedTemporaryObjectKind;
557   }
558 };
559 
560 class ReturnedValueConstructionContext : public ConstructionContext {
561   const ReturnStmt *RS;
562 
563 protected:
564   explicit ReturnedValueConstructionContext(ConstructionContext::Kind K,
565                                             const ReturnStmt *RS)
566       : ConstructionContext(K), RS(RS) {
567     assert(classof(this));
568     assert(RS);
569   }
570 
571 public:
572   const ReturnStmt *getReturnStmt() const { return RS; }
573 
574   static bool classof(const ConstructionContext *CC) {
575     return CC->getKind() >= RETURNED_VALUE_BEGIN &&
576            CC->getKind() <= RETURNED_VALUE_END;
577   }
578 };
579 
580 /// Represents a temporary object that is being immediately returned from a
581 /// function by value, eg. return t; or return T(123);. In this case there is
582 /// always going to be a constructor at the return site. However, the usual
583 /// temporary-related bureaucracy (CXXBindTemporaryExpr,
584 /// MaterializeTemporaryExpr) is normally located in the caller function's AST.
585 class SimpleReturnedValueConstructionContext
586     : public ReturnedValueConstructionContext {
587   friend class ConstructionContext; // Allows to create<>() itself.
588 
589   explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS)
590       : ReturnedValueConstructionContext(
591             ConstructionContext::SimpleReturnedValueKind, RS) {}
592 
593 public:
594   static bool classof(const ConstructionContext *CC) {
595     return CC->getKind() == SimpleReturnedValueKind;
596   }
597 };
598 
599 /// Represents a temporary object that is being immediately returned from a
600 /// function by value, eg. return t; or return T(123); in C++17.
601 /// In C++17 there is not going to be an elidable copy constructor at the
602 /// return site.  However, the usual temporary-related bureaucracy (CXXBindTemporaryExpr,
603 /// MaterializeTemporaryExpr) is normally located in the caller function's AST.
604 /// Note that if the object has trivial destructor, then this code is
605 /// indistinguishable from a simple returned value constructor on the AST level;
606 /// in this case we provide a simple returned value construction context.
607 class CXX17ElidedCopyReturnedValueConstructionContext
608     : public ReturnedValueConstructionContext {
609   const CXXBindTemporaryExpr *BTE;
610 
611   friend class ConstructionContext; // Allows to create<>() itself.
612 
613   explicit CXX17ElidedCopyReturnedValueConstructionContext(
614       const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE)
615       : ReturnedValueConstructionContext(
616             ConstructionContext::CXX17ElidedCopyReturnedValueKind, RS),
617         BTE(BTE) {
618     assert(BTE);
619   }
620 
621 public:
622   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
623 
624   static bool classof(const ConstructionContext *CC) {
625     return CC->getKind() == CXX17ElidedCopyReturnedValueKind;
626   }
627 };
628 
629 class ArgumentConstructionContext : public ConstructionContext {
630   // The call of which the context is an argument.
631   const Expr *CE;
632 
633   // Which argument we're constructing. Note that when numbering between
634   // arguments and parameters is inconsistent (eg., operator calls),
635   // this is the index of the argument, not of the parameter.
636   unsigned Index;
637 
638   // Whether the object needs to be destroyed.
639   const CXXBindTemporaryExpr *BTE;
640 
641   friend class ConstructionContext; // Allows to create<>() itself.
642 
643   explicit ArgumentConstructionContext(const Expr *CE, unsigned Index,
644                                        const CXXBindTemporaryExpr *BTE)
645       : ConstructionContext(ArgumentKind), CE(CE),
646         Index(Index), BTE(BTE) {
647     assert(isa<CallExpr>(CE) || isa<CXXConstructExpr>(CE) ||
648            isa<ObjCMessageExpr>(CE));
649     // BTE is optional.
650   }
651 
652 public:
653   const Expr *getCallLikeExpr() const { return CE; }
654   unsigned getIndex() const { return Index; }
655   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
656 
657   static bool classof(const ConstructionContext *CC) {
658     return CC->getKind() == ArgumentKind;
659   }
660 };
661 
662 } // end namespace clang
663 
664 #endif // LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
665