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
23namespace 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.
28class ConstructionContextItem {
29public:
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
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
66private:
67  const void *const Data;
68  const ItemKind Kind;
69  const unsigned Index = 0;
70
71  bool hasStatement() const {
72    return Kind >= STATEMENT_KIND_BEGIN &&
73           Kind <= STATEMENT_KIND_END;
74  }
75
76  bool hasIndex() const {
77    return Kind >= STATEMENT_WITH_INDEX_KIND_BEGIN &&
78           Kind <= STATEMENT_WITH_INDEX_KIND_END;
79  }
80
81  bool hasInitializer() const {
82    return Kind >= INITIALIZER_KIND_BEGIN &&
83           Kind <= INITIALIZER_KIND_END;
84  }
85
86public:
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.
90  ConstructionContextItem(const DeclStmt *DS)
91      : Data(DS), Kind(VariableKind) {}
92
93  ConstructionContextItem(const CXXNewExpr *NE)
94      : Data(NE), Kind(NewAllocatorKind) {}
95
96  ConstructionContextItem(const ReturnStmt *RS)
97      : Data(RS), Kind(ReturnKind) {}
98
99  ConstructionContextItem(const MaterializeTemporaryExpr *MTE)
100      : Data(MTE), Kind(MaterializationKind) {}
101
102  ConstructionContextItem(const CXXBindTemporaryExpr *BTE,
103                          bool IsElided = false)
104      : Data(BTE),
105        Kind(IsElided ? ElidedDestructorKind : TemporaryDestructorKind) {}
106
107  ConstructionContextItem(const CXXConstructExpr *CE)
108      : Data(CE), Kind(ElidableConstructorKind) {}
109
110  ConstructionContextItem(const CallExpr *CE, unsigned Index)
111      : Data(CE), Kind(ArgumentKind), Index(Index) {}
112
113  ConstructionContextItem(const CXXConstructExpr *CE, unsigned Index)
114      : Data(CE), Kind(ArgumentKind), Index(Index) {}
115
116  ConstructionContextItem(const CXXInheritedCtorInitExpr *CE, unsigned Index)
117      : Data(CE), Kind(ArgumentKind), Index(Index) {}
118
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.
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
130  ConstructionContextItem(const CXXCtorInitializer *Init)
131      : Data(Init), Kind(InitializerKind), Index(0) {}
132
133  ConstructionContextItem(const LambdaExpr *LE, unsigned Index)
134      : Data(LE), Kind(LambdaCaptureKind), Index(Index) {}
135
136  ItemKind getKind() const { return Kind; }
137
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).
146  const Stmt *getStmt() const {
147    assert(hasStatement());
148    return static_cast<const Stmt *>(Data);
149  }
150
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.
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.
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
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.
213class ConstructionContextLayer {
214  const ConstructionContextLayer *Parent = nullptr;
215  ConstructionContextItem Item;
216
217  ConstructionContextLayer(ConstructionContextItem Item,
218                           const ConstructionContextLayer *Parent)
219      : Parent(Parent), Item(Item) {}
220
221public:
222  static const ConstructionContextLayer *
223  create(BumpVectorContext &C, const ConstructionContextItem &Item,
224         const ConstructionContextLayer *Parent = nullptr);
225
226  const ConstructionContextItem &getItem() const { return Item; }
227  const ConstructionContextLayer *getParent() const { return Parent; }
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.
243class ConstructionContext {
244public:
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
267protected:
268  Kind K;
269
270  // Do not make public! These need to only be constructed
271  // via createFromLayers().
272  explicit ConstructionContext(Kind K) : K(K) {}
273
274private:
275  // A helper function for constructing an instance into a bump vector context.
276  template <typename T, typename... ArgTypes>
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
299public:
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
307  Kind getKind() const { return K; }
308
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.
316class VariableConstructionContext : public ConstructionContext {
317  const DeclStmt *DS;
318
319protected:
320  VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS)
321      : ConstructionContext(K), DS(DS) {
322    assert(classof(this));
323    assert(DS);
324  }
325
326public:
327  const DeclStmt *getDeclStmt() const { return DS; }
328
329  const ArrayInitLoopExpr *getArrayInitLoop() const override {
330    const auto *Var = cast<VarDecl>(DS->getSingleDecl());
331
332    return dyn_cast<ArrayInitLoopExpr>(Var->getInit());
333  }
334
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.
345class SimpleVariableConstructionContext : public VariableConstructionContext {
346  friend class ConstructionContext; // Allows to create<>() itself.
347
348  explicit SimpleVariableConstructionContext(const DeclStmt *DS)
349      : VariableConstructionContext(ConstructionContext::SimpleVariableKind,
350                                    DS) {}
351
352public:
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.
367class CXX17ElidedCopyVariableConstructionContext
368    : public VariableConstructionContext {
369  const CXXBindTemporaryExpr *BTE;
370
371  friend class ConstructionContext; // Allows to create<>() itself.
372
373  explicit CXX17ElidedCopyVariableConstructionContext(
374      const DeclStmt *DS, const CXXBindTemporaryExpr *BTE)
375      : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) {
376    assert(BTE);
377  }
378
379public:
380  const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
381
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.
388class ConstructorInitializerConstructionContext : public ConstructionContext {
389  const CXXCtorInitializer *I;
390
391protected:
392  explicit ConstructorInitializerConstructionContext(
393      ConstructionContext::Kind K, const CXXCtorInitializer *I)
394      : ConstructionContext(K), I(I) {
395    assert(classof(this));
396    assert(I);
397  }
398
399public:
400  const CXXCtorInitializer *getCXXCtorInitializer() const { return I; }
401
402  const ArrayInitLoopExpr *getArrayInitLoop() const override {
403    return dyn_cast<ArrayInitLoopExpr>(I->getInit());
404  }
405
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) { ... }.
414class SimpleConstructorInitializerConstructionContext
415    : public ConstructorInitializerConstructionContext {
416  friend class ConstructionContext; // Allows to create<>() itself.
417
418  explicit SimpleConstructorInitializerConstructionContext(
419      const CXXCtorInitializer *I)
420      : ConstructorInitializerConstructionContext(
421            ConstructionContext::SimpleConstructorInitializerKind, I) {}
422
423public:
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.
439class CXX17ElidedCopyConstructorInitializerConstructionContext
440    : public ConstructorInitializerConstructionContext {
441  const CXXBindTemporaryExpr *BTE;
442
443  friend class ConstructionContext; // Allows to create<>() itself.
444
445  explicit CXX17ElidedCopyConstructorInitializerConstructionContext(
446      const CXXCtorInitializer *I, const CXXBindTemporaryExpr *BTE)
447      : ConstructorInitializerConstructionContext(
448            CXX17ElidedCopyConstructorInitializerKind, I),
449        BTE(BTE) {
450    assert(BTE);
451  }
452
453public:
454  const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
455
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);.
463class NewAllocatedObjectConstructionContext : public ConstructionContext {
464  const CXXNewExpr *NE;
465
466  friend class ConstructionContext; // Allows to create<>() itself.
467
468  explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE)
469      : ConstructionContext(ConstructionContext::NewAllocatedObjectKind),
470        NE(NE) {
471    assert(NE);
472  }
473
474public:
475  const CXXNewExpr *getCXXNewExpr() const { return NE; }
476
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.
486class TemporaryObjectConstructionContext : public ConstructionContext {
487  const CXXBindTemporaryExpr *BTE;
488  const MaterializeTemporaryExpr *MTE;
489
490protected:
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
501public:
502  /// CXXBindTemporaryExpr here is non-null as long as the temporary has
503  /// a non-trivial destructor.
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.
513  const MaterializeTemporaryExpr *getMaterializedTemporaryExpr() const {
514    return MTE;
515  }
516
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.
526class SimpleTemporaryObjectConstructionContext
527    : public TemporaryObjectConstructionContext {
528  friend class ConstructionContext; // Allows to create<>() itself.
529
530  explicit SimpleTemporaryObjectConstructionContext(
531      const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE)
532      : TemporaryObjectConstructionContext(
533            ConstructionContext::SimpleTemporaryObjectKind, BTE, MTE) {}
534
535public:
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.
549class ElidedTemporaryObjectConstructionContext
550    : public TemporaryObjectConstructionContext {
551  const CXXConstructExpr *ElidedCE;
552  const ConstructionContext *ElidedCC;
553
554  friend class ConstructionContext; // Allows to create<>() itself.
555
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
568public:
569  const CXXConstructExpr *getConstructorAfterElision() const {
570    return ElidedCE;
571  }
572
573  const ConstructionContext *getConstructionContextAfterElision() const {
574    return ElidedCC;
575  }
576
577  static bool classof(const ConstructionContext *CC) {
578    return CC->getKind() == ElidedTemporaryObjectKind;
579  }
580};
581
582class ReturnedValueConstructionContext : public ConstructionContext {
583  const ReturnStmt *RS;
584
585protected:
586  explicit ReturnedValueConstructionContext(ConstructionContext::Kind K,
587                                            const ReturnStmt *RS)
588      : ConstructionContext(K), RS(RS) {
589    assert(classof(this));
590    assert(RS);
591  }
592
593public:
594  const ReturnStmt *getReturnStmt() const { return RS; }
595
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.
607class SimpleReturnedValueConstructionContext
608    : public ReturnedValueConstructionContext {
609  friend class ConstructionContext; // Allows to create<>() itself.
610
611  explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS)
612      : ReturnedValueConstructionContext(
613            ConstructionContext::SimpleReturnedValueKind, RS) {}
614
615public:
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.
629class CXX17ElidedCopyReturnedValueConstructionContext
630    : public ReturnedValueConstructionContext {
631  const CXXBindTemporaryExpr *BTE;
632
633  friend class ConstructionContext; // Allows to create<>() itself.
634
635  explicit CXX17ElidedCopyReturnedValueConstructionContext(
636      const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE)
637      : ReturnedValueConstructionContext(
638            ConstructionContext::CXX17ElidedCopyReturnedValueKind, RS),
639        BTE(BTE) {
640    assert(BTE);
641  }
642
643public:
644  const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
645
646  static bool classof(const ConstructionContext *CC) {
647    return CC->getKind() == CXX17ElidedCopyReturnedValueKind;
648  }
649};
650
651class 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
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
674public:
675  const Expr *getCallLikeExpr() const { return CE; }
676  unsigned getIndex() const { return Index; }
677  const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
678
679  static bool classof(const ConstructionContext *CC) {
680    return CC->getKind() == ArgumentKind;
681  }
682};
683
684class 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
693  explicit LambdaCaptureConstructionContext(const LambdaExpr *LE,
694                                            unsigned Index)
695      : ConstructionContext(LambdaCaptureKind), LE(LE), Index(Index) {}
696
697public:
698  const LambdaExpr *getLambdaExpr() const { return LE; }
699  unsigned getIndex() const { return Index; }
700
701  const Expr *getInitializer() const {
702    return *(LE->capture_init_begin() + Index);
703  }
704
705  const FieldDecl *getFieldDecl() const {
706    auto It = LE->getLambdaClass()->field_begin();
707    std::advance(It, Index);
708    return *It;
709  }
710
711  const ArrayInitLoopExpr *getArrayInitLoop() const override {
712    return dyn_cast_or_null<ArrayInitLoopExpr>(getInitializer());
713  }
714
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