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