123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- 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,
- STATEMENT_WITH_INDEX_KIND_BEGIN=ArgumentKind,
- STATEMENT_WITH_INDEX_KIND_END=ArgumentKind,
- STATEMENT_KIND_BEGIN = VariableKind,
- STATEMENT_KIND_END = ArgumentKind,
- 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 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<CXXInheritedCtorInitExpr>(E) || isa<ObjCMessageExpr>(E));
- }
- ConstructionContextItem(const CXXCtorInitializer *Init)
- : Data(Init), Kind(InitializerKind), Index(0) {}
- 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
- };
- 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; }
- };
- /// 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; }
- 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; }
- 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") accodring 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;
- }
- };
- } // end namespace clang
- #endif // LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|