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 23 namespace 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. 28 class ConstructionContextItem { 29 public: 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 63 private: 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 83 public: 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. 203 class ConstructionContextLayer { 204 const ConstructionContextLayer *Parent = nullptr; 205 ConstructionContextItem Item; 206 207 ConstructionContextLayer(ConstructionContextItem Item, 208 const ConstructionContextLayer *Parent) 209 : Parent(Parent), Item(Item) {} 210 211 public: 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. 233 class ConstructionContext { 234 public: 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 256 protected: 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 263 private: 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 288 public: 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. 300 class VariableConstructionContext : public ConstructionContext { 301 const DeclStmt *DS; 302 303 protected: 304 VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS) 305 : ConstructionContext(K), DS(DS) { 306 assert(classof(this)); 307 assert(DS); 308 } 309 310 public: 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. 323 class 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 330 public: 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. 345 class 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 357 public: 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. 366 class ConstructorInitializerConstructionContext : public ConstructionContext { 367 const CXXCtorInitializer *I; 368 369 protected: 370 explicit ConstructorInitializerConstructionContext( 371 ConstructionContext::Kind K, const CXXCtorInitializer *I) 372 : ConstructionContext(K), I(I) { 373 assert(classof(this)); 374 assert(I); 375 } 376 377 public: 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) { ... }. 388 class 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 397 public: 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. 413 class 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 427 public: 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);. 437 class 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 448 public: 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. 460 class TemporaryObjectConstructionContext : public ConstructionContext { 461 const CXXBindTemporaryExpr *BTE; 462 const MaterializeTemporaryExpr *MTE; 463 464 protected: 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 475 public: 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. 500 class 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 509 public: 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. 523 class 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 542 public: 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 556 class ReturnedValueConstructionContext : public ConstructionContext { 557 const ReturnStmt *RS; 558 559 protected: 560 explicit ReturnedValueConstructionContext(ConstructionContext::Kind K, 561 const ReturnStmt *RS) 562 : ConstructionContext(K), RS(RS) { 563 assert(classof(this)); 564 assert(RS); 565 } 566 567 public: 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. 581 class 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 589 public: 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. 603 class 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 617 public: 618 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; } 619 620 static bool classof(const ConstructionContext *CC) { 621 return CC->getKind() == CXX17ElidedCopyReturnedValueKind; 622 } 623 }; 624 625 class 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 648 public: 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