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 CXXInheritedCtorInitExpr *CE, unsigned Index)
114      : Data(CE), Kind(ArgumentKind), Index(Index) {}
115
116  ConstructionContextItem(const ObjCMessageExpr *ME, unsigned Index)
117      : Data(ME), Kind(ArgumentKind), Index(Index) {}
118
119  // A polymorphic version of the previous calls with dynamic type check.
120  ConstructionContextItem(const Expr *E, unsigned Index)
121      : Data(E), Kind(ArgumentKind), Index(Index) {
122    assert(isa<CallExpr>(E) || isa<CXXConstructExpr>(E) ||
123           isa<CXXInheritedCtorInitExpr>(E) || isa<ObjCMessageExpr>(E));
124  }
125
126  ConstructionContextItem(const CXXCtorInitializer *Init)
127      : Data(Init), Kind(InitializerKind), Index(0) {}
128
129  ItemKind getKind() const { return Kind; }
130
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).
139  const Stmt *getStmt() const {
140    assert(hasStatement());
141    return static_cast<const Stmt *>(Data);
142  }
143
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.
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.
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
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.
206class ConstructionContextLayer {
207  const ConstructionContextLayer *Parent = nullptr;
208  ConstructionContextItem Item;
209
210  ConstructionContextLayer(ConstructionContextItem Item,
211                           const ConstructionContextLayer *Parent)
212      : Parent(Parent), Item(Item) {}
213
214public:
215  static const ConstructionContextLayer *
216  create(BumpVectorContext &C, const ConstructionContextItem &Item,
217         const ConstructionContextLayer *Parent = nullptr);
218
219  const ConstructionContextItem &getItem() const { return Item; }
220  const ConstructionContextLayer *getParent() const { return Parent; }
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.
236class ConstructionContext {
237public:
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
259protected:
260  Kind K;
261
262  // Do not make public! These need to only be constructed
263  // via createFromLayers().
264  explicit ConstructionContext(Kind K) : K(K) {}
265
266private:
267  // A helper function for constructing an instance into a bump vector context.
268  template <typename T, typename... ArgTypes>
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
291public:
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
299  Kind getKind() const { return K; }
300};
301
302/// An abstract base class for local variable constructors.
303class VariableConstructionContext : public ConstructionContext {
304  const DeclStmt *DS;
305
306protected:
307  VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS)
308      : ConstructionContext(K), DS(DS) {
309    assert(classof(this));
310    assert(DS);
311  }
312
313public:
314  const DeclStmt *getDeclStmt() const { return DS; }
315
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.
326class SimpleVariableConstructionContext : public VariableConstructionContext {
327  friend class ConstructionContext; // Allows to create<>() itself.
328
329  explicit SimpleVariableConstructionContext(const DeclStmt *DS)
330      : VariableConstructionContext(ConstructionContext::SimpleVariableKind,
331                                    DS) {}
332
333public:
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.
348class CXX17ElidedCopyVariableConstructionContext
349    : public VariableConstructionContext {
350  const CXXBindTemporaryExpr *BTE;
351
352  friend class ConstructionContext; // Allows to create<>() itself.
353
354  explicit CXX17ElidedCopyVariableConstructionContext(
355      const DeclStmt *DS, const CXXBindTemporaryExpr *BTE)
356      : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) {
357    assert(BTE);
358  }
359
360public:
361  const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
362
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.
369class ConstructorInitializerConstructionContext : public ConstructionContext {
370  const CXXCtorInitializer *I;
371
372protected:
373  explicit ConstructorInitializerConstructionContext(
374      ConstructionContext::Kind K, const CXXCtorInitializer *I)
375      : ConstructionContext(K), I(I) {
376    assert(classof(this));
377    assert(I);
378  }
379
380public:
381  const CXXCtorInitializer *getCXXCtorInitializer() const { return I; }
382
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) { ... }.
391class SimpleConstructorInitializerConstructionContext
392    : public ConstructorInitializerConstructionContext {
393  friend class ConstructionContext; // Allows to create<>() itself.
394
395  explicit SimpleConstructorInitializerConstructionContext(
396      const CXXCtorInitializer *I)
397      : ConstructorInitializerConstructionContext(
398            ConstructionContext::SimpleConstructorInitializerKind, I) {}
399
400public:
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.
416class CXX17ElidedCopyConstructorInitializerConstructionContext
417    : public ConstructorInitializerConstructionContext {
418  const CXXBindTemporaryExpr *BTE;
419
420  friend class ConstructionContext; // Allows to create<>() itself.
421
422  explicit CXX17ElidedCopyConstructorInitializerConstructionContext(
423      const CXXCtorInitializer *I, const CXXBindTemporaryExpr *BTE)
424      : ConstructorInitializerConstructionContext(
425            CXX17ElidedCopyConstructorInitializerKind, I),
426        BTE(BTE) {
427    assert(BTE);
428  }
429
430public:
431  const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
432
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);.
440class NewAllocatedObjectConstructionContext : public ConstructionContext {
441  const CXXNewExpr *NE;
442
443  friend class ConstructionContext; // Allows to create<>() itself.
444
445  explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE)
446      : ConstructionContext(ConstructionContext::NewAllocatedObjectKind),
447        NE(NE) {
448    assert(NE);
449  }
450
451public:
452  const CXXNewExpr *getCXXNewExpr() const { return NE; }
453
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.
463class TemporaryObjectConstructionContext : public ConstructionContext {
464  const CXXBindTemporaryExpr *BTE;
465  const MaterializeTemporaryExpr *MTE;
466
467protected:
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
478public:
479  /// CXXBindTemporaryExpr here is non-null as long as the temporary has
480  /// a non-trivial destructor.
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.
490  const MaterializeTemporaryExpr *getMaterializedTemporaryExpr() const {
491    return MTE;
492  }
493
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.
503class SimpleTemporaryObjectConstructionContext
504    : public TemporaryObjectConstructionContext {
505  friend class ConstructionContext; // Allows to create<>() itself.
506
507  explicit SimpleTemporaryObjectConstructionContext(
508      const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE)
509      : TemporaryObjectConstructionContext(
510            ConstructionContext::SimpleTemporaryObjectKind, BTE, MTE) {}
511
512public:
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.
526class ElidedTemporaryObjectConstructionContext
527    : public TemporaryObjectConstructionContext {
528  const CXXConstructExpr *ElidedCE;
529  const ConstructionContext *ElidedCC;
530
531  friend class ConstructionContext; // Allows to create<>() itself.
532
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
545public:
546  const CXXConstructExpr *getConstructorAfterElision() const {
547    return ElidedCE;
548  }
549
550  const ConstructionContext *getConstructionContextAfterElision() const {
551    return ElidedCC;
552  }
553
554  static bool classof(const ConstructionContext *CC) {
555    return CC->getKind() == ElidedTemporaryObjectKind;
556  }
557};
558
559class ReturnedValueConstructionContext : public ConstructionContext {
560  const ReturnStmt *RS;
561
562protected:
563  explicit ReturnedValueConstructionContext(ConstructionContext::Kind K,
564                                            const ReturnStmt *RS)
565      : ConstructionContext(K), RS(RS) {
566    assert(classof(this));
567    assert(RS);
568  }
569
570public:
571  const ReturnStmt *getReturnStmt() const { return RS; }
572
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.
584class SimpleReturnedValueConstructionContext
585    : public ReturnedValueConstructionContext {
586  friend class ConstructionContext; // Allows to create<>() itself.
587
588  explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS)
589      : ReturnedValueConstructionContext(
590            ConstructionContext::SimpleReturnedValueKind, RS) {}
591
592public:
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.
606class CXX17ElidedCopyReturnedValueConstructionContext
607    : public ReturnedValueConstructionContext {
608  const CXXBindTemporaryExpr *BTE;
609
610  friend class ConstructionContext; // Allows to create<>() itself.
611
612  explicit CXX17ElidedCopyReturnedValueConstructionContext(
613      const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE)
614      : ReturnedValueConstructionContext(
615            ConstructionContext::CXX17ElidedCopyReturnedValueKind, RS),
616        BTE(BTE) {
617    assert(BTE);
618  }
619
620public:
621  const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
622
623  static bool classof(const ConstructionContext *CC) {
624    return CC->getKind() == CXX17ElidedCopyReturnedValueKind;
625  }
626};
627
628class 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
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
651public:
652  const Expr *getCallLikeExpr() const { return CE; }
653  unsigned getIndex() const { return Index; }
654  const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
655
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