Home | History | Annotate | Line # | Download | only in Analysis
      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 
     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 
     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 
     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.
     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.
    206 class ConstructionContextLayer {
    207   const ConstructionContextLayer *Parent = nullptr;
    208   ConstructionContextItem Item;
    209 
    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 
    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.
    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().
    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>
    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 
    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:
    307   VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS)
    308       : ConstructionContext(K), DS(DS) {
    309     assert(classof(this));
    310     assert(DS);
    311   }
    312 
    313 public:
    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.
    326 class 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 
    333 public:
    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 
    354   explicit CXX17ElidedCopyVariableConstructionContext(
    355       const DeclStmt *DS, const CXXBindTemporaryExpr *BTE)
    356       : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) {
    357     assert(BTE);
    358   }
    359 
    360 public:
    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.
    369 class ConstructorInitializerConstructionContext : public ConstructionContext {
    370   const CXXCtorInitializer *I;
    371 
    372 protected:
    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:
    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) { ... }.
    391 class 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 
    400 public:
    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 
    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:
    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);.
    440 class 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 
    451 public:
    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.
    463 class TemporaryObjectConstructionContext : public ConstructionContext {
    464   const CXXBindTemporaryExpr *BTE;
    465   const MaterializeTemporaryExpr *MTE;
    466 
    467 protected:
    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.
    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.
    503 class 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 
    512 public:
    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 
    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:
    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 
    559 class ReturnedValueConstructionContext : public ConstructionContext {
    560   const ReturnStmt *RS;
    561 
    562 protected:
    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:
    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.
    584 class 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 
    592 public:
    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 
    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:
    621   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
    622 
    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 
    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:
    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