- //===- ConstructionContext.h - CFG constructor information ------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // This file defines the ConstructionContext class and its sub-classes, 
- // which represent various different ways of constructing C++ objects 
- // with the additional information the users may want to know about 
- // the constructor. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H 
- #define LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H 
-   
- #include "clang/Analysis/Support/BumpVector.h" 
- #include "clang/AST/ExprCXX.h" 
- #include "clang/AST/ExprObjC.h" 
-   
- namespace clang { 
-   
- /// Represents a single point (AST node) in the program that requires attention 
- /// during construction of an object. ConstructionContext would be represented 
- /// as a list of such items. 
- class ConstructionContextItem { 
- public: 
-   enum ItemKind { 
-     VariableKind, 
-     NewAllocatorKind, 
-     ReturnKind, 
-     MaterializationKind, 
-     TemporaryDestructorKind, 
-     ElidedDestructorKind, 
-     ElidableConstructorKind, 
-     ArgumentKind, 
-     LambdaCaptureKind, 
-     STATEMENT_WITH_INDEX_KIND_BEGIN = ArgumentKind, 
-     STATEMENT_WITH_INDEX_KIND_END = LambdaCaptureKind, 
-     STATEMENT_KIND_BEGIN = VariableKind, 
-     STATEMENT_KIND_END = LambdaCaptureKind, 
-     InitializerKind, 
-     INITIALIZER_KIND_BEGIN = InitializerKind, 
-     INITIALIZER_KIND_END = InitializerKind 
-   }; 
-   
-   LLVM_DUMP_METHOD static StringRef getKindAsString(ItemKind K) { 
-     switch (K) { 
-       case VariableKind:            return "construct into local variable"; 
-       case NewAllocatorKind:        return "construct into new-allocator"; 
-       case ReturnKind:              return "construct into return address"; 
-       case MaterializationKind:     return "materialize temporary"; 
-       case TemporaryDestructorKind: return "destroy temporary"; 
-       case ElidedDestructorKind:    return "elide destructor"; 
-       case ElidableConstructorKind: return "elide constructor"; 
-       case ArgumentKind:            return "construct into argument"; 
-       case LambdaCaptureKind: 
-         return "construct into lambda captured variable"; 
-       case InitializerKind:         return "construct into member variable"; 
-     }; 
-     llvm_unreachable("Unknown ItemKind"); 
-   } 
-   
- private: 
-   const void *const Data; 
-   const ItemKind Kind; 
-   const unsigned Index = 0; 
-   
-   bool hasStatement() const { 
-     return Kind >= STATEMENT_KIND_BEGIN && 
-            Kind <= STATEMENT_KIND_END; 
-   } 
-   
-   bool hasIndex() const { 
-     return Kind >= STATEMENT_WITH_INDEX_KIND_BEGIN && 
-            Kind <= STATEMENT_WITH_INDEX_KIND_END; 
-   } 
-   
-   bool hasInitializer() const { 
-     return Kind >= INITIALIZER_KIND_BEGIN && 
-            Kind <= INITIALIZER_KIND_END; 
-   } 
-   
- public: 
-   // ConstructionContextItem should be simple enough so that it was easy to 
-   // re-construct it from the AST node it captures. For that reason we provide 
-   // simple implicit conversions from all sorts of supported AST nodes. 
-   ConstructionContextItem(const DeclStmt *DS) 
-       : Data(DS), Kind(VariableKind) {} 
-   
-   ConstructionContextItem(const CXXNewExpr *NE) 
-       : Data(NE), Kind(NewAllocatorKind) {} 
-   
-   ConstructionContextItem(const ReturnStmt *RS) 
-       : Data(RS), Kind(ReturnKind) {} 
-   
-   ConstructionContextItem(const MaterializeTemporaryExpr *MTE) 
-       : Data(MTE), Kind(MaterializationKind) {} 
-   
-   ConstructionContextItem(const CXXBindTemporaryExpr *BTE, 
-                           bool IsElided = false) 
-       : Data(BTE), 
-         Kind(IsElided ? ElidedDestructorKind : TemporaryDestructorKind) {} 
-   
-   ConstructionContextItem(const CXXConstructExpr *CE) 
-       : Data(CE), Kind(ElidableConstructorKind) {} 
-   
-   ConstructionContextItem(const CallExpr *CE, unsigned Index) 
-       : Data(CE), Kind(ArgumentKind), Index(Index) {} 
-   
-   ConstructionContextItem(const CXXConstructExpr *CE, unsigned Index) 
-       : Data(CE), Kind(ArgumentKind), Index(Index) {} 
-   
-   ConstructionContextItem(const CXXInheritedCtorInitExpr *CE, unsigned Index) 
-       : Data(CE), Kind(ArgumentKind), Index(Index) {} 
-   
-   ConstructionContextItem(const ObjCMessageExpr *ME, unsigned Index) 
-       : Data(ME), Kind(ArgumentKind), Index(Index) {} 
-   
-   // A polymorphic version of the previous calls with dynamic type check. 
-   ConstructionContextItem(const Expr *E, unsigned Index) 
-       : Data(E), Kind(ArgumentKind), Index(Index) { 
-     assert(isa<CallExpr>(E) || isa<CXXConstructExpr>(E) || 
-            isa<CXXDeleteExpr>(E) || isa<CXXInheritedCtorInitExpr>(E) || 
-            isa<ObjCMessageExpr>(E)); 
-   } 
-   
-   ConstructionContextItem(const CXXCtorInitializer *Init) 
-       : Data(Init), Kind(InitializerKind), Index(0) {} 
-   
-   ConstructionContextItem(const LambdaExpr *LE, unsigned Index) 
-       : Data(LE), Kind(LambdaCaptureKind), Index(Index) {} 
-   
-   ItemKind getKind() const { return Kind; } 
-   
-   LLVM_DUMP_METHOD StringRef getKindAsString() const { 
-     return getKindAsString(getKind()); 
-   } 
-   
-   /// The construction site - the statement that triggered the construction 
-   /// for one of its parts. For instance, stack variable declaration statement 
-   /// triggers construction of itself or its elements if it's an array, 
-   /// new-expression triggers construction of the newly allocated object(s). 
-   const Stmt *getStmt() const { 
-     assert(hasStatement()); 
-     return static_cast<const Stmt *>(Data); 
-   } 
-   
-   const Stmt *getStmtOrNull() const { 
-     return hasStatement() ? getStmt() : nullptr; 
-   } 
-   
-   /// The construction site is not necessarily a statement. It may also be a 
-   /// CXXCtorInitializer, which means that a member variable is being 
-   /// constructed during initialization of the object that contains it. 
-   const CXXCtorInitializer *getCXXCtorInitializer() const { 
-     assert(hasInitializer()); 
-     return static_cast<const CXXCtorInitializer *>(Data); 
-   } 
-   
-   /// If a single trigger statement triggers multiple constructors, they are 
-   /// usually being enumerated. This covers function argument constructors 
-   /// triggered by a call-expression and items in an initializer list triggered 
-   /// by an init-list-expression. 
-   unsigned getIndex() const { 
-     // This is a fairly specific request. Let's make sure the user knows 
-     // what he's doing. 
-     assert(hasIndex()); 
-     return Index; 
-   } 
-   
-   void Profile(llvm::FoldingSetNodeID &ID) const { 
-     ID.AddPointer(Data); 
-     ID.AddInteger(Kind); 
-     ID.AddInteger(Index); 
-   } 
-   
-   bool operator==(const ConstructionContextItem &Other) const { 
-     // For most kinds the Index comparison is trivially true, but 
-     // checking kind separately doesn't seem to be less expensive 
-     // than checking Index. Same in operator<(). 
-     return std::make_tuple(Data, Kind, Index) == 
-            std::make_tuple(Other.Data, Other.Kind, Other.Index); 
-   } 
-   
-   bool operator<(const ConstructionContextItem &Other) const { 
-     return std::make_tuple(Data, Kind, Index) < 
-            std::make_tuple(Other.Data, Other.Kind, Other.Index); 
-   } 
- }; 
-   
- /// Construction context can be seen as a linked list of multiple layers. 
- /// Sometimes a single trigger is not enough to describe the construction 
- /// site. That's what causing us to have a chain of "partial" construction 
- /// context layers. Some examples: 
- /// - A constructor within in an aggregate initializer list within a variable 
- ///   would have a construction context of the initializer list with 
- ///   the parent construction context of a variable. 
- /// - A constructor for a temporary that needs to be both destroyed 
- ///   and materialized into an elidable copy constructor would have a 
- ///   construction context of a CXXBindTemporaryExpr with the parent 
- ///   construction context of a MaterializeTemproraryExpr. 
- /// Not all of these are currently supported. 
- /// Layers are created gradually while traversing the AST, and layers that 
- /// represent the outmost AST nodes are built first, while the node that 
- /// immediately contains the constructor would be built last and capture the 
- /// previous layers as its parents. Construction context captures the last layer 
- /// (which has links to the previous layers) and classifies the seemingly 
- /// arbitrary chain of layers into one of the possible ways of constructing 
- /// an object in C++ for user-friendly experience. 
- class ConstructionContextLayer { 
-   const ConstructionContextLayer *Parent = nullptr; 
-   ConstructionContextItem Item; 
-   
-   ConstructionContextLayer(ConstructionContextItem Item, 
-                            const ConstructionContextLayer *Parent) 
-       : Parent(Parent), Item(Item) {} 
-   
- public: 
-   static const ConstructionContextLayer * 
-   create(BumpVectorContext &C, const ConstructionContextItem &Item, 
-          const ConstructionContextLayer *Parent = nullptr); 
-   
-   const ConstructionContextItem &getItem() const { return Item; } 
-   const ConstructionContextLayer *getParent() const { return Parent; } 
-   bool isLast() const { return !Parent; } 
-   
-   /// See if Other is a proper initial segment of this construction context 
-   /// in terms of the parent chain - i.e. a few first parents coincide and 
-   /// then the other context terminates but our context goes further - i.e., 
-   /// we are providing the same context that the other context provides, 
-   /// and a bit more above that. 
-   bool isStrictlyMoreSpecificThan(const ConstructionContextLayer *Other) const; 
- }; 
-   
-   
- /// ConstructionContext's subclasses describe different ways of constructing 
- /// an object in C++. The context re-captures the essential parent AST nodes 
- /// of the CXXConstructExpr it is assigned to and presents these nodes 
- /// through easy-to-understand accessor methods. 
- class ConstructionContext { 
- public: 
-   enum Kind { 
-     SimpleVariableKind, 
-     CXX17ElidedCopyVariableKind, 
-     VARIABLE_BEGIN = SimpleVariableKind, 
-     VARIABLE_END = CXX17ElidedCopyVariableKind, 
-     SimpleConstructorInitializerKind, 
-     CXX17ElidedCopyConstructorInitializerKind, 
-     INITIALIZER_BEGIN = SimpleConstructorInitializerKind, 
-     INITIALIZER_END = CXX17ElidedCopyConstructorInitializerKind, 
-     NewAllocatedObjectKind, 
-     SimpleTemporaryObjectKind, 
-     ElidedTemporaryObjectKind, 
-     TEMPORARY_BEGIN = SimpleTemporaryObjectKind, 
-     TEMPORARY_END = ElidedTemporaryObjectKind, 
-     SimpleReturnedValueKind, 
-     CXX17ElidedCopyReturnedValueKind, 
-     RETURNED_VALUE_BEGIN = SimpleReturnedValueKind, 
-     RETURNED_VALUE_END = CXX17ElidedCopyReturnedValueKind, 
-     ArgumentKind, 
-     LambdaCaptureKind 
-   }; 
-   
- protected: 
-   Kind K; 
-   
-   // Do not make public! These need to only be constructed 
-   // via createFromLayers(). 
-   explicit ConstructionContext(Kind K) : K(K) {} 
-   
- private: 
-   // A helper function for constructing an instance into a bump vector context. 
-   template <typename T, typename... ArgTypes> 
-   static T *create(BumpVectorContext &C, ArgTypes... Args) { 
-     auto *CC = C.getAllocator().Allocate<T>(); 
-     return new (CC) T(Args...); 
-   } 
-   
-   // A sub-routine of createFromLayers() that deals with temporary objects 
-   // that need to be materialized. The BTE argument is for the situation when 
-   // the object also needs to be bound for destruction. 
-   static const ConstructionContext *createMaterializedTemporaryFromLayers( 
-       BumpVectorContext &C, const MaterializeTemporaryExpr *MTE, 
-       const CXXBindTemporaryExpr *BTE, 
-       const ConstructionContextLayer *ParentLayer); 
-   
-   // A sub-routine of createFromLayers() that deals with temporary objects 
-   // that need to be bound for destruction. Automatically finds out if the 
-   // object also needs to be materialized and delegates to 
-   // createMaterializedTemporaryFromLayers() if necessary. 
-   static const ConstructionContext * 
-   createBoundTemporaryFromLayers( 
-       BumpVectorContext &C, const CXXBindTemporaryExpr *BTE, 
-       const ConstructionContextLayer *ParentLayer); 
-   
- public: 
-   /// Consume the construction context layer, together with its parent layers, 
-   /// and wrap it up into a complete construction context. May return null 
-   /// if layers do not form any supported construction context. 
-   static const ConstructionContext * 
-   createFromLayers(BumpVectorContext &C, 
-                    const ConstructionContextLayer *TopLayer); 
-   
-   Kind getKind() const { return K; } 
-   
-   virtual const ArrayInitLoopExpr *getArrayInitLoop() const { return nullptr; } 
-   
-   // Only declared to silence -Wnon-virtual-dtor warnings. 
-   virtual ~ConstructionContext() = default; 
- }; 
-   
- /// An abstract base class for local variable constructors. 
- class VariableConstructionContext : public ConstructionContext { 
-   const DeclStmt *DS; 
-   
- protected: 
-   VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS) 
-       : ConstructionContext(K), DS(DS) { 
-     assert(classof(this)); 
-     assert(DS); 
-   } 
-   
- public: 
-   const DeclStmt *getDeclStmt() const { return DS; } 
-   
-   const ArrayInitLoopExpr *getArrayInitLoop() const override { 
-     const auto *Var = cast<VarDecl>(DS->getSingleDecl()); 
-   
-     return dyn_cast<ArrayInitLoopExpr>(Var->getInit()); 
-   } 
-   
-   static bool classof(const ConstructionContext *CC) { 
-     return CC->getKind() >= VARIABLE_BEGIN && 
-            CC->getKind() <= VARIABLE_END; 
-   } 
- }; 
-   
- /// Represents construction into a simple local variable, eg. T var(123);. 
- /// If a variable has an initializer, eg. T var = makeT();, then the final 
- /// elidable copy-constructor from makeT() into var would also be a simple 
- /// variable constructor handled by this class. 
- class SimpleVariableConstructionContext : public VariableConstructionContext { 
-   friend class ConstructionContext; // Allows to create<>() itself. 
-   
-   explicit SimpleVariableConstructionContext(const DeclStmt *DS) 
-       : VariableConstructionContext(ConstructionContext::SimpleVariableKind, 
-                                     DS) {} 
-   
- public: 
-   static bool classof(const ConstructionContext *CC) { 
-     return CC->getKind() == SimpleVariableKind; 
-   } 
- }; 
-   
- /// Represents construction into a simple variable with an initializer syntax, 
- /// with a single constructor, eg. T var = makeT();. Such construction context 
- /// may only appear in C++17 because previously it was split into a temporary 
- /// object constructor and an elidable simple variable copy-constructor and 
- /// we were producing separate construction contexts for these constructors. 
- /// In C++17 we have a single construction context that combines both. 
- /// Note that if the object has trivial destructor, then this code is 
- /// indistinguishable from a simple variable constructor on the AST level; 
- /// in this case we provide a simple variable construction context. 
- class CXX17ElidedCopyVariableConstructionContext 
-     : public VariableConstructionContext { 
-   const CXXBindTemporaryExpr *BTE; 
-   
-   friend class ConstructionContext; // Allows to create<>() itself. 
-   
-   explicit CXX17ElidedCopyVariableConstructionContext( 
-       const DeclStmt *DS, const CXXBindTemporaryExpr *BTE) 
-       : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) { 
-     assert(BTE); 
-   } 
-   
- public: 
-   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; } 
-   
-   static bool classof(const ConstructionContext *CC) { 
-     return CC->getKind() == CXX17ElidedCopyVariableKind; 
-   } 
- }; 
-   
- // An abstract base class for constructor-initializer-based constructors. 
- class ConstructorInitializerConstructionContext : public ConstructionContext { 
-   const CXXCtorInitializer *I; 
-   
- protected: 
-   explicit ConstructorInitializerConstructionContext( 
-       ConstructionContext::Kind K, const CXXCtorInitializer *I) 
-       : ConstructionContext(K), I(I) { 
-     assert(classof(this)); 
-     assert(I); 
-   } 
-   
- public: 
-   const CXXCtorInitializer *getCXXCtorInitializer() const { return I; } 
-   
-   const ArrayInitLoopExpr *getArrayInitLoop() const override { 
-     return dyn_cast<ArrayInitLoopExpr>(I->getInit()); 
-   } 
-   
-   static bool classof(const ConstructionContext *CC) { 
-     return CC->getKind() >= INITIALIZER_BEGIN && 
-            CC->getKind() <= INITIALIZER_END; 
-   } 
- }; 
-   
- /// Represents construction into a field or a base class within a bigger object 
- /// via a constructor initializer, eg. T(): field(123) { ... }. 
- class SimpleConstructorInitializerConstructionContext 
-     : public ConstructorInitializerConstructionContext { 
-   friend class ConstructionContext; // Allows to create<>() itself. 
-   
-   explicit SimpleConstructorInitializerConstructionContext( 
-       const CXXCtorInitializer *I) 
-       : ConstructorInitializerConstructionContext( 
-             ConstructionContext::SimpleConstructorInitializerKind, I) {} 
-   
- public: 
-   static bool classof(const ConstructionContext *CC) { 
-     return CC->getKind() == SimpleConstructorInitializerKind; 
-   } 
- }; 
-   
- /// Represents construction into a field or a base class within a bigger object 
- /// via a constructor initializer, with a single constructor, eg. 
- /// T(): field(Field(123)) { ... }. Such construction context may only appear 
- /// in C++17 because previously it was split into a temporary object constructor 
- /// and an elidable simple constructor-initializer copy-constructor and we were 
- /// producing separate construction contexts for these constructors. In C++17 
- /// we have a single construction context that combines both. Note that if the 
- /// object has trivial destructor, then this code is indistinguishable from 
- /// a simple constructor-initializer constructor on the AST level; in this case 
- /// we provide a simple constructor-initializer construction context. 
- class CXX17ElidedCopyConstructorInitializerConstructionContext 
-     : public ConstructorInitializerConstructionContext { 
-   const CXXBindTemporaryExpr *BTE; 
-   
-   friend class ConstructionContext; // Allows to create<>() itself. 
-   
-   explicit CXX17ElidedCopyConstructorInitializerConstructionContext( 
-       const CXXCtorInitializer *I, const CXXBindTemporaryExpr *BTE) 
-       : ConstructorInitializerConstructionContext( 
-             CXX17ElidedCopyConstructorInitializerKind, I), 
-         BTE(BTE) { 
-     assert(BTE); 
-   } 
-   
- public: 
-   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; } 
-   
-   static bool classof(const ConstructionContext *CC) { 
-     return CC->getKind() == CXX17ElidedCopyConstructorInitializerKind; 
-   } 
- }; 
-   
- /// Represents immediate initialization of memory allocated by operator new, 
- /// eg. new T(123);. 
- class NewAllocatedObjectConstructionContext : public ConstructionContext { 
-   const CXXNewExpr *NE; 
-   
-   friend class ConstructionContext; // Allows to create<>() itself. 
-   
-   explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE) 
-       : ConstructionContext(ConstructionContext::NewAllocatedObjectKind), 
-         NE(NE) { 
-     assert(NE); 
-   } 
-   
- public: 
-   const CXXNewExpr *getCXXNewExpr() const { return NE; } 
-   
-   static bool classof(const ConstructionContext *CC) { 
-     return CC->getKind() == NewAllocatedObjectKind; 
-   } 
- }; 
-   
- /// Represents a temporary object, eg. T(123), that does not immediately cross 
- /// function boundaries "by value"; constructors that construct function 
- /// value-type arguments or values that are immediately returned from the 
- /// function that returns a value receive separate construction context kinds. 
- class TemporaryObjectConstructionContext : public ConstructionContext { 
-   const CXXBindTemporaryExpr *BTE; 
-   const MaterializeTemporaryExpr *MTE; 
-   
- protected: 
-   explicit TemporaryObjectConstructionContext( 
-       ConstructionContext::Kind K, const CXXBindTemporaryExpr *BTE, 
-       const MaterializeTemporaryExpr *MTE) 
-       : ConstructionContext(K), BTE(BTE), MTE(MTE) { 
-     // Both BTE and MTE can be null here, all combinations possible. 
-     // Even though for now at least one should be non-null, we simply haven't 
-     // implemented the other case yet (this would be a temporary in the middle 
-     // of nowhere that doesn't have a non-trivial destructor). 
-   } 
-   
- public: 
-   /// CXXBindTemporaryExpr here is non-null as long as the temporary has 
-   /// a non-trivial destructor. 
-   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { 
-     return BTE; 
-   } 
-   
-   /// MaterializeTemporaryExpr is non-null as long as the temporary is actually 
-   /// used after construction, eg. by binding to a reference (lifetime 
-   /// extension), accessing a field, calling a method, or passing it into 
-   /// a function (an elidable copy or move constructor would be a common 
-   /// example) by reference. 
-   const MaterializeTemporaryExpr *getMaterializedTemporaryExpr() const { 
-     return MTE; 
-   } 
-   
-   static bool classof(const ConstructionContext *CC) { 
-     return CC->getKind() >= TEMPORARY_BEGIN && CC->getKind() <= TEMPORARY_END; 
-   } 
- }; 
-   
- /// Represents a temporary object that is not constructed for the purpose of 
- /// being immediately copied/moved by an elidable copy/move-constructor. 
- /// This includes temporary objects "in the middle of nowhere" like T(123) and 
- /// lifetime-extended temporaries. 
- class SimpleTemporaryObjectConstructionContext 
-     : public TemporaryObjectConstructionContext { 
-   friend class ConstructionContext; // Allows to create<>() itself. 
-   
-   explicit SimpleTemporaryObjectConstructionContext( 
-       const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE) 
-       : TemporaryObjectConstructionContext( 
-             ConstructionContext::SimpleTemporaryObjectKind, BTE, MTE) {} 
-   
- public: 
-   static bool classof(const ConstructionContext *CC) { 
-     return CC->getKind() == SimpleTemporaryObjectKind; 
-   } 
- }; 
-   
- /// Represents a temporary object that is constructed for the sole purpose 
- /// of being immediately copied by an elidable copy/move constructor. 
- /// For example, T t = T(123); includes a temporary T(123) that is immediately 
- /// copied to variable t. In such cases the elidable copy can (but not 
- /// necessarily should) be omitted ("elided") according to the rules of the 
- /// language; the constructor would then construct variable t directly. 
- /// This construction context contains information of the elidable constructor 
- /// and its respective construction context. 
- class ElidedTemporaryObjectConstructionContext 
-     : public TemporaryObjectConstructionContext { 
-   const CXXConstructExpr *ElidedCE; 
-   const ConstructionContext *ElidedCC; 
-   
-   friend class ConstructionContext; // Allows to create<>() itself. 
-   
-   explicit ElidedTemporaryObjectConstructionContext( 
-       const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE, 
-       const CXXConstructExpr *ElidedCE, const ConstructionContext *ElidedCC) 
-       : TemporaryObjectConstructionContext( 
-             ConstructionContext::ElidedTemporaryObjectKind, BTE, MTE), 
-         ElidedCE(ElidedCE), ElidedCC(ElidedCC) { 
-     // Elided constructor and its context should be either both specified 
-     // or both unspecified. In the former case, the constructor must be 
-     // elidable. 
-     assert(ElidedCE && ElidedCE->isElidable() && ElidedCC); 
-   } 
-   
- public: 
-   const CXXConstructExpr *getConstructorAfterElision() const { 
-     return ElidedCE; 
-   } 
-   
-   const ConstructionContext *getConstructionContextAfterElision() const { 
-     return ElidedCC; 
-   } 
-   
-   static bool classof(const ConstructionContext *CC) { 
-     return CC->getKind() == ElidedTemporaryObjectKind; 
-   } 
- }; 
-   
- class ReturnedValueConstructionContext : public ConstructionContext { 
-   const ReturnStmt *RS; 
-   
- protected: 
-   explicit ReturnedValueConstructionContext(ConstructionContext::Kind K, 
-                                             const ReturnStmt *RS) 
-       : ConstructionContext(K), RS(RS) { 
-     assert(classof(this)); 
-     assert(RS); 
-   } 
-   
- public: 
-   const ReturnStmt *getReturnStmt() const { return RS; } 
-   
-   static bool classof(const ConstructionContext *CC) { 
-     return CC->getKind() >= RETURNED_VALUE_BEGIN && 
-            CC->getKind() <= RETURNED_VALUE_END; 
-   } 
- }; 
-   
- /// Represents a temporary object that is being immediately returned from a 
- /// function by value, eg. return t; or return T(123);. In this case there is 
- /// always going to be a constructor at the return site. However, the usual 
- /// temporary-related bureaucracy (CXXBindTemporaryExpr, 
- /// MaterializeTemporaryExpr) is normally located in the caller function's AST. 
- class SimpleReturnedValueConstructionContext 
-     : public ReturnedValueConstructionContext { 
-   friend class ConstructionContext; // Allows to create<>() itself. 
-   
-   explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS) 
-       : ReturnedValueConstructionContext( 
-             ConstructionContext::SimpleReturnedValueKind, RS) {} 
-   
- public: 
-   static bool classof(const ConstructionContext *CC) { 
-     return CC->getKind() == SimpleReturnedValueKind; 
-   } 
- }; 
-   
- /// Represents a temporary object that is being immediately returned from a 
- /// function by value, eg. return t; or return T(123); in C++17. 
- /// In C++17 there is not going to be an elidable copy constructor at the 
- /// return site.  However, the usual temporary-related bureaucracy (CXXBindTemporaryExpr, 
- /// MaterializeTemporaryExpr) is normally located in the caller function's AST. 
- /// Note that if the object has trivial destructor, then this code is 
- /// indistinguishable from a simple returned value constructor on the AST level; 
- /// in this case we provide a simple returned value construction context. 
- class CXX17ElidedCopyReturnedValueConstructionContext 
-     : public ReturnedValueConstructionContext { 
-   const CXXBindTemporaryExpr *BTE; 
-   
-   friend class ConstructionContext; // Allows to create<>() itself. 
-   
-   explicit CXX17ElidedCopyReturnedValueConstructionContext( 
-       const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE) 
-       : ReturnedValueConstructionContext( 
-             ConstructionContext::CXX17ElidedCopyReturnedValueKind, RS), 
-         BTE(BTE) { 
-     assert(BTE); 
-   } 
-   
- public: 
-   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; } 
-   
-   static bool classof(const ConstructionContext *CC) { 
-     return CC->getKind() == CXX17ElidedCopyReturnedValueKind; 
-   } 
- }; 
-   
- class ArgumentConstructionContext : public ConstructionContext { 
-   // The call of which the context is an argument. 
-   const Expr *CE; 
-   
-   // Which argument we're constructing. Note that when numbering between 
-   // arguments and parameters is inconsistent (eg., operator calls), 
-   // this is the index of the argument, not of the parameter. 
-   unsigned Index; 
-   
-   // Whether the object needs to be destroyed. 
-   const CXXBindTemporaryExpr *BTE; 
-   
-   friend class ConstructionContext; // Allows to create<>() itself. 
-   
-   explicit ArgumentConstructionContext(const Expr *CE, unsigned Index, 
-                                        const CXXBindTemporaryExpr *BTE) 
-       : ConstructionContext(ArgumentKind), CE(CE), 
-         Index(Index), BTE(BTE) { 
-     assert(isa<CallExpr>(CE) || isa<CXXConstructExpr>(CE) || 
-            isa<ObjCMessageExpr>(CE)); 
-     // BTE is optional. 
-   } 
-   
- public: 
-   const Expr *getCallLikeExpr() const { return CE; } 
-   unsigned getIndex() const { return Index; } 
-   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; } 
-   
-   static bool classof(const ConstructionContext *CC) { 
-     return CC->getKind() == ArgumentKind; 
-   } 
- }; 
-   
- class LambdaCaptureConstructionContext : public ConstructionContext { 
-   // The lambda of which the initializer we capture. 
-   const LambdaExpr *LE; 
-   
-   // Index of the captured element in the captured list. 
-   unsigned Index; 
-   
-   friend class ConstructionContext; // Allows to create<>() itself. 
-   
-   explicit LambdaCaptureConstructionContext(const LambdaExpr *LE, 
-                                             unsigned Index) 
-       : ConstructionContext(LambdaCaptureKind), LE(LE), Index(Index) {} 
-   
- public: 
-   const LambdaExpr *getLambdaExpr() const { return LE; } 
-   unsigned getIndex() const { return Index; } 
-   
-   const Expr *getInitializer() const { 
-     return *(LE->capture_init_begin() + Index); 
-   } 
-   
-   const FieldDecl *getFieldDecl() const { 
-     auto It = LE->getLambdaClass()->field_begin(); 
-     std::advance(It, Index); 
-     return *It; 
-   } 
-   
-   const ArrayInitLoopExpr *getArrayInitLoop() const override { 
-     return dyn_cast_or_null<ArrayInitLoopExpr>(getInitializer()); 
-   } 
-   
-   static bool classof(const ConstructionContext *CC) { 
-     return CC->getKind() == LambdaCaptureKind; 
-   } 
- }; 
-   
- } // end namespace clang 
-   
- #endif // LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H 
-