1218799Snwhitehorn//===- ConstructionContext.h - CFG constructor information ------*- C++ -*-===// 2218799Snwhitehorn// 3218799Snwhitehorn// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4258421Sdteske// See https://llvm.org/LICENSE.txt for license information. 5218799Snwhitehorn// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6218799Snwhitehorn// 7218799Snwhitehorn//===----------------------------------------------------------------------===// 8218799Snwhitehorn// 9218799Snwhitehorn// This file defines the ConstructionContext class and its sub-classes, 10218799Snwhitehorn// which represent various different ways of constructing C++ objects 11218799Snwhitehorn// with the additional information the users may want to know about 12218799Snwhitehorn// the constructor. 13218799Snwhitehorn// 14218799Snwhitehorn//===----------------------------------------------------------------------===// 15218799Snwhitehorn 16218799Snwhitehorn#ifndef LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H 17218799Snwhitehorn#define LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H 18218799Snwhitehorn 19218799Snwhitehorn#include "clang/Analysis/Support/BumpVector.h" 20218799Snwhitehorn#include "clang/AST/ExprCXX.h" 21218799Snwhitehorn#include "clang/AST/ExprObjC.h" 22218799Snwhitehorn 23218799Snwhitehornnamespace clang { 24218799Snwhitehorn 25218799Snwhitehorn/// Represents a single point (AST node) in the program that requires attention 26218799Snwhitehorn/// during construction of an object. ConstructionContext would be represented 27218799Snwhitehorn/// as a list of such items. 28218799Snwhitehornclass ConstructionContextItem { 29258421Sdteskepublic: 30258421Sdteske enum ItemKind { 31218799Snwhitehorn VariableKind, 32258421Sdteske NewAllocatorKind, 33258421Sdteske ReturnKind, 34258421Sdteske MaterializationKind, 35258421Sdteske TemporaryDestructorKind, 36258421Sdteske ElidedDestructorKind, 37218799Snwhitehorn ElidableConstructorKind, 38218799Snwhitehorn ArgumentKind, 39218799Snwhitehorn LambdaCaptureKind, 40218799Snwhitehorn STATEMENT_WITH_INDEX_KIND_BEGIN = ArgumentKind, 41218799Snwhitehorn STATEMENT_WITH_INDEX_KIND_END = LambdaCaptureKind, 42218799Snwhitehorn STATEMENT_KIND_BEGIN = VariableKind, 43218799Snwhitehorn STATEMENT_KIND_END = LambdaCaptureKind, 44218799Snwhitehorn InitializerKind, 45218799Snwhitehorn INITIALIZER_KIND_BEGIN = InitializerKind, 46218799Snwhitehorn INITIALIZER_KIND_END = InitializerKind 47218799Snwhitehorn }; 48218799Snwhitehorn 49218799Snwhitehorn LLVM_DUMP_METHOD static StringRef getKindAsString(ItemKind K) { 50218799Snwhitehorn switch (K) { 51218799Snwhitehorn case VariableKind: return "construct into local variable"; 52218799Snwhitehorn case NewAllocatorKind: return "construct into new-allocator"; 53218799Snwhitehorn case ReturnKind: return "construct into return address"; 54218799Snwhitehorn case MaterializationKind: return "materialize temporary"; 55218799Snwhitehorn case TemporaryDestructorKind: return "destroy temporary"; 56218799Snwhitehorn case ElidedDestructorKind: return "elide destructor"; 57218799Snwhitehorn case ElidableConstructorKind: return "elide constructor"; 58218799Snwhitehorn case ArgumentKind: return "construct into argument"; 59218799Snwhitehorn case LambdaCaptureKind: 60218799Snwhitehorn return "construct into lambda captured variable"; 61258421Sdteske case InitializerKind: return "construct into member variable"; 62258421Sdteske }; 63218799Snwhitehorn llvm_unreachable("Unknown ItemKind"); 64218799Snwhitehorn } 65218799Snwhitehorn 66218799Snwhitehornprivate: 67218799Snwhitehorn const void *const Data; 68218799Snwhitehorn const ItemKind Kind; 69218799Snwhitehorn const unsigned Index = 0; 70218799Snwhitehorn 71218799Snwhitehorn bool hasStatement() const { 72245980Snwhitehorn return Kind >= STATEMENT_KIND_BEGIN && 73218799Snwhitehorn Kind <= STATEMENT_KIND_END; 74218799Snwhitehorn } 75218799Snwhitehorn 76218799Snwhitehorn bool hasIndex() const { 77218799Snwhitehorn return Kind >= STATEMENT_WITH_INDEX_KIND_BEGIN && 78218799Snwhitehorn Kind <= STATEMENT_WITH_INDEX_KIND_END; 79218799Snwhitehorn } 80218799Snwhitehorn 81218799Snwhitehorn bool hasInitializer() const { 82218799Snwhitehorn return Kind >= INITIALIZER_KIND_BEGIN && 83218799Snwhitehorn Kind <= INITIALIZER_KIND_END; 84218799Snwhitehorn } 85218799Snwhitehorn 86218799Snwhitehornpublic: 87218799Snwhitehorn // ConstructionContextItem should be simple enough so that it was easy to 88218799Snwhitehorn // re-construct it from the AST node it captures. For that reason we provide 89218799Snwhitehorn // simple implicit conversions from all sorts of supported AST nodes. 90218799Snwhitehorn ConstructionContextItem(const DeclStmt *DS) 91218799Snwhitehorn : Data(DS), Kind(VariableKind) {} 92218799Snwhitehorn 93218799Snwhitehorn ConstructionContextItem(const CXXNewExpr *NE) 94218799Snwhitehorn : Data(NE), Kind(NewAllocatorKind) {} 95218799Snwhitehorn 96218799Snwhitehorn ConstructionContextItem(const ReturnStmt *RS) 97218799Snwhitehorn : Data(RS), Kind(ReturnKind) {} 98218799Snwhitehorn 99218799Snwhitehorn ConstructionContextItem(const MaterializeTemporaryExpr *MTE) 100218799Snwhitehorn : Data(MTE), Kind(MaterializationKind) {} 101218799Snwhitehorn 102218799Snwhitehorn ConstructionContextItem(const CXXBindTemporaryExpr *BTE, 103218799Snwhitehorn bool IsElided = false) 104225539Sbrueffer : Data(BTE), 105218799Snwhitehorn Kind(IsElided ? ElidedDestructorKind : TemporaryDestructorKind) {} 106218799Snwhitehorn 107218799Snwhitehorn ConstructionContextItem(const CXXConstructExpr *CE) 108218799Snwhitehorn : Data(CE), Kind(ElidableConstructorKind) {} 109218799Snwhitehorn 110218799Snwhitehorn ConstructionContextItem(const CallExpr *CE, unsigned Index) 111218799Snwhitehorn : Data(CE), Kind(ArgumentKind), Index(Index) {} 112218799Snwhitehorn 113260682Sdteske ConstructionContextItem(const CXXConstructExpr *CE, unsigned Index) 114260682Sdteske : Data(CE), Kind(ArgumentKind), Index(Index) {} 115260682Sdteske 116260682Sdteske ConstructionContextItem(const CXXInheritedCtorInitExpr *CE, unsigned Index) 117260682Sdteske : Data(CE), Kind(ArgumentKind), Index(Index) {} 118260682Sdteske 119260682Sdteske ConstructionContextItem(const ObjCMessageExpr *ME, unsigned Index) 120260682Sdteske : Data(ME), Kind(ArgumentKind), Index(Index) {} 121260682Sdteske 122260682Sdteske // A polymorphic version of the previous calls with dynamic type check. 123260682Sdteske ConstructionContextItem(const Expr *E, unsigned Index) 124260682Sdteske : Data(E), Kind(ArgumentKind), Index(Index) { 125260682Sdteske assert(isa<CallExpr>(E) || isa<CXXConstructExpr>(E) || 126260682Sdteske isa<CXXDeleteExpr>(E) || isa<CXXInheritedCtorInitExpr>(E) || 127260682Sdteske isa<ObjCMessageExpr>(E)); 128260682Sdteske } 129260682Sdteske 130260682Sdteske ConstructionContextItem(const CXXCtorInitializer *Init) 131260682Sdteske : Data(Init), Kind(InitializerKind), Index(0) {} 132260682Sdteske 133260682Sdteske ConstructionContextItem(const LambdaExpr *LE, unsigned Index) 134260682Sdteske : Data(LE), Kind(LambdaCaptureKind), Index(Index) {} 135260682Sdteske 136218799Snwhitehorn ItemKind getKind() const { return Kind; } 137218799Snwhitehorn 138218799Snwhitehorn LLVM_DUMP_METHOD StringRef getKindAsString() const { 139218799Snwhitehorn return getKindAsString(getKind()); 140218799Snwhitehorn } 141218799Snwhitehorn 142218799Snwhitehorn /// The construction site - the statement that triggered the construction 143218799Snwhitehorn /// for one of its parts. For instance, stack variable declaration statement 144218799Snwhitehorn /// triggers construction of itself or its elements if it's an array, 145218799Snwhitehorn /// new-expression triggers construction of the newly allocated object(s). 146218799Snwhitehorn const Stmt *getStmt() const { 147218799Snwhitehorn assert(hasStatement()); 148218799Snwhitehorn return static_cast<const Stmt *>(Data); 149218799Snwhitehorn } 150218799Snwhitehorn 151218799Snwhitehorn const Stmt *getStmtOrNull() const { 152218799Snwhitehorn return hasStatement() ? getStmt() : nullptr; 153218799Snwhitehorn } 154218799Snwhitehorn 155218799Snwhitehorn /// The construction site is not necessarily a statement. It may also be a 156218799Snwhitehorn /// CXXCtorInitializer, which means that a member variable is being 157218799Snwhitehorn /// constructed during initialization of the object that contains it. 158218799Snwhitehorn const CXXCtorInitializer *getCXXCtorInitializer() const { 159218799Snwhitehorn assert(hasInitializer()); 160218799Snwhitehorn return static_cast<const CXXCtorInitializer *>(Data); 161260682Sdteske } 162218799Snwhitehorn 163218799Snwhitehorn /// If a single trigger statement triggers multiple constructors, they are 164218799Snwhitehorn /// usually being enumerated. This covers function argument constructors 165218799Snwhitehorn /// triggered by a call-expression and items in an initializer list triggered 166258421Sdteske /// by an init-list-expression. 167258421Sdteske unsigned getIndex() const { 168258421Sdteske // This is a fairly specific request. Let's make sure the user knows 169258421Sdteske // what he's doing. 170218799Snwhitehorn assert(hasIndex()); 171218799Snwhitehorn return Index; 172258421Sdteske } 173258421Sdteske 174258421Sdteske void Profile(llvm::FoldingSetNodeID &ID) const { 175258421Sdteske ID.AddPointer(Data); 176 ID.AddInteger(Kind); 177 ID.AddInteger(Index); 178 } 179 180 bool operator==(const ConstructionContextItem &Other) const { 181 // For most kinds the Index comparison is trivially true, but 182 // checking kind separately doesn't seem to be less expensive 183 // than checking Index. Same in operator<(). 184 return std::make_tuple(Data, Kind, Index) == 185 std::make_tuple(Other.Data, Other.Kind, Other.Index); 186 } 187 188 bool operator<(const ConstructionContextItem &Other) const { 189 return std::make_tuple(Data, Kind, Index) < 190 std::make_tuple(Other.Data, Other.Kind, Other.Index); 191 } 192}; 193 194/// Construction context can be seen as a linked list of multiple layers. 195/// Sometimes a single trigger is not enough to describe the construction 196/// site. That's what causing us to have a chain of "partial" construction 197/// context layers. Some examples: 198/// - A constructor within in an aggregate initializer list within a variable 199/// would have a construction context of the initializer list with 200/// the parent construction context of a variable. 201/// - A constructor for a temporary that needs to be both destroyed 202/// and materialized into an elidable copy constructor would have a 203/// construction context of a CXXBindTemporaryExpr with the parent 204/// construction context of a MaterializeTemproraryExpr. 205/// Not all of these are currently supported. 206/// Layers are created gradually while traversing the AST, and layers that 207/// represent the outmost AST nodes are built first, while the node that 208/// immediately contains the constructor would be built last and capture the 209/// previous layers as its parents. Construction context captures the last layer 210/// (which has links to the previous layers) and classifies the seemingly 211/// arbitrary chain of layers into one of the possible ways of constructing 212/// an object in C++ for user-friendly experience. 213class ConstructionContextLayer { 214 const ConstructionContextLayer *Parent = nullptr; 215 ConstructionContextItem Item; 216 217 ConstructionContextLayer(ConstructionContextItem Item, 218 const ConstructionContextLayer *Parent) 219 : Parent(Parent), Item(Item) {} 220 221public: 222 static const ConstructionContextLayer * 223 create(BumpVectorContext &C, const ConstructionContextItem &Item, 224 const ConstructionContextLayer *Parent = nullptr); 225 226 const ConstructionContextItem &getItem() const { return Item; } 227 const ConstructionContextLayer *getParent() const { return Parent; } 228 bool isLast() const { return !Parent; } 229 230 /// See if Other is a proper initial segment of this construction context 231 /// in terms of the parent chain - i.e. a few first parents coincide and 232 /// then the other context terminates but our context goes further - i.e., 233 /// we are providing the same context that the other context provides, 234 /// and a bit more above that. 235 bool isStrictlyMoreSpecificThan(const ConstructionContextLayer *Other) const; 236}; 237 238 239/// ConstructionContext's subclasses describe different ways of constructing 240/// an object in C++. The context re-captures the essential parent AST nodes 241/// of the CXXConstructExpr it is assigned to and presents these nodes 242/// through easy-to-understand accessor methods. 243class ConstructionContext { 244public: 245 enum Kind { 246 SimpleVariableKind, 247 CXX17ElidedCopyVariableKind, 248 VARIABLE_BEGIN = SimpleVariableKind, 249 VARIABLE_END = CXX17ElidedCopyVariableKind, 250 SimpleConstructorInitializerKind, 251 CXX17ElidedCopyConstructorInitializerKind, 252 INITIALIZER_BEGIN = SimpleConstructorInitializerKind, 253 INITIALIZER_END = CXX17ElidedCopyConstructorInitializerKind, 254 NewAllocatedObjectKind, 255 SimpleTemporaryObjectKind, 256 ElidedTemporaryObjectKind, 257 TEMPORARY_BEGIN = SimpleTemporaryObjectKind, 258 TEMPORARY_END = ElidedTemporaryObjectKind, 259 SimpleReturnedValueKind, 260 CXX17ElidedCopyReturnedValueKind, 261 RETURNED_VALUE_BEGIN = SimpleReturnedValueKind, 262 RETURNED_VALUE_END = CXX17ElidedCopyReturnedValueKind, 263 ArgumentKind, 264 LambdaCaptureKind 265 }; 266 267protected: 268 Kind K; 269 270 // Do not make public! These need to only be constructed 271 // via createFromLayers(). 272 explicit ConstructionContext(Kind K) : K(K) {} 273 274private: 275 // A helper function for constructing an instance into a bump vector context. 276 template <typename T, typename... ArgTypes> 277 static T *create(BumpVectorContext &C, ArgTypes... Args) { 278 auto *CC = C.getAllocator().Allocate<T>(); 279 return new (CC) T(Args...); 280 } 281 282 // A sub-routine of createFromLayers() that deals with temporary objects 283 // that need to be materialized. The BTE argument is for the situation when 284 // the object also needs to be bound for destruction. 285 static const ConstructionContext *createMaterializedTemporaryFromLayers( 286 BumpVectorContext &C, const MaterializeTemporaryExpr *MTE, 287 const CXXBindTemporaryExpr *BTE, 288 const ConstructionContextLayer *ParentLayer); 289 290 // A sub-routine of createFromLayers() that deals with temporary objects 291 // that need to be bound for destruction. Automatically finds out if the 292 // object also needs to be materialized and delegates to 293 // createMaterializedTemporaryFromLayers() if necessary. 294 static const ConstructionContext * 295 createBoundTemporaryFromLayers( 296 BumpVectorContext &C, const CXXBindTemporaryExpr *BTE, 297 const ConstructionContextLayer *ParentLayer); 298 299public: 300 /// Consume the construction context layer, together with its parent layers, 301 /// and wrap it up into a complete construction context. May return null 302 /// if layers do not form any supported construction context. 303 static const ConstructionContext * 304 createFromLayers(BumpVectorContext &C, 305 const ConstructionContextLayer *TopLayer); 306 307 Kind getKind() const { return K; } 308 309 virtual const ArrayInitLoopExpr *getArrayInitLoop() const { return nullptr; } 310 311 // Only declared to silence -Wnon-virtual-dtor warnings. 312 virtual ~ConstructionContext() = default; 313}; 314 315/// An abstract base class for local variable constructors. 316class VariableConstructionContext : public ConstructionContext { 317 const DeclStmt *DS; 318 319protected: 320 VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS) 321 : ConstructionContext(K), DS(DS) { 322 assert(classof(this)); 323 assert(DS); 324 } 325 326public: 327 const DeclStmt *getDeclStmt() const { return DS; } 328 329 const ArrayInitLoopExpr *getArrayInitLoop() const override { 330 const auto *Var = cast<VarDecl>(DS->getSingleDecl()); 331 332 return dyn_cast<ArrayInitLoopExpr>(Var->getInit()); 333 } 334 335 static bool classof(const ConstructionContext *CC) { 336 return CC->getKind() >= VARIABLE_BEGIN && 337 CC->getKind() <= VARIABLE_END; 338 } 339}; 340 341/// Represents construction into a simple local variable, eg. T var(123);. 342/// If a variable has an initializer, eg. T var = makeT();, then the final 343/// elidable copy-constructor from makeT() into var would also be a simple 344/// variable constructor handled by this class. 345class SimpleVariableConstructionContext : public VariableConstructionContext { 346 friend class ConstructionContext; // Allows to create<>() itself. 347 348 explicit SimpleVariableConstructionContext(const DeclStmt *DS) 349 : VariableConstructionContext(ConstructionContext::SimpleVariableKind, 350 DS) {} 351 352public: 353 static bool classof(const ConstructionContext *CC) { 354 return CC->getKind() == SimpleVariableKind; 355 } 356}; 357 358/// Represents construction into a simple variable with an initializer syntax, 359/// with a single constructor, eg. T var = makeT();. Such construction context 360/// may only appear in C++17 because previously it was split into a temporary 361/// object constructor and an elidable simple variable copy-constructor and 362/// we were producing separate construction contexts for these constructors. 363/// In C++17 we have a single construction context that combines both. 364/// Note that if the object has trivial destructor, then this code is 365/// indistinguishable from a simple variable constructor on the AST level; 366/// in this case we provide a simple variable construction context. 367class CXX17ElidedCopyVariableConstructionContext 368 : public VariableConstructionContext { 369 const CXXBindTemporaryExpr *BTE; 370 371 friend class ConstructionContext; // Allows to create<>() itself. 372 373 explicit CXX17ElidedCopyVariableConstructionContext( 374 const DeclStmt *DS, const CXXBindTemporaryExpr *BTE) 375 : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) { 376 assert(BTE); 377 } 378 379public: 380 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; } 381 382 static bool classof(const ConstructionContext *CC) { 383 return CC->getKind() == CXX17ElidedCopyVariableKind; 384 } 385}; 386 387// An abstract base class for constructor-initializer-based constructors. 388class ConstructorInitializerConstructionContext : public ConstructionContext { 389 const CXXCtorInitializer *I; 390 391protected: 392 explicit ConstructorInitializerConstructionContext( 393 ConstructionContext::Kind K, const CXXCtorInitializer *I) 394 : ConstructionContext(K), I(I) { 395 assert(classof(this)); 396 assert(I); 397 } 398 399public: 400 const CXXCtorInitializer *getCXXCtorInitializer() const { return I; } 401 402 const ArrayInitLoopExpr *getArrayInitLoop() const override { 403 return dyn_cast<ArrayInitLoopExpr>(I->getInit()); 404 } 405 406 static bool classof(const ConstructionContext *CC) { 407 return CC->getKind() >= INITIALIZER_BEGIN && 408 CC->getKind() <= INITIALIZER_END; 409 } 410}; 411 412/// Represents construction into a field or a base class within a bigger object 413/// via a constructor initializer, eg. T(): field(123) { ... }. 414class SimpleConstructorInitializerConstructionContext 415 : public ConstructorInitializerConstructionContext { 416 friend class ConstructionContext; // Allows to create<>() itself. 417 418 explicit SimpleConstructorInitializerConstructionContext( 419 const CXXCtorInitializer *I) 420 : ConstructorInitializerConstructionContext( 421 ConstructionContext::SimpleConstructorInitializerKind, I) {} 422 423public: 424 static bool classof(const ConstructionContext *CC) { 425 return CC->getKind() == SimpleConstructorInitializerKind; 426 } 427}; 428 429/// Represents construction into a field or a base class within a bigger object 430/// via a constructor initializer, with a single constructor, eg. 431/// T(): field(Field(123)) { ... }. Such construction context may only appear 432/// in C++17 because previously it was split into a temporary object constructor 433/// and an elidable simple constructor-initializer copy-constructor and we were 434/// producing separate construction contexts for these constructors. In C++17 435/// we have a single construction context that combines both. Note that if the 436/// object has trivial destructor, then this code is indistinguishable from 437/// a simple constructor-initializer constructor on the AST level; in this case 438/// we provide a simple constructor-initializer construction context. 439class CXX17ElidedCopyConstructorInitializerConstructionContext 440 : public ConstructorInitializerConstructionContext { 441 const CXXBindTemporaryExpr *BTE; 442 443 friend class ConstructionContext; // Allows to create<>() itself. 444 445 explicit CXX17ElidedCopyConstructorInitializerConstructionContext( 446 const CXXCtorInitializer *I, const CXXBindTemporaryExpr *BTE) 447 : ConstructorInitializerConstructionContext( 448 CXX17ElidedCopyConstructorInitializerKind, I), 449 BTE(BTE) { 450 assert(BTE); 451 } 452 453public: 454 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; } 455 456 static bool classof(const ConstructionContext *CC) { 457 return CC->getKind() == CXX17ElidedCopyConstructorInitializerKind; 458 } 459}; 460 461/// Represents immediate initialization of memory allocated by operator new, 462/// eg. new T(123);. 463class NewAllocatedObjectConstructionContext : public ConstructionContext { 464 const CXXNewExpr *NE; 465 466 friend class ConstructionContext; // Allows to create<>() itself. 467 468 explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE) 469 : ConstructionContext(ConstructionContext::NewAllocatedObjectKind), 470 NE(NE) { 471 assert(NE); 472 } 473 474public: 475 const CXXNewExpr *getCXXNewExpr() const { return NE; } 476 477 static bool classof(const ConstructionContext *CC) { 478 return CC->getKind() == NewAllocatedObjectKind; 479 } 480}; 481 482/// Represents a temporary object, eg. T(123), that does not immediately cross 483/// function boundaries "by value"; constructors that construct function 484/// value-type arguments or values that are immediately returned from the 485/// function that returns a value receive separate construction context kinds. 486class TemporaryObjectConstructionContext : public ConstructionContext { 487 const CXXBindTemporaryExpr *BTE; 488 const MaterializeTemporaryExpr *MTE; 489 490protected: 491 explicit TemporaryObjectConstructionContext( 492 ConstructionContext::Kind K, const CXXBindTemporaryExpr *BTE, 493 const MaterializeTemporaryExpr *MTE) 494 : ConstructionContext(K), BTE(BTE), MTE(MTE) { 495 // Both BTE and MTE can be null here, all combinations possible. 496 // Even though for now at least one should be non-null, we simply haven't 497 // implemented the other case yet (this would be a temporary in the middle 498 // of nowhere that doesn't have a non-trivial destructor). 499 } 500 501public: 502 /// CXXBindTemporaryExpr here is non-null as long as the temporary has 503 /// a non-trivial destructor. 504 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { 505 return BTE; 506 } 507 508 /// MaterializeTemporaryExpr is non-null as long as the temporary is actually 509 /// used after construction, eg. by binding to a reference (lifetime 510 /// extension), accessing a field, calling a method, or passing it into 511 /// a function (an elidable copy or move constructor would be a common 512 /// example) by reference. 513 const MaterializeTemporaryExpr *getMaterializedTemporaryExpr() const { 514 return MTE; 515 } 516 517 static bool classof(const ConstructionContext *CC) { 518 return CC->getKind() >= TEMPORARY_BEGIN && CC->getKind() <= TEMPORARY_END; 519 } 520}; 521 522/// Represents a temporary object that is not constructed for the purpose of 523/// being immediately copied/moved by an elidable copy/move-constructor. 524/// This includes temporary objects "in the middle of nowhere" like T(123) and 525/// lifetime-extended temporaries. 526class SimpleTemporaryObjectConstructionContext 527 : public TemporaryObjectConstructionContext { 528 friend class ConstructionContext; // Allows to create<>() itself. 529 530 explicit SimpleTemporaryObjectConstructionContext( 531 const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE) 532 : TemporaryObjectConstructionContext( 533 ConstructionContext::SimpleTemporaryObjectKind, BTE, MTE) {} 534 535public: 536 static bool classof(const ConstructionContext *CC) { 537 return CC->getKind() == SimpleTemporaryObjectKind; 538 } 539}; 540 541/// Represents a temporary object that is constructed for the sole purpose 542/// of being immediately copied by an elidable copy/move constructor. 543/// For example, T t = T(123); includes a temporary T(123) that is immediately 544/// copied to variable t. In such cases the elidable copy can (but not 545/// necessarily should) be omitted ("elided") according to the rules of the 546/// language; the constructor would then construct variable t directly. 547/// This construction context contains information of the elidable constructor 548/// and its respective construction context. 549class ElidedTemporaryObjectConstructionContext 550 : public TemporaryObjectConstructionContext { 551 const CXXConstructExpr *ElidedCE; 552 const ConstructionContext *ElidedCC; 553 554 friend class ConstructionContext; // Allows to create<>() itself. 555 556 explicit ElidedTemporaryObjectConstructionContext( 557 const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE, 558 const CXXConstructExpr *ElidedCE, const ConstructionContext *ElidedCC) 559 : TemporaryObjectConstructionContext( 560 ConstructionContext::ElidedTemporaryObjectKind, BTE, MTE), 561 ElidedCE(ElidedCE), ElidedCC(ElidedCC) { 562 // Elided constructor and its context should be either both specified 563 // or both unspecified. In the former case, the constructor must be 564 // elidable. 565 assert(ElidedCE && ElidedCE->isElidable() && ElidedCC); 566 } 567 568public: 569 const CXXConstructExpr *getConstructorAfterElision() const { 570 return ElidedCE; 571 } 572 573 const ConstructionContext *getConstructionContextAfterElision() const { 574 return ElidedCC; 575 } 576 577 static bool classof(const ConstructionContext *CC) { 578 return CC->getKind() == ElidedTemporaryObjectKind; 579 } 580}; 581 582class ReturnedValueConstructionContext : public ConstructionContext { 583 const ReturnStmt *RS; 584 585protected: 586 explicit ReturnedValueConstructionContext(ConstructionContext::Kind K, 587 const ReturnStmt *RS) 588 : ConstructionContext(K), RS(RS) { 589 assert(classof(this)); 590 assert(RS); 591 } 592 593public: 594 const ReturnStmt *getReturnStmt() const { return RS; } 595 596 static bool classof(const ConstructionContext *CC) { 597 return CC->getKind() >= RETURNED_VALUE_BEGIN && 598 CC->getKind() <= RETURNED_VALUE_END; 599 } 600}; 601 602/// Represents a temporary object that is being immediately returned from a 603/// function by value, eg. return t; or return T(123);. In this case there is 604/// always going to be a constructor at the return site. However, the usual 605/// temporary-related bureaucracy (CXXBindTemporaryExpr, 606/// MaterializeTemporaryExpr) is normally located in the caller function's AST. 607class SimpleReturnedValueConstructionContext 608 : public ReturnedValueConstructionContext { 609 friend class ConstructionContext; // Allows to create<>() itself. 610 611 explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS) 612 : ReturnedValueConstructionContext( 613 ConstructionContext::SimpleReturnedValueKind, RS) {} 614 615public: 616 static bool classof(const ConstructionContext *CC) { 617 return CC->getKind() == SimpleReturnedValueKind; 618 } 619}; 620 621/// Represents a temporary object that is being immediately returned from a 622/// function by value, eg. return t; or return T(123); in C++17. 623/// In C++17 there is not going to be an elidable copy constructor at the 624/// return site. However, the usual temporary-related bureaucracy (CXXBindTemporaryExpr, 625/// MaterializeTemporaryExpr) is normally located in the caller function's AST. 626/// Note that if the object has trivial destructor, then this code is 627/// indistinguishable from a simple returned value constructor on the AST level; 628/// in this case we provide a simple returned value construction context. 629class CXX17ElidedCopyReturnedValueConstructionContext 630 : public ReturnedValueConstructionContext { 631 const CXXBindTemporaryExpr *BTE; 632 633 friend class ConstructionContext; // Allows to create<>() itself. 634 635 explicit CXX17ElidedCopyReturnedValueConstructionContext( 636 const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE) 637 : ReturnedValueConstructionContext( 638 ConstructionContext::CXX17ElidedCopyReturnedValueKind, RS), 639 BTE(BTE) { 640 assert(BTE); 641 } 642 643public: 644 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; } 645 646 static bool classof(const ConstructionContext *CC) { 647 return CC->getKind() == CXX17ElidedCopyReturnedValueKind; 648 } 649}; 650 651class ArgumentConstructionContext : public ConstructionContext { 652 // The call of which the context is an argument. 653 const Expr *CE; 654 655 // Which argument we're constructing. Note that when numbering between 656 // arguments and parameters is inconsistent (eg., operator calls), 657 // this is the index of the argument, not of the parameter. 658 unsigned Index; 659 660 // Whether the object needs to be destroyed. 661 const CXXBindTemporaryExpr *BTE; 662 663 friend class ConstructionContext; // Allows to create<>() itself. 664 665 explicit ArgumentConstructionContext(const Expr *CE, unsigned Index, 666 const CXXBindTemporaryExpr *BTE) 667 : ConstructionContext(ArgumentKind), CE(CE), 668 Index(Index), BTE(BTE) { 669 assert(isa<CallExpr>(CE) || isa<CXXConstructExpr>(CE) || 670 isa<ObjCMessageExpr>(CE)); 671 // BTE is optional. 672 } 673 674public: 675 const Expr *getCallLikeExpr() const { return CE; } 676 unsigned getIndex() const { return Index; } 677 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; } 678 679 static bool classof(const ConstructionContext *CC) { 680 return CC->getKind() == ArgumentKind; 681 } 682}; 683 684class LambdaCaptureConstructionContext : public ConstructionContext { 685 // The lambda of which the initializer we capture. 686 const LambdaExpr *LE; 687 688 // Index of the captured element in the captured list. 689 unsigned Index; 690 691 friend class ConstructionContext; // Allows to create<>() itself. 692 693 explicit LambdaCaptureConstructionContext(const LambdaExpr *LE, 694 unsigned Index) 695 : ConstructionContext(LambdaCaptureKind), LE(LE), Index(Index) {} 696 697public: 698 const LambdaExpr *getLambdaExpr() const { return LE; } 699 unsigned getIndex() const { return Index; } 700 701 const Expr *getInitializer() const { 702 return *(LE->capture_init_begin() + Index); 703 } 704 705 const FieldDecl *getFieldDecl() const { 706 auto It = LE->getLambdaClass()->field_begin(); 707 std::advance(It, Index); 708 return *It; 709 } 710 711 const ArrayInitLoopExpr *getArrayInitLoop() const override { 712 return dyn_cast_or_null<ArrayInitLoopExpr>(getInitializer()); 713 } 714 715 static bool classof(const ConstructionContext *CC) { 716 return CC->getKind() == LambdaCaptureKind; 717 } 718}; 719 720} // end namespace clang 721 722#endif // LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H 723