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