Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:26

0001 //===- ConstructionContext.h - CFG constructor information ------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file defines the ConstructionContext class and its sub-classes,
0010 // which represent various different ways of constructing C++ objects
0011 // with the additional information the users may want to know about
0012 // the constructor.
0013 //
0014 //===----------------------------------------------------------------------===//
0015 
0016 #ifndef LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
0017 #define LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
0018 
0019 #include "clang/Analysis/Support/BumpVector.h"
0020 #include "clang/AST/ExprCXX.h"
0021 #include "clang/AST/ExprObjC.h"
0022 
0023 namespace clang {
0024 
0025 /// Represents a single point (AST node) in the program that requires attention
0026 /// during construction of an object. ConstructionContext would be represented
0027 /// as a list of such items.
0028 class ConstructionContextItem {
0029 public:
0030   enum ItemKind {
0031     VariableKind,
0032     NewAllocatorKind,
0033     ReturnKind,
0034     MaterializationKind,
0035     TemporaryDestructorKind,
0036     ElidedDestructorKind,
0037     ElidableConstructorKind,
0038     ArgumentKind,
0039     LambdaCaptureKind,
0040     STATEMENT_WITH_INDEX_KIND_BEGIN = ArgumentKind,
0041     STATEMENT_WITH_INDEX_KIND_END = LambdaCaptureKind,
0042     STATEMENT_KIND_BEGIN = VariableKind,
0043     STATEMENT_KIND_END = LambdaCaptureKind,
0044     InitializerKind,
0045     INITIALIZER_KIND_BEGIN = InitializerKind,
0046     INITIALIZER_KIND_END = InitializerKind
0047   };
0048 
0049   LLVM_DUMP_METHOD static StringRef getKindAsString(ItemKind K) {
0050     switch (K) {
0051       case VariableKind:            return "construct into local variable";
0052       case NewAllocatorKind:        return "construct into new-allocator";
0053       case ReturnKind:              return "construct into return address";
0054       case MaterializationKind:     return "materialize temporary";
0055       case TemporaryDestructorKind: return "destroy temporary";
0056       case ElidedDestructorKind:    return "elide destructor";
0057       case ElidableConstructorKind: return "elide constructor";
0058       case ArgumentKind:            return "construct into argument";
0059       case LambdaCaptureKind:
0060         return "construct into lambda captured variable";
0061       case InitializerKind:         return "construct into member variable";
0062     };
0063     llvm_unreachable("Unknown ItemKind");
0064   }
0065 
0066 private:
0067   const void *const Data;
0068   const ItemKind Kind;
0069   const unsigned Index = 0;
0070 
0071   bool hasStatement() const {
0072     return Kind >= STATEMENT_KIND_BEGIN &&
0073            Kind <= STATEMENT_KIND_END;
0074   }
0075 
0076   bool hasIndex() const {
0077     return Kind >= STATEMENT_WITH_INDEX_KIND_BEGIN &&
0078            Kind <= STATEMENT_WITH_INDEX_KIND_END;
0079   }
0080 
0081   bool hasInitializer() const {
0082     return Kind >= INITIALIZER_KIND_BEGIN &&
0083            Kind <= INITIALIZER_KIND_END;
0084   }
0085 
0086 public:
0087   // ConstructionContextItem should be simple enough so that it was easy to
0088   // re-construct it from the AST node it captures. For that reason we provide
0089   // simple implicit conversions from all sorts of supported AST nodes.
0090   ConstructionContextItem(const DeclStmt *DS)
0091       : Data(DS), Kind(VariableKind) {}
0092 
0093   ConstructionContextItem(const CXXNewExpr *NE)
0094       : Data(NE), Kind(NewAllocatorKind) {}
0095 
0096   ConstructionContextItem(const ReturnStmt *RS)
0097       : Data(RS), Kind(ReturnKind) {}
0098 
0099   ConstructionContextItem(const MaterializeTemporaryExpr *MTE)
0100       : Data(MTE), Kind(MaterializationKind) {}
0101 
0102   ConstructionContextItem(const CXXBindTemporaryExpr *BTE,
0103                           bool IsElided = false)
0104       : Data(BTE),
0105         Kind(IsElided ? ElidedDestructorKind : TemporaryDestructorKind) {}
0106 
0107   ConstructionContextItem(const CXXConstructExpr *CE)
0108       : Data(CE), Kind(ElidableConstructorKind) {}
0109 
0110   ConstructionContextItem(const CallExpr *CE, unsigned Index)
0111       : Data(CE), Kind(ArgumentKind), Index(Index) {}
0112 
0113   ConstructionContextItem(const CXXConstructExpr *CE, unsigned Index)
0114       : Data(CE), Kind(ArgumentKind), Index(Index) {}
0115 
0116   ConstructionContextItem(const CXXInheritedCtorInitExpr *CE, unsigned Index)
0117       : Data(CE), Kind(ArgumentKind), Index(Index) {}
0118 
0119   ConstructionContextItem(const ObjCMessageExpr *ME, unsigned Index)
0120       : Data(ME), Kind(ArgumentKind), Index(Index) {}
0121 
0122   // A polymorphic version of the previous calls with dynamic type check.
0123   ConstructionContextItem(const Expr *E, unsigned Index)
0124       : Data(E), Kind(ArgumentKind), Index(Index) {
0125     assert(isa<CallExpr>(E) || isa<CXXConstructExpr>(E) ||
0126            isa<CXXDeleteExpr>(E) || isa<CXXInheritedCtorInitExpr>(E) ||
0127            isa<ObjCMessageExpr>(E));
0128   }
0129 
0130   ConstructionContextItem(const CXXCtorInitializer *Init)
0131       : Data(Init), Kind(InitializerKind), Index(0) {}
0132 
0133   ConstructionContextItem(const LambdaExpr *LE, unsigned Index)
0134       : Data(LE), Kind(LambdaCaptureKind), Index(Index) {}
0135 
0136   ItemKind getKind() const { return Kind; }
0137 
0138   LLVM_DUMP_METHOD StringRef getKindAsString() const {
0139     return getKindAsString(getKind());
0140   }
0141 
0142   /// The construction site - the statement that triggered the construction
0143   /// for one of its parts. For instance, stack variable declaration statement
0144   /// triggers construction of itself or its elements if it's an array,
0145   /// new-expression triggers construction of the newly allocated object(s).
0146   const Stmt *getStmt() const {
0147     assert(hasStatement());
0148     return static_cast<const Stmt *>(Data);
0149   }
0150 
0151   const Stmt *getStmtOrNull() const {
0152     return hasStatement() ? getStmt() : nullptr;
0153   }
0154 
0155   /// The construction site is not necessarily a statement. It may also be a
0156   /// CXXCtorInitializer, which means that a member variable is being
0157   /// constructed during initialization of the object that contains it.
0158   const CXXCtorInitializer *getCXXCtorInitializer() const {
0159     assert(hasInitializer());
0160     return static_cast<const CXXCtorInitializer *>(Data);
0161   }
0162 
0163   /// If a single trigger statement triggers multiple constructors, they are
0164   /// usually being enumerated. This covers function argument constructors
0165   /// triggered by a call-expression and items in an initializer list triggered
0166   /// by an init-list-expression.
0167   unsigned getIndex() const {
0168     // This is a fairly specific request. Let's make sure the user knows
0169     // what he's doing.
0170     assert(hasIndex());
0171     return Index;
0172   }
0173 
0174   void Profile(llvm::FoldingSetNodeID &ID) const {
0175     ID.AddPointer(Data);
0176     ID.AddInteger(Kind);
0177     ID.AddInteger(Index);
0178   }
0179 
0180   bool operator==(const ConstructionContextItem &Other) const {
0181     // For most kinds the Index comparison is trivially true, but
0182     // checking kind separately doesn't seem to be less expensive
0183     // than checking Index. Same in operator<().
0184     return std::make_tuple(Data, Kind, Index) ==
0185            std::make_tuple(Other.Data, Other.Kind, Other.Index);
0186   }
0187 
0188   bool operator<(const ConstructionContextItem &Other) const {
0189     return std::make_tuple(Data, Kind, Index) <
0190            std::make_tuple(Other.Data, Other.Kind, Other.Index);
0191   }
0192 };
0193 
0194 /// Construction context can be seen as a linked list of multiple layers.
0195 /// Sometimes a single trigger is not enough to describe the construction
0196 /// site. That's what causing us to have a chain of "partial" construction
0197 /// context layers. Some examples:
0198 /// - A constructor within in an aggregate initializer list within a variable
0199 ///   would have a construction context of the initializer list with
0200 ///   the parent construction context of a variable.
0201 /// - A constructor for a temporary that needs to be both destroyed
0202 ///   and materialized into an elidable copy constructor would have a
0203 ///   construction context of a CXXBindTemporaryExpr with the parent
0204 ///   construction context of a MaterializeTemproraryExpr.
0205 /// Not all of these are currently supported.
0206 /// Layers are created gradually while traversing the AST, and layers that
0207 /// represent the outmost AST nodes are built first, while the node that
0208 /// immediately contains the constructor would be built last and capture the
0209 /// previous layers as its parents. Construction context captures the last layer
0210 /// (which has links to the previous layers) and classifies the seemingly
0211 /// arbitrary chain of layers into one of the possible ways of constructing
0212 /// an object in C++ for user-friendly experience.
0213 class ConstructionContextLayer {
0214   const ConstructionContextLayer *Parent = nullptr;
0215   ConstructionContextItem Item;
0216 
0217   ConstructionContextLayer(ConstructionContextItem Item,
0218                            const ConstructionContextLayer *Parent)
0219       : Parent(Parent), Item(Item) {}
0220 
0221 public:
0222   static const ConstructionContextLayer *
0223   create(BumpVectorContext &C, const ConstructionContextItem &Item,
0224          const ConstructionContextLayer *Parent = nullptr);
0225 
0226   const ConstructionContextItem &getItem() const { return Item; }
0227   const ConstructionContextLayer *getParent() const { return Parent; }
0228   bool isLast() const { return !Parent; }
0229 
0230   /// See if Other is a proper initial segment of this construction context
0231   /// in terms of the parent chain - i.e. a few first parents coincide and
0232   /// then the other context terminates but our context goes further - i.e.,
0233   /// we are providing the same context that the other context provides,
0234   /// and a bit more above that.
0235   bool isStrictlyMoreSpecificThan(const ConstructionContextLayer *Other) const;
0236 };
0237 
0238 
0239 /// ConstructionContext's subclasses describe different ways of constructing
0240 /// an object in C++. The context re-captures the essential parent AST nodes
0241 /// of the CXXConstructExpr it is assigned to and presents these nodes
0242 /// through easy-to-understand accessor methods.
0243 class ConstructionContext {
0244 public:
0245   enum Kind {
0246     SimpleVariableKind,
0247     CXX17ElidedCopyVariableKind,
0248     VARIABLE_BEGIN = SimpleVariableKind,
0249     VARIABLE_END = CXX17ElidedCopyVariableKind,
0250     SimpleConstructorInitializerKind,
0251     CXX17ElidedCopyConstructorInitializerKind,
0252     INITIALIZER_BEGIN = SimpleConstructorInitializerKind,
0253     INITIALIZER_END = CXX17ElidedCopyConstructorInitializerKind,
0254     NewAllocatedObjectKind,
0255     SimpleTemporaryObjectKind,
0256     ElidedTemporaryObjectKind,
0257     TEMPORARY_BEGIN = SimpleTemporaryObjectKind,
0258     TEMPORARY_END = ElidedTemporaryObjectKind,
0259     SimpleReturnedValueKind,
0260     CXX17ElidedCopyReturnedValueKind,
0261     RETURNED_VALUE_BEGIN = SimpleReturnedValueKind,
0262     RETURNED_VALUE_END = CXX17ElidedCopyReturnedValueKind,
0263     ArgumentKind,
0264     LambdaCaptureKind
0265   };
0266 
0267 protected:
0268   Kind K;
0269 
0270   // Do not make public! These need to only be constructed
0271   // via createFromLayers().
0272   explicit ConstructionContext(Kind K) : K(K) {}
0273 
0274 private:
0275   // A helper function for constructing an instance into a bump vector context.
0276   template <typename T, typename... ArgTypes>
0277   static T *create(BumpVectorContext &C, ArgTypes... Args) {
0278     auto *CC = C.getAllocator().Allocate<T>();
0279     return new (CC) T(Args...);
0280   }
0281 
0282   // A sub-routine of createFromLayers() that deals with temporary objects
0283   // that need to be materialized. The BTE argument is for the situation when
0284   // the object also needs to be bound for destruction.
0285   static const ConstructionContext *createMaterializedTemporaryFromLayers(
0286       BumpVectorContext &C, const MaterializeTemporaryExpr *MTE,
0287       const CXXBindTemporaryExpr *BTE,
0288       const ConstructionContextLayer *ParentLayer);
0289 
0290   // A sub-routine of createFromLayers() that deals with temporary objects
0291   // that need to be bound for destruction. Automatically finds out if the
0292   // object also needs to be materialized and delegates to
0293   // createMaterializedTemporaryFromLayers() if necessary.
0294   static const ConstructionContext *
0295   createBoundTemporaryFromLayers(
0296       BumpVectorContext &C, const CXXBindTemporaryExpr *BTE,
0297       const ConstructionContextLayer *ParentLayer);
0298 
0299 public:
0300   /// Consume the construction context layer, together with its parent layers,
0301   /// and wrap it up into a complete construction context. May return null
0302   /// if layers do not form any supported construction context.
0303   static const ConstructionContext *
0304   createFromLayers(BumpVectorContext &C,
0305                    const ConstructionContextLayer *TopLayer);
0306 
0307   Kind getKind() const { return K; }
0308 
0309   virtual const ArrayInitLoopExpr *getArrayInitLoop() const { return nullptr; }
0310 
0311   // Only declared to silence -Wnon-virtual-dtor warnings.
0312   virtual ~ConstructionContext() = default;
0313 };
0314 
0315 /// An abstract base class for local variable constructors.
0316 class VariableConstructionContext : public ConstructionContext {
0317   const DeclStmt *DS;
0318 
0319 protected:
0320   VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS)
0321       : ConstructionContext(K), DS(DS) {
0322     assert(classof(this));
0323     assert(DS);
0324   }
0325 
0326 public:
0327   const DeclStmt *getDeclStmt() const { return DS; }
0328 
0329   const ArrayInitLoopExpr *getArrayInitLoop() const override {
0330     const auto *Var = cast<VarDecl>(DS->getSingleDecl());
0331 
0332     return dyn_cast<ArrayInitLoopExpr>(Var->getInit());
0333   }
0334 
0335   static bool classof(const ConstructionContext *CC) {
0336     return CC->getKind() >= VARIABLE_BEGIN &&
0337            CC->getKind() <= VARIABLE_END;
0338   }
0339 };
0340 
0341 /// Represents construction into a simple local variable, eg. T var(123);.
0342 /// If a variable has an initializer, eg. T var = makeT();, then the final
0343 /// elidable copy-constructor from makeT() into var would also be a simple
0344 /// variable constructor handled by this class.
0345 class SimpleVariableConstructionContext : public VariableConstructionContext {
0346   friend class ConstructionContext; // Allows to create<>() itself.
0347 
0348   explicit SimpleVariableConstructionContext(const DeclStmt *DS)
0349       : VariableConstructionContext(ConstructionContext::SimpleVariableKind,
0350                                     DS) {}
0351 
0352 public:
0353   static bool classof(const ConstructionContext *CC) {
0354     return CC->getKind() == SimpleVariableKind;
0355   }
0356 };
0357 
0358 /// Represents construction into a simple variable with an initializer syntax,
0359 /// with a single constructor, eg. T var = makeT();. Such construction context
0360 /// may only appear in C++17 because previously it was split into a temporary
0361 /// object constructor and an elidable simple variable copy-constructor and
0362 /// we were producing separate construction contexts for these constructors.
0363 /// In C++17 we have a single construction context that combines both.
0364 /// Note that if the object has trivial destructor, then this code is
0365 /// indistinguishable from a simple variable constructor on the AST level;
0366 /// in this case we provide a simple variable construction context.
0367 class CXX17ElidedCopyVariableConstructionContext
0368     : public VariableConstructionContext {
0369   const CXXBindTemporaryExpr *BTE;
0370 
0371   friend class ConstructionContext; // Allows to create<>() itself.
0372 
0373   explicit CXX17ElidedCopyVariableConstructionContext(
0374       const DeclStmt *DS, const CXXBindTemporaryExpr *BTE)
0375       : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) {
0376     assert(BTE);
0377   }
0378 
0379 public:
0380   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
0381 
0382   static bool classof(const ConstructionContext *CC) {
0383     return CC->getKind() == CXX17ElidedCopyVariableKind;
0384   }
0385 };
0386 
0387 // An abstract base class for constructor-initializer-based constructors.
0388 class ConstructorInitializerConstructionContext : public ConstructionContext {
0389   const CXXCtorInitializer *I;
0390 
0391 protected:
0392   explicit ConstructorInitializerConstructionContext(
0393       ConstructionContext::Kind K, const CXXCtorInitializer *I)
0394       : ConstructionContext(K), I(I) {
0395     assert(classof(this));
0396     assert(I);
0397   }
0398 
0399 public:
0400   const CXXCtorInitializer *getCXXCtorInitializer() const { return I; }
0401 
0402   const ArrayInitLoopExpr *getArrayInitLoop() const override {
0403     return dyn_cast<ArrayInitLoopExpr>(I->getInit());
0404   }
0405 
0406   static bool classof(const ConstructionContext *CC) {
0407     return CC->getKind() >= INITIALIZER_BEGIN &&
0408            CC->getKind() <= INITIALIZER_END;
0409   }
0410 };
0411 
0412 /// Represents construction into a field or a base class within a bigger object
0413 /// via a constructor initializer, eg. T(): field(123) { ... }.
0414 class SimpleConstructorInitializerConstructionContext
0415     : public ConstructorInitializerConstructionContext {
0416   friend class ConstructionContext; // Allows to create<>() itself.
0417 
0418   explicit SimpleConstructorInitializerConstructionContext(
0419       const CXXCtorInitializer *I)
0420       : ConstructorInitializerConstructionContext(
0421             ConstructionContext::SimpleConstructorInitializerKind, I) {}
0422 
0423 public:
0424   static bool classof(const ConstructionContext *CC) {
0425     return CC->getKind() == SimpleConstructorInitializerKind;
0426   }
0427 };
0428 
0429 /// Represents construction into a field or a base class within a bigger object
0430 /// via a constructor initializer, with a single constructor, eg.
0431 /// T(): field(Field(123)) { ... }. Such construction context may only appear
0432 /// in C++17 because previously it was split into a temporary object constructor
0433 /// and an elidable simple constructor-initializer copy-constructor and we were
0434 /// producing separate construction contexts for these constructors. In C++17
0435 /// we have a single construction context that combines both. Note that if the
0436 /// object has trivial destructor, then this code is indistinguishable from
0437 /// a simple constructor-initializer constructor on the AST level; in this case
0438 /// we provide a simple constructor-initializer construction context.
0439 class CXX17ElidedCopyConstructorInitializerConstructionContext
0440     : public ConstructorInitializerConstructionContext {
0441   const CXXBindTemporaryExpr *BTE;
0442 
0443   friend class ConstructionContext; // Allows to create<>() itself.
0444 
0445   explicit CXX17ElidedCopyConstructorInitializerConstructionContext(
0446       const CXXCtorInitializer *I, const CXXBindTemporaryExpr *BTE)
0447       : ConstructorInitializerConstructionContext(
0448             CXX17ElidedCopyConstructorInitializerKind, I),
0449         BTE(BTE) {
0450     assert(BTE);
0451   }
0452 
0453 public:
0454   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
0455 
0456   static bool classof(const ConstructionContext *CC) {
0457     return CC->getKind() == CXX17ElidedCopyConstructorInitializerKind;
0458   }
0459 };
0460 
0461 /// Represents immediate initialization of memory allocated by operator new,
0462 /// eg. new T(123);.
0463 class NewAllocatedObjectConstructionContext : public ConstructionContext {
0464   const CXXNewExpr *NE;
0465 
0466   friend class ConstructionContext; // Allows to create<>() itself.
0467 
0468   explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE)
0469       : ConstructionContext(ConstructionContext::NewAllocatedObjectKind),
0470         NE(NE) {
0471     assert(NE);
0472   }
0473 
0474 public:
0475   const CXXNewExpr *getCXXNewExpr() const { return NE; }
0476 
0477   static bool classof(const ConstructionContext *CC) {
0478     return CC->getKind() == NewAllocatedObjectKind;
0479   }
0480 };
0481 
0482 /// Represents a temporary object, eg. T(123), that does not immediately cross
0483 /// function boundaries "by value"; constructors that construct function
0484 /// value-type arguments or values that are immediately returned from the
0485 /// function that returns a value receive separate construction context kinds.
0486 class TemporaryObjectConstructionContext : public ConstructionContext {
0487   const CXXBindTemporaryExpr *BTE;
0488   const MaterializeTemporaryExpr *MTE;
0489 
0490 protected:
0491   explicit TemporaryObjectConstructionContext(
0492       ConstructionContext::Kind K, const CXXBindTemporaryExpr *BTE,
0493       const MaterializeTemporaryExpr *MTE)
0494       : ConstructionContext(K), BTE(BTE), MTE(MTE) {
0495     // Both BTE and MTE can be null here, all combinations possible.
0496     // Even though for now at least one should be non-null, we simply haven't
0497     // implemented the other case yet (this would be a temporary in the middle
0498     // of nowhere that doesn't have a non-trivial destructor).
0499   }
0500 
0501 public:
0502   /// CXXBindTemporaryExpr here is non-null as long as the temporary has
0503   /// a non-trivial destructor.
0504   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const {
0505     return BTE;
0506   }
0507 
0508   /// MaterializeTemporaryExpr is non-null as long as the temporary is actually
0509   /// used after construction, eg. by binding to a reference (lifetime
0510   /// extension), accessing a field, calling a method, or passing it into
0511   /// a function (an elidable copy or move constructor would be a common
0512   /// example) by reference.
0513   const MaterializeTemporaryExpr *getMaterializedTemporaryExpr() const {
0514     return MTE;
0515   }
0516 
0517   static bool classof(const ConstructionContext *CC) {
0518     return CC->getKind() >= TEMPORARY_BEGIN && CC->getKind() <= TEMPORARY_END;
0519   }
0520 };
0521 
0522 /// Represents a temporary object that is not constructed for the purpose of
0523 /// being immediately copied/moved by an elidable copy/move-constructor.
0524 /// This includes temporary objects "in the middle of nowhere" like T(123) and
0525 /// lifetime-extended temporaries.
0526 class SimpleTemporaryObjectConstructionContext
0527     : public TemporaryObjectConstructionContext {
0528   friend class ConstructionContext; // Allows to create<>() itself.
0529 
0530   explicit SimpleTemporaryObjectConstructionContext(
0531       const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE)
0532       : TemporaryObjectConstructionContext(
0533             ConstructionContext::SimpleTemporaryObjectKind, BTE, MTE) {}
0534 
0535 public:
0536   static bool classof(const ConstructionContext *CC) {
0537     return CC->getKind() == SimpleTemporaryObjectKind;
0538   }
0539 };
0540 
0541 /// Represents a temporary object that is constructed for the sole purpose
0542 /// of being immediately copied by an elidable copy/move constructor.
0543 /// For example, T t = T(123); includes a temporary T(123) that is immediately
0544 /// copied to variable t. In such cases the elidable copy can (but not
0545 /// necessarily should) be omitted ("elided") according to the rules of the
0546 /// language; the constructor would then construct variable t directly.
0547 /// This construction context contains information of the elidable constructor
0548 /// and its respective construction context.
0549 class ElidedTemporaryObjectConstructionContext
0550     : public TemporaryObjectConstructionContext {
0551   const CXXConstructExpr *ElidedCE;
0552   const ConstructionContext *ElidedCC;
0553 
0554   friend class ConstructionContext; // Allows to create<>() itself.
0555 
0556   explicit ElidedTemporaryObjectConstructionContext(
0557       const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE,
0558       const CXXConstructExpr *ElidedCE, const ConstructionContext *ElidedCC)
0559       : TemporaryObjectConstructionContext(
0560             ConstructionContext::ElidedTemporaryObjectKind, BTE, MTE),
0561         ElidedCE(ElidedCE), ElidedCC(ElidedCC) {
0562     // Elided constructor and its context should be either both specified
0563     // or both unspecified. In the former case, the constructor must be
0564     // elidable.
0565     assert(ElidedCE && ElidedCE->isElidable() && ElidedCC);
0566   }
0567 
0568 public:
0569   const CXXConstructExpr *getConstructorAfterElision() const {
0570     return ElidedCE;
0571   }
0572 
0573   const ConstructionContext *getConstructionContextAfterElision() const {
0574     return ElidedCC;
0575   }
0576 
0577   static bool classof(const ConstructionContext *CC) {
0578     return CC->getKind() == ElidedTemporaryObjectKind;
0579   }
0580 };
0581 
0582 class ReturnedValueConstructionContext : public ConstructionContext {
0583   const ReturnStmt *RS;
0584 
0585 protected:
0586   explicit ReturnedValueConstructionContext(ConstructionContext::Kind K,
0587                                             const ReturnStmt *RS)
0588       : ConstructionContext(K), RS(RS) {
0589     assert(classof(this));
0590     assert(RS);
0591   }
0592 
0593 public:
0594   const ReturnStmt *getReturnStmt() const { return RS; }
0595 
0596   static bool classof(const ConstructionContext *CC) {
0597     return CC->getKind() >= RETURNED_VALUE_BEGIN &&
0598            CC->getKind() <= RETURNED_VALUE_END;
0599   }
0600 };
0601 
0602 /// Represents a temporary object that is being immediately returned from a
0603 /// function by value, eg. return t; or return T(123);. In this case there is
0604 /// always going to be a constructor at the return site. However, the usual
0605 /// temporary-related bureaucracy (CXXBindTemporaryExpr,
0606 /// MaterializeTemporaryExpr) is normally located in the caller function's AST.
0607 class SimpleReturnedValueConstructionContext
0608     : public ReturnedValueConstructionContext {
0609   friend class ConstructionContext; // Allows to create<>() itself.
0610 
0611   explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS)
0612       : ReturnedValueConstructionContext(
0613             ConstructionContext::SimpleReturnedValueKind, RS) {}
0614 
0615 public:
0616   static bool classof(const ConstructionContext *CC) {
0617     return CC->getKind() == SimpleReturnedValueKind;
0618   }
0619 };
0620 
0621 /// Represents a temporary object that is being immediately returned from a
0622 /// function by value, eg. return t; or return T(123); in C++17.
0623 /// In C++17 there is not going to be an elidable copy constructor at the
0624 /// return site.  However, the usual temporary-related bureaucracy (CXXBindTemporaryExpr,
0625 /// MaterializeTemporaryExpr) is normally located in the caller function's AST.
0626 /// Note that if the object has trivial destructor, then this code is
0627 /// indistinguishable from a simple returned value constructor on the AST level;
0628 /// in this case we provide a simple returned value construction context.
0629 class CXX17ElidedCopyReturnedValueConstructionContext
0630     : public ReturnedValueConstructionContext {
0631   const CXXBindTemporaryExpr *BTE;
0632 
0633   friend class ConstructionContext; // Allows to create<>() itself.
0634 
0635   explicit CXX17ElidedCopyReturnedValueConstructionContext(
0636       const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE)
0637       : ReturnedValueConstructionContext(
0638             ConstructionContext::CXX17ElidedCopyReturnedValueKind, RS),
0639         BTE(BTE) {
0640     assert(BTE);
0641   }
0642 
0643 public:
0644   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
0645 
0646   static bool classof(const ConstructionContext *CC) {
0647     return CC->getKind() == CXX17ElidedCopyReturnedValueKind;
0648   }
0649 };
0650 
0651 class ArgumentConstructionContext : public ConstructionContext {
0652   // The call of which the context is an argument.
0653   const Expr *CE;
0654 
0655   // Which argument we're constructing. Note that when numbering between
0656   // arguments and parameters is inconsistent (eg., operator calls),
0657   // this is the index of the argument, not of the parameter.
0658   unsigned Index;
0659 
0660   // Whether the object needs to be destroyed.
0661   const CXXBindTemporaryExpr *BTE;
0662 
0663   friend class ConstructionContext; // Allows to create<>() itself.
0664 
0665   explicit ArgumentConstructionContext(const Expr *CE, unsigned Index,
0666                                        const CXXBindTemporaryExpr *BTE)
0667       : ConstructionContext(ArgumentKind), CE(CE),
0668         Index(Index), BTE(BTE) {
0669     assert(isa<CallExpr>(CE) || isa<CXXConstructExpr>(CE) ||
0670            isa<ObjCMessageExpr>(CE));
0671     // BTE is optional.
0672   }
0673 
0674 public:
0675   const Expr *getCallLikeExpr() const { return CE; }
0676   unsigned getIndex() const { return Index; }
0677   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
0678 
0679   static bool classof(const ConstructionContext *CC) {
0680     return CC->getKind() == ArgumentKind;
0681   }
0682 };
0683 
0684 class LambdaCaptureConstructionContext : public ConstructionContext {
0685   // The lambda of which the initializer we capture.
0686   const LambdaExpr *LE;
0687 
0688   // Index of the captured element in the captured list.
0689   unsigned Index;
0690 
0691   friend class ConstructionContext; // Allows to create<>() itself.
0692 
0693   explicit LambdaCaptureConstructionContext(const LambdaExpr *LE,
0694                                             unsigned Index)
0695       : ConstructionContext(LambdaCaptureKind), LE(LE), Index(Index) {}
0696 
0697 public:
0698   const LambdaExpr *getLambdaExpr() const { return LE; }
0699   unsigned getIndex() const { return Index; }
0700 
0701   const Expr *getInitializer() const {
0702     return *(LE->capture_init_begin() + Index);
0703   }
0704 
0705   const FieldDecl *getFieldDecl() const {
0706     auto It = LE->getLambdaClass()->field_begin();
0707     std::advance(It, Index);
0708     return *It;
0709   }
0710 
0711   const ArrayInitLoopExpr *getArrayInitLoop() const override {
0712     return dyn_cast_or_null<ArrayInitLoopExpr>(getInitializer());
0713   }
0714 
0715   static bool classof(const ConstructionContext *CC) {
0716     return CC->getKind() == LambdaCaptureKind;
0717   }
0718 };
0719 
0720 } // end namespace clang
0721 
0722 #endif // LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H