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