1//===- ConstructionContext.h - CFG constructor information ------*- C++ -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file defines the ConstructionContext class and its sub-classes, 10// which represent various different ways of constructing C++ objects 11// with the additional information the users may want to know about 12// the constructor. 13// 14//===----------------------------------------------------------------------===// 15 16#ifndef LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H 17#define LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H 18 19#include "clang/Analysis/Support/BumpVector.h" 20#include "clang/AST/ExprCXX.h" 21#include "clang/AST/ExprObjC.h" 22 23namespace clang { 24 25/// Represents a single point (AST node) in the program that requires attention 26/// during construction of an object. ConstructionContext would be represented 27/// as a list of such items. 28class ConstructionContextItem { 29public: 30 enum ItemKind { 31 VariableKind, 32 NewAllocatorKind, 33 ReturnKind, 34 MaterializationKind, 35 TemporaryDestructorKind, 36 ElidedDestructorKind, 37 ElidableConstructorKind, 38 ArgumentKind, 39 STATEMENT_WITH_INDEX_KIND_BEGIN=ArgumentKind, 40 STATEMENT_WITH_INDEX_KIND_END=ArgumentKind, 41 STATEMENT_KIND_BEGIN = VariableKind, 42 STATEMENT_KIND_END = ArgumentKind, 43 InitializerKind, 44 INITIALIZER_KIND_BEGIN=InitializerKind, 45 INITIALIZER_KIND_END=InitializerKind 46 }; 47 48 LLVM_DUMP_METHOD static StringRef getKindAsString(ItemKind K) { 49 switch (K) { 50 case VariableKind: return "construct into local variable"; 51 case NewAllocatorKind: return "construct into new-allocator"; 52 case ReturnKind: return "construct into return address"; 53 case MaterializationKind: return "materialize temporary"; 54 case TemporaryDestructorKind: return "destroy temporary"; 55 case ElidedDestructorKind: return "elide destructor"; 56 case ElidableConstructorKind: return "elide constructor"; 57 case ArgumentKind: return "construct into argument"; 58 case InitializerKind: return "construct into member variable"; 59 }; 60 llvm_unreachable("Unknown ItemKind"); 61 } 62 63private: 64 const void *const Data; 65 const ItemKind Kind; 66 const unsigned Index = 0; 67 68 bool hasStatement() const { 69 return Kind >= STATEMENT_KIND_BEGIN && 70 Kind <= STATEMENT_KIND_END; 71 } 72 73 bool hasIndex() const { 74 return Kind >= STATEMENT_WITH_INDEX_KIND_BEGIN && 75 Kind >= STATEMENT_WITH_INDEX_KIND_END; 76 } 77 78 bool hasInitializer() const { 79 return Kind >= INITIALIZER_KIND_BEGIN && 80 Kind <= INITIALIZER_KIND_END; 81 } 82 83public: 84 // ConstructionContextItem should be simple enough so that it was easy to 85 // re-construct it from the AST node it captures. For that reason we provide 86 // simple implicit conversions from all sorts of supported AST nodes. 87 ConstructionContextItem(const DeclStmt *DS) 88 : Data(DS), Kind(VariableKind) {} 89 90 ConstructionContextItem(const CXXNewExpr *NE) 91 : Data(NE), Kind(NewAllocatorKind) {} 92 93 ConstructionContextItem(const ReturnStmt *RS) 94 : Data(RS), Kind(ReturnKind) {} 95 96 ConstructionContextItem(const MaterializeTemporaryExpr *MTE) 97 : Data(MTE), Kind(MaterializationKind) {} 98 99 ConstructionContextItem(const CXXBindTemporaryExpr *BTE, 100 bool IsElided = false) 101 : Data(BTE), 102 Kind(IsElided ? ElidedDestructorKind : TemporaryDestructorKind) {} 103 104 ConstructionContextItem(const CXXConstructExpr *CE) 105 : Data(CE), Kind(ElidableConstructorKind) {} 106 107 ConstructionContextItem(const CallExpr *CE, unsigned Index) 108 : Data(CE), Kind(ArgumentKind), Index(Index) {} 109 110 ConstructionContextItem(const CXXConstructExpr *CE, unsigned Index) 111 : Data(CE), Kind(ArgumentKind), Index(Index) {} 112 113 ConstructionContextItem(const ObjCMessageExpr *ME, unsigned Index) 114 : Data(ME), Kind(ArgumentKind), Index(Index) {} 115 116 // A polymorphic version of the previous calls with dynamic type check. 117 ConstructionContextItem(const Expr *E, unsigned Index) 118 : Data(E), Kind(ArgumentKind), Index(Index) { 119 assert(isa<CallExpr>(E) || isa<CXXConstructExpr>(E) || 120 isa<ObjCMessageExpr>(E)); 121 } 122 123 ConstructionContextItem(const CXXCtorInitializer *Init) 124 : Data(Init), Kind(InitializerKind), Index(0) {} 125 126 ItemKind getKind() const { return Kind; } 127 128 LLVM_DUMP_METHOD StringRef getKindAsString() const { 129 return getKindAsString(getKind()); 130 } 131 132 /// The construction site - the statement that triggered the construction 133 /// for one of its parts. For instance, stack variable declaration statement 134 /// triggers construction of itself or its elements if it's an array, 135 /// new-expression triggers construction of the newly allocated object(s). 136 const Stmt *getStmt() const { 137 assert(hasStatement()); 138 return static_cast<const Stmt *>(Data); 139 } 140 141 const Stmt *getStmtOrNull() const { 142 return hasStatement() ? getStmt() : nullptr; 143 } 144 145 /// The construction site is not necessarily a statement. It may also be a 146 /// CXXCtorInitializer, which means that a member variable is being 147 /// constructed during initialization of the object that contains it. 148 const CXXCtorInitializer *getCXXCtorInitializer() const { 149 assert(hasInitializer()); 150 return static_cast<const CXXCtorInitializer *>(Data); 151 } 152 153 /// If a single trigger statement triggers multiple constructors, they are 154 /// usually being enumerated. This covers function argument constructors 155 /// triggered by a call-expression and items in an initializer list triggered 156 /// by an init-list-expression. 157 unsigned getIndex() const { 158 // This is a fairly specific request. Let's make sure the user knows 159 // what he's doing. 160 assert(hasIndex()); 161 return Index; 162 } 163 164 void Profile(llvm::FoldingSetNodeID &ID) const { 165 ID.AddPointer(Data); 166 ID.AddInteger(Kind); 167 ID.AddInteger(Index); 168 } 169 170 bool operator==(const ConstructionContextItem &Other) const { 171 // For most kinds the Index comparison is trivially true, but 172 // checking kind separately doesn't seem to be less expensive 173 // than checking Index. Same in operator<(). 174 return std::make_tuple(Data, Kind, Index) == 175 std::make_tuple(Other.Data, Other.Kind, Other.Index); 176 } 177 178 bool operator<(const ConstructionContextItem &Other) const { 179 return std::make_tuple(Data, Kind, Index) < 180 std::make_tuple(Other.Data, Other.Kind, Other.Index); 181 } 182}; 183 184/// Construction context can be seen as a linked list of multiple layers. 185/// Sometimes a single trigger is not enough to describe the construction 186/// site. That's what causing us to have a chain of "partial" construction 187/// context layers. Some examples: 188/// - A constructor within in an aggregate initializer list within a variable 189/// would have a construction context of the initializer list with 190/// the parent construction context of a variable. 191/// - A constructor for a temporary that needs to be both destroyed 192/// and materialized into an elidable copy constructor would have a 193/// construction context of a CXXBindTemporaryExpr with the parent 194/// construction context of a MaterializeTemproraryExpr. 195/// Not all of these are currently supported. 196/// Layers are created gradually while traversing the AST, and layers that 197/// represent the outmost AST nodes are built first, while the node that 198/// immediately contains the constructor would be built last and capture the 199/// previous layers as its parents. Construction context captures the last layer 200/// (which has links to the previous layers) and classifies the seemingly 201/// arbitrary chain of layers into one of the possible ways of constructing 202/// an object in C++ for user-friendly experience. 203class ConstructionContextLayer { 204 const ConstructionContextLayer *Parent = nullptr; 205 ConstructionContextItem Item; 206 207 ConstructionContextLayer(ConstructionContextItem Item, 208 const ConstructionContextLayer *Parent) 209 : Parent(Parent), Item(Item) {} 210 211public: 212 static const ConstructionContextLayer * 213 create(BumpVectorContext &C, const ConstructionContextItem &Item, 214 const ConstructionContextLayer *Parent = nullptr); 215 216 const ConstructionContextItem &getItem() const { return Item; } 217 const ConstructionContextLayer *getParent() const { return Parent; } 218 bool isLast() const { return !Parent; } 219 220 /// See if Other is a proper initial segment of this construction context 221 /// in terms of the parent chain - i.e. a few first parents coincide and 222 /// then the other context terminates but our context goes further - i.e., 223 /// we are providing the same context that the other context provides, 224 /// and a bit more above that. 225 bool isStrictlyMoreSpecificThan(const ConstructionContextLayer *Other) const; 226}; 227 228 229/// ConstructionContext's subclasses describe different ways of constructing 230/// an object in C++. The context re-captures the essential parent AST nodes 231/// of the CXXConstructExpr it is assigned to and presents these nodes 232/// through easy-to-understand accessor methods. 233class ConstructionContext { 234public: 235 enum Kind { 236 SimpleVariableKind, 237 CXX17ElidedCopyVariableKind, 238 VARIABLE_BEGIN = SimpleVariableKind, 239 VARIABLE_END = CXX17ElidedCopyVariableKind, 240 SimpleConstructorInitializerKind, 241 CXX17ElidedCopyConstructorInitializerKind, 242 INITIALIZER_BEGIN = SimpleConstructorInitializerKind, 243 INITIALIZER_END = CXX17ElidedCopyConstructorInitializerKind, 244 NewAllocatedObjectKind, 245 SimpleTemporaryObjectKind, 246 ElidedTemporaryObjectKind, 247 TEMPORARY_BEGIN = SimpleTemporaryObjectKind, 248 TEMPORARY_END = ElidedTemporaryObjectKind, 249 SimpleReturnedValueKind, 250 CXX17ElidedCopyReturnedValueKind, 251 RETURNED_VALUE_BEGIN = SimpleReturnedValueKind, 252 RETURNED_VALUE_END = CXX17ElidedCopyReturnedValueKind, 253 ArgumentKind 254 }; 255 256protected: 257 Kind K; 258 259 // Do not make public! These need to only be constructed 260 // via createFromLayers(). 261 explicit ConstructionContext(Kind K) : K(K) {} 262 263private: 264 // A helper function for constructing an instance into a bump vector context. 265 template <typename T, typename... ArgTypes> 266 static T *create(BumpVectorContext &C, ArgTypes... Args) { 267 auto *CC = C.getAllocator().Allocate<T>(); 268 return new (CC) T(Args...); 269 } 270 271 // A sub-routine of createFromLayers() that deals with temporary objects 272 // that need to be materialized. The BTE argument is for the situation when 273 // the object also needs to be bound for destruction. 274 static const ConstructionContext *createMaterializedTemporaryFromLayers( 275 BumpVectorContext &C, const MaterializeTemporaryExpr *MTE, 276 const CXXBindTemporaryExpr *BTE, 277 const ConstructionContextLayer *ParentLayer); 278 279 // A sub-routine of createFromLayers() that deals with temporary objects 280 // that need to be bound for destruction. Automatically finds out if the 281 // object also needs to be materialized and delegates to 282 // createMaterializedTemporaryFromLayers() if necessary. 283 static const ConstructionContext * 284 createBoundTemporaryFromLayers( 285 BumpVectorContext &C, const CXXBindTemporaryExpr *BTE, 286 const ConstructionContextLayer *ParentLayer); 287 288public: 289 /// Consume the construction context layer, together with its parent layers, 290 /// and wrap it up into a complete construction context. May return null 291 /// if layers do not form any supported construction context. 292 static const ConstructionContext * 293 createFromLayers(BumpVectorContext &C, 294 const ConstructionContextLayer *TopLayer); 295 296 Kind getKind() const { return K; } 297}; 298 299/// An abstract base class for local variable constructors. 300class VariableConstructionContext : public ConstructionContext { 301 const DeclStmt *DS; 302 303protected: 304 VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS) 305 : ConstructionContext(K), DS(DS) { 306 assert(classof(this)); 307 assert(DS); 308 } 309 310public: 311 const DeclStmt *getDeclStmt() const { return DS; } 312 313 static bool classof(const ConstructionContext *CC) { 314 return CC->getKind() >= VARIABLE_BEGIN && 315 CC->getKind() <= VARIABLE_END; 316 } 317}; 318 319/// Represents construction into a simple local variable, eg. T var(123);. 320/// If a variable has an initializer, eg. T var = makeT();, then the final 321/// elidable copy-constructor from makeT() into var would also be a simple 322/// variable constructor handled by this class. 323class SimpleVariableConstructionContext : public VariableConstructionContext { 324 friend class ConstructionContext; // Allows to create<>() itself. 325 326 explicit SimpleVariableConstructionContext(const DeclStmt *DS) 327 : VariableConstructionContext(ConstructionContext::SimpleVariableKind, 328 DS) {} 329 330public: 331 static bool classof(const ConstructionContext *CC) { 332 return CC->getKind() == SimpleVariableKind; 333 } 334}; 335 336/// Represents construction into a simple variable with an initializer syntax, 337/// with a single constructor, eg. T var = makeT();. Such construction context 338/// may only appear in C++17 because previously it was split into a temporary 339/// object constructor and an elidable simple variable copy-constructor and 340/// we were producing separate construction contexts for these constructors. 341/// In C++17 we have a single construction context that combines both. 342/// Note that if the object has trivial destructor, then this code is 343/// indistinguishable from a simple variable constructor on the AST level; 344/// in this case we provide a simple variable construction context. 345class CXX17ElidedCopyVariableConstructionContext 346 : public VariableConstructionContext { 347 const CXXBindTemporaryExpr *BTE; 348 349 friend class ConstructionContext; // Allows to create<>() itself. 350 351 explicit CXX17ElidedCopyVariableConstructionContext( 352 const DeclStmt *DS, const CXXBindTemporaryExpr *BTE) 353 : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) { 354 assert(BTE); 355 } 356 357public: 358 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; } 359 360 static bool classof(const ConstructionContext *CC) { 361 return CC->getKind() == CXX17ElidedCopyVariableKind; 362 } 363}; 364 365// An abstract base class for constructor-initializer-based constructors. 366class ConstructorInitializerConstructionContext : public ConstructionContext { 367 const CXXCtorInitializer *I; 368 369protected: 370 explicit ConstructorInitializerConstructionContext( 371 ConstructionContext::Kind K, const CXXCtorInitializer *I) 372 : ConstructionContext(K), I(I) { 373 assert(classof(this)); 374 assert(I); 375 } 376 377public: 378 const CXXCtorInitializer *getCXXCtorInitializer() const { return I; } 379 380 static bool classof(const ConstructionContext *CC) { 381 return CC->getKind() >= INITIALIZER_BEGIN && 382 CC->getKind() <= INITIALIZER_END; 383 } 384}; 385 386/// Represents construction into a field or a base class within a bigger object 387/// via a constructor initializer, eg. T(): field(123) { ... }. 388class SimpleConstructorInitializerConstructionContext 389 : public ConstructorInitializerConstructionContext { 390 friend class ConstructionContext; // Allows to create<>() itself. 391 392 explicit SimpleConstructorInitializerConstructionContext( 393 const CXXCtorInitializer *I) 394 : ConstructorInitializerConstructionContext( 395 ConstructionContext::SimpleConstructorInitializerKind, I) {} 396 397public: 398 static bool classof(const ConstructionContext *CC) { 399 return CC->getKind() == SimpleConstructorInitializerKind; 400 } 401}; 402 403/// Represents construction into a field or a base class within a bigger object 404/// via a constructor initializer, with a single constructor, eg. 405/// T(): field(Field(123)) { ... }. Such construction context may only appear 406/// in C++17 because previously it was split into a temporary object constructor 407/// and an elidable simple constructor-initializer copy-constructor and we were 408/// producing separate construction contexts for these constructors. In C++17 409/// we have a single construction context that combines both. Note that if the 410/// object has trivial destructor, then this code is indistinguishable from 411/// a simple constructor-initializer constructor on the AST level; in this case 412/// we provide a simple constructor-initializer construction context. 413class CXX17ElidedCopyConstructorInitializerConstructionContext 414 : public ConstructorInitializerConstructionContext { 415 const CXXBindTemporaryExpr *BTE; 416 417 friend class ConstructionContext; // Allows to create<>() itself. 418 419 explicit CXX17ElidedCopyConstructorInitializerConstructionContext( 420 const CXXCtorInitializer *I, const CXXBindTemporaryExpr *BTE) 421 : ConstructorInitializerConstructionContext( 422 CXX17ElidedCopyConstructorInitializerKind, I), 423 BTE(BTE) { 424 assert(BTE); 425 } 426 427public: 428 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; } 429 430 static bool classof(const ConstructionContext *CC) { 431 return CC->getKind() == CXX17ElidedCopyConstructorInitializerKind; 432 } 433}; 434 435/// Represents immediate initialization of memory allocated by operator new, 436/// eg. new T(123);. 437class NewAllocatedObjectConstructionContext : public ConstructionContext { 438 const CXXNewExpr *NE; 439 440 friend class ConstructionContext; // Allows to create<>() itself. 441 442 explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE) 443 : ConstructionContext(ConstructionContext::NewAllocatedObjectKind), 444 NE(NE) { 445 assert(NE); 446 } 447 448public: 449 const CXXNewExpr *getCXXNewExpr() const { return NE; } 450 451 static bool classof(const ConstructionContext *CC) { 452 return CC->getKind() == NewAllocatedObjectKind; 453 } 454}; 455 456/// Represents a temporary object, eg. T(123), that does not immediately cross 457/// function boundaries "by value"; constructors that construct function 458/// value-type arguments or values that are immediately returned from the 459/// function that returns a value receive separate construction context kinds. 460class TemporaryObjectConstructionContext : public ConstructionContext { 461 const CXXBindTemporaryExpr *BTE; 462 const MaterializeTemporaryExpr *MTE; 463 464protected: 465 explicit TemporaryObjectConstructionContext( 466 ConstructionContext::Kind K, const CXXBindTemporaryExpr *BTE, 467 const MaterializeTemporaryExpr *MTE) 468 : ConstructionContext(K), BTE(BTE), MTE(MTE) { 469 // Both BTE and MTE can be null here, all combinations possible. 470 // Even though for now at least one should be non-null, we simply haven't 471 // implemented the other case yet (this would be a temporary in the middle 472 // of nowhere that doesn't have a non-trivial destructor). 473 } 474 475public: 476 /// CXXBindTemporaryExpr here is non-null as long as the temporary has 477 /// a non-trivial destructor. 478 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { 479 return BTE; 480 } 481 482 /// MaterializeTemporaryExpr is non-null as long as the temporary is actually 483 /// used after construction, eg. by binding to a reference (lifetime 484 /// extension), accessing a field, calling a method, or passing it into 485 /// a function (an elidable copy or move constructor would be a common 486 /// example) by reference. 487 const MaterializeTemporaryExpr *getMaterializedTemporaryExpr() const { 488 return MTE; 489 } 490 491 static bool classof(const ConstructionContext *CC) { 492 return CC->getKind() >= TEMPORARY_BEGIN && CC->getKind() <= TEMPORARY_END; 493 } 494}; 495 496/// Represents a temporary object that is not constructed for the purpose of 497/// being immediately copied/moved by an elidable copy/move-constructor. 498/// This includes temporary objects "in the middle of nowhere" like T(123) and 499/// lifetime-extended temporaries. 500class SimpleTemporaryObjectConstructionContext 501 : public TemporaryObjectConstructionContext { 502 friend class ConstructionContext; // Allows to create<>() itself. 503 504 explicit SimpleTemporaryObjectConstructionContext( 505 const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE) 506 : TemporaryObjectConstructionContext( 507 ConstructionContext::SimpleTemporaryObjectKind, BTE, MTE) {} 508 509public: 510 static bool classof(const ConstructionContext *CC) { 511 return CC->getKind() == SimpleTemporaryObjectKind; 512 } 513}; 514 515/// Represents a temporary object that is constructed for the sole purpose 516/// of being immediately copied by an elidable copy/move constructor. 517/// For example, T t = T(123); includes a temporary T(123) that is immediately 518/// copied to variable t. In such cases the elidable copy can (but not 519/// necessarily should) be omitted ("elided") accodring to the rules of the 520/// language; the constructor would then construct variable t directly. 521/// This construction context contains information of the elidable constructor 522/// and its respective construction context. 523class ElidedTemporaryObjectConstructionContext 524 : public TemporaryObjectConstructionContext { 525 const CXXConstructExpr *ElidedCE; 526 const ConstructionContext *ElidedCC; 527 528 friend class ConstructionContext; // Allows to create<>() itself. 529 530 explicit ElidedTemporaryObjectConstructionContext( 531 const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE, 532 const CXXConstructExpr *ElidedCE, const ConstructionContext *ElidedCC) 533 : TemporaryObjectConstructionContext( 534 ConstructionContext::ElidedTemporaryObjectKind, BTE, MTE), 535 ElidedCE(ElidedCE), ElidedCC(ElidedCC) { 536 // Elided constructor and its context should be either both specified 537 // or both unspecified. In the former case, the constructor must be 538 // elidable. 539 assert(ElidedCE && ElidedCE->isElidable() && ElidedCC); 540 } 541 542public: 543 const CXXConstructExpr *getConstructorAfterElision() const { 544 return ElidedCE; 545 } 546 547 const ConstructionContext *getConstructionContextAfterElision() const { 548 return ElidedCC; 549 } 550 551 static bool classof(const ConstructionContext *CC) { 552 return CC->getKind() == ElidedTemporaryObjectKind; 553 } 554}; 555 556class ReturnedValueConstructionContext : public ConstructionContext { 557 const ReturnStmt *RS; 558 559protected: 560 explicit ReturnedValueConstructionContext(ConstructionContext::Kind K, 561 const ReturnStmt *RS) 562 : ConstructionContext(K), RS(RS) { 563 assert(classof(this)); 564 assert(RS); 565 } 566 567public: 568 const ReturnStmt *getReturnStmt() const { return RS; } 569 570 static bool classof(const ConstructionContext *CC) { 571 return CC->getKind() >= RETURNED_VALUE_BEGIN && 572 CC->getKind() <= RETURNED_VALUE_END; 573 } 574}; 575 576/// Represents a temporary object that is being immediately returned from a 577/// function by value, eg. return t; or return T(123);. In this case there is 578/// always going to be a constructor at the return site. However, the usual 579/// temporary-related bureaucracy (CXXBindTemporaryExpr, 580/// MaterializeTemporaryExpr) is normally located in the caller function's AST. 581class SimpleReturnedValueConstructionContext 582 : public ReturnedValueConstructionContext { 583 friend class ConstructionContext; // Allows to create<>() itself. 584 585 explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS) 586 : ReturnedValueConstructionContext( 587 ConstructionContext::SimpleReturnedValueKind, RS) {} 588 589public: 590 static bool classof(const ConstructionContext *CC) { 591 return CC->getKind() == SimpleReturnedValueKind; 592 } 593}; 594 595/// Represents a temporary object that is being immediately returned from a 596/// function by value, eg. return t; or return T(123); in C++17. 597/// In C++17 there is not going to be an elidable copy constructor at the 598/// return site. However, the usual temporary-related bureaucracy (CXXBindTemporaryExpr, 599/// MaterializeTemporaryExpr) is normally located in the caller function's AST. 600/// Note that if the object has trivial destructor, then this code is 601/// indistinguishable from a simple returned value constructor on the AST level; 602/// in this case we provide a simple returned value construction context. 603class CXX17ElidedCopyReturnedValueConstructionContext 604 : public ReturnedValueConstructionContext { 605 const CXXBindTemporaryExpr *BTE; 606 607 friend class ConstructionContext; // Allows to create<>() itself. 608 609 explicit CXX17ElidedCopyReturnedValueConstructionContext( 610 const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE) 611 : ReturnedValueConstructionContext( 612 ConstructionContext::CXX17ElidedCopyReturnedValueKind, RS), 613 BTE(BTE) { 614 assert(BTE); 615 } 616 617public: 618 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; } 619 620 static bool classof(const ConstructionContext *CC) { 621 return CC->getKind() == CXX17ElidedCopyReturnedValueKind; 622 } 623}; 624 625class ArgumentConstructionContext : public ConstructionContext { 626 // The call of which the context is an argument. 627 const Expr *CE; 628 629 // Which argument we're constructing. Note that when numbering between 630 // arguments and parameters is inconsistent (eg., operator calls), 631 // this is the index of the argument, not of the parameter. 632 unsigned Index; 633 634 // Whether the object needs to be destroyed. 635 const CXXBindTemporaryExpr *BTE; 636 637 friend class ConstructionContext; // Allows to create<>() itself. 638 639 explicit ArgumentConstructionContext(const Expr *CE, unsigned Index, 640 const CXXBindTemporaryExpr *BTE) 641 : ConstructionContext(ArgumentKind), CE(CE), 642 Index(Index), BTE(BTE) { 643 assert(isa<CallExpr>(CE) || isa<CXXConstructExpr>(CE) || 644 isa<ObjCMessageExpr>(CE)); 645 // BTE is optional. 646 } 647 648public: 649 const Expr *getCallLikeExpr() const { return CE; } 650 unsigned getIndex() const { return Index; } 651 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; } 652 653 static bool classof(const ConstructionContext *CC) { 654 return CC->getKind() == ArgumentKind; 655 } 656}; 657 658} // end namespace clang 659 660#endif // LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H 661