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