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