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