1 //===-- Transfer.cpp --------------------------------------------*- 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 transfer functions that evaluate program statements and 10 // update an environment accordingly. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/Analysis/FlowSensitive/Transfer.h" 15 #include "clang/AST/Decl.h" 16 #include "clang/AST/DeclBase.h" 17 #include "clang/AST/DeclCXX.h" 18 #include "clang/AST/Expr.h" 19 #include "clang/AST/ExprCXX.h" 20 #include "clang/AST/OperationKinds.h" 21 #include "clang/AST/Stmt.h" 22 #include "clang/AST/StmtVisitor.h" 23 #include "clang/Analysis/FlowSensitive/ControlFlowContext.h" 24 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" 25 #include "clang/Analysis/FlowSensitive/NoopAnalysis.h" 26 #include "clang/Analysis/FlowSensitive/RecordOps.h" 27 #include "clang/Analysis/FlowSensitive/Value.h" 28 #include "clang/Basic/Builtins.h" 29 #include "clang/Basic/OperatorKinds.h" 30 #include "llvm/Support/Casting.h" 31 #include "llvm/Support/Debug.h" 32 #include <assert.h> 33 #include <cassert> 34 35 #define DEBUG_TYPE "dataflow" 36 37 namespace clang { 38 namespace dataflow { 39 40 const Environment *StmtToEnvMap::getEnvironment(const Stmt &S) const { 41 auto BlockIt = CFCtx.getStmtToBlock().find(&ignoreCFGOmittedNodes(S)); 42 assert(BlockIt != CFCtx.getStmtToBlock().end()); 43 if (!CFCtx.isBlockReachable(*BlockIt->getSecond())) 44 return nullptr; 45 if (BlockIt->getSecond()->getBlockID() == CurBlockID) 46 return &CurState.Env; 47 const auto &State = BlockToState[BlockIt->getSecond()->getBlockID()]; 48 if (!(State)) 49 return nullptr; 50 return &State->Env; 51 } 52 53 static BoolValue &evaluateBooleanEquality(const Expr &LHS, const Expr &RHS, 54 Environment &Env) { 55 Value *LHSValue = Env.getValue(LHS); 56 Value *RHSValue = Env.getValue(RHS); 57 58 if (LHSValue == RHSValue) 59 return Env.getBoolLiteralValue(true); 60 61 if (auto *LHSBool = dyn_cast_or_null<BoolValue>(LHSValue)) 62 if (auto *RHSBool = dyn_cast_or_null<BoolValue>(RHSValue)) 63 return Env.makeIff(*LHSBool, *RHSBool); 64 65 return Env.makeAtomicBoolValue(); 66 } 67 68 static BoolValue &unpackValue(BoolValue &V, Environment &Env) { 69 if (auto *Top = llvm::dyn_cast<TopBoolValue>(&V)) { 70 auto &A = Env.getDataflowAnalysisContext().arena(); 71 return A.makeBoolValue(A.makeAtomRef(Top->getAtom())); 72 } 73 return V; 74 } 75 76 // Unpacks the value (if any) associated with `E` and updates `E` to the new 77 // value, if any unpacking occured. Also, does the lvalue-to-rvalue conversion, 78 // by skipping past the reference. 79 static Value *maybeUnpackLValueExpr(const Expr &E, Environment &Env) { 80 auto *Loc = Env.getStorageLocation(E); 81 if (Loc == nullptr) 82 return nullptr; 83 auto *Val = Env.getValue(*Loc); 84 85 auto *B = dyn_cast_or_null<BoolValue>(Val); 86 if (B == nullptr) 87 return Val; 88 89 auto &UnpackedVal = unpackValue(*B, Env); 90 if (&UnpackedVal == Val) 91 return Val; 92 Env.setValue(*Loc, UnpackedVal); 93 return &UnpackedVal; 94 } 95 96 static void propagateValue(const Expr &From, const Expr &To, Environment &Env) { 97 if (auto *Val = Env.getValue(From)) 98 Env.setValue(To, *Val); 99 } 100 101 static void propagateStorageLocation(const Expr &From, const Expr &To, 102 Environment &Env) { 103 if (auto *Loc = Env.getStorageLocation(From)) 104 Env.setStorageLocation(To, *Loc); 105 } 106 107 // Propagates the value or storage location of `From` to `To` in cases where 108 // `From` may be either a glvalue or a prvalue. `To` must be a glvalue iff 109 // `From` is a glvalue. 110 static void propagateValueOrStorageLocation(const Expr &From, const Expr &To, 111 Environment &Env) { 112 assert(From.isGLValue() == To.isGLValue()); 113 if (From.isGLValue()) 114 propagateStorageLocation(From, To, Env); 115 else 116 propagateValue(From, To, Env); 117 } 118 119 namespace { 120 121 class TransferVisitor : public ConstStmtVisitor<TransferVisitor> { 122 public: 123 TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env) 124 : StmtToEnv(StmtToEnv), Env(Env) {} 125 126 void VisitBinaryOperator(const BinaryOperator *S) { 127 const Expr *LHS = S->getLHS(); 128 assert(LHS != nullptr); 129 130 const Expr *RHS = S->getRHS(); 131 assert(RHS != nullptr); 132 133 switch (S->getOpcode()) { 134 case BO_Assign: { 135 auto *LHSLoc = Env.getStorageLocation(*LHS); 136 if (LHSLoc == nullptr) 137 break; 138 139 auto *RHSVal = Env.getValue(*RHS); 140 if (RHSVal == nullptr) 141 break; 142 143 // Assign a value to the storage location of the left-hand side. 144 Env.setValue(*LHSLoc, *RHSVal); 145 146 // Assign a storage location for the whole expression. 147 Env.setStorageLocation(*S, *LHSLoc); 148 break; 149 } 150 case BO_LAnd: 151 case BO_LOr: { 152 BoolValue &LHSVal = getLogicOperatorSubExprValue(*LHS); 153 BoolValue &RHSVal = getLogicOperatorSubExprValue(*RHS); 154 155 if (S->getOpcode() == BO_LAnd) 156 Env.setValue(*S, Env.makeAnd(LHSVal, RHSVal)); 157 else 158 Env.setValue(*S, Env.makeOr(LHSVal, RHSVal)); 159 break; 160 } 161 case BO_NE: 162 case BO_EQ: { 163 auto &LHSEqRHSValue = evaluateBooleanEquality(*LHS, *RHS, Env); 164 Env.setValue(*S, S->getOpcode() == BO_EQ ? LHSEqRHSValue 165 : Env.makeNot(LHSEqRHSValue)); 166 break; 167 } 168 case BO_Comma: { 169 propagateValueOrStorageLocation(*RHS, *S, Env); 170 break; 171 } 172 default: 173 break; 174 } 175 } 176 177 void VisitDeclRefExpr(const DeclRefExpr *S) { 178 const ValueDecl *VD = S->getDecl(); 179 assert(VD != nullptr); 180 181 // Some `DeclRefExpr`s aren't glvalues, so we can't associate them with a 182 // `StorageLocation`, and there's also no sensible `Value` that we can 183 // assign to them. Examples: 184 // - Non-static member variables 185 // - Non static member functions 186 // Note: Member operators are an exception to this, but apparently only 187 // if the `DeclRefExpr` is used within the callee of a 188 // `CXXOperatorCallExpr`. In other cases, for example when applying the 189 // address-of operator, the `DeclRefExpr` is a prvalue. 190 if (!S->isGLValue()) 191 return; 192 193 auto *DeclLoc = Env.getStorageLocation(*VD); 194 if (DeclLoc == nullptr) 195 return; 196 197 Env.setStorageLocation(*S, *DeclLoc); 198 } 199 200 void VisitDeclStmt(const DeclStmt *S) { 201 // Group decls are converted into single decls in the CFG so the cast below 202 // is safe. 203 const auto &D = *cast<VarDecl>(S->getSingleDecl()); 204 205 ProcessVarDecl(D); 206 } 207 208 void ProcessVarDecl(const VarDecl &D) { 209 // Static local vars are already initialized in `Environment`. 210 if (D.hasGlobalStorage()) 211 return; 212 213 // If this is the holding variable for a `BindingDecl`, we may already 214 // have a storage location set up -- so check. (See also explanation below 215 // where we process the `BindingDecl`.) 216 if (D.getType()->isReferenceType() && Env.getStorageLocation(D) != nullptr) 217 return; 218 219 assert(Env.getStorageLocation(D) == nullptr); 220 221 Env.setStorageLocation(D, Env.createObject(D)); 222 223 // `DecompositionDecl` must be handled after we've interpreted the loc 224 // itself, because the binding expression refers back to the 225 // `DecompositionDecl` (even though it has no written name). 226 if (const auto *Decomp = dyn_cast<DecompositionDecl>(&D)) { 227 // If VarDecl is a DecompositionDecl, evaluate each of its bindings. This 228 // needs to be evaluated after initializing the values in the storage for 229 // VarDecl, as the bindings refer to them. 230 // FIXME: Add support for ArraySubscriptExpr. 231 // FIXME: Consider adding AST nodes used in BindingDecls to the CFG. 232 for (const auto *B : Decomp->bindings()) { 233 if (auto *ME = dyn_cast_or_null<MemberExpr>(B->getBinding())) { 234 auto *DE = dyn_cast_or_null<DeclRefExpr>(ME->getBase()); 235 if (DE == nullptr) 236 continue; 237 238 // ME and its base haven't been visited because they aren't included 239 // in the statements of the CFG basic block. 240 VisitDeclRefExpr(DE); 241 VisitMemberExpr(ME); 242 243 if (auto *Loc = Env.getStorageLocation(*ME)) 244 Env.setStorageLocation(*B, *Loc); 245 } else if (auto *VD = B->getHoldingVar()) { 246 // Holding vars are used to back the `BindingDecl`s of tuple-like 247 // types. The holding var declarations appear after the 248 // `DecompositionDecl`, so we have to explicitly process them here 249 // to know their storage location. They will be processed a second 250 // time when we visit their `VarDecl`s, so we have code that protects 251 // against this above. 252 ProcessVarDecl(*VD); 253 auto *VDLoc = Env.getStorageLocation(*VD); 254 assert(VDLoc != nullptr); 255 Env.setStorageLocation(*B, *VDLoc); 256 } 257 } 258 } 259 } 260 261 void VisitImplicitCastExpr(const ImplicitCastExpr *S) { 262 const Expr *SubExpr = S->getSubExpr(); 263 assert(SubExpr != nullptr); 264 265 switch (S->getCastKind()) { 266 case CK_IntegralToBoolean: { 267 // This cast creates a new, boolean value from the integral value. We 268 // model that with a fresh value in the environment, unless it's already a 269 // boolean. 270 if (auto *SubExprVal = 271 dyn_cast_or_null<BoolValue>(Env.getValue(*SubExpr))) 272 Env.setValue(*S, *SubExprVal); 273 else 274 // FIXME: If integer modeling is added, then update this code to create 275 // the boolean based on the integer model. 276 Env.setValue(*S, Env.makeAtomicBoolValue()); 277 break; 278 } 279 280 case CK_LValueToRValue: { 281 // When an L-value is used as an R-value, it may result in sharing, so we 282 // need to unpack any nested `Top`s. 283 auto *SubExprVal = maybeUnpackLValueExpr(*SubExpr, Env); 284 if (SubExprVal == nullptr) 285 break; 286 287 Env.setValue(*S, *SubExprVal); 288 break; 289 } 290 291 case CK_IntegralCast: 292 // FIXME: This cast creates a new integral value from the 293 // subexpression. But, because we don't model integers, we don't 294 // distinguish between this new value and the underlying one. If integer 295 // modeling is added, then update this code to create a fresh location and 296 // value. 297 case CK_UncheckedDerivedToBase: 298 case CK_ConstructorConversion: 299 case CK_UserDefinedConversion: 300 // FIXME: Add tests that excercise CK_UncheckedDerivedToBase, 301 // CK_ConstructorConversion, and CK_UserDefinedConversion. 302 case CK_NoOp: { 303 // FIXME: Consider making `Environment::getStorageLocation` skip noop 304 // expressions (this and other similar expressions in the file) instead 305 // of assigning them storage locations. 306 propagateValueOrStorageLocation(*SubExpr, *S, Env); 307 break; 308 } 309 case CK_NullToPointer: { 310 auto &NullPointerVal = 311 Env.getOrCreateNullPointerValue(S->getType()->getPointeeType()); 312 Env.setValue(*S, NullPointerVal); 313 break; 314 } 315 case CK_NullToMemberPointer: 316 // FIXME: Implement pointers to members. For now, don't associate a value 317 // with this expression. 318 break; 319 case CK_FunctionToPointerDecay: { 320 StorageLocation *PointeeLoc = Env.getStorageLocation(*SubExpr); 321 if (PointeeLoc == nullptr) 322 break; 323 324 Env.setValue(*S, Env.create<PointerValue>(*PointeeLoc)); 325 break; 326 } 327 case CK_BuiltinFnToFnPtr: 328 // Despite its name, the result type of `BuiltinFnToFnPtr` is a function, 329 // not a function pointer. In addition, builtin functions can only be 330 // called directly; it is not legal to take their address. We therefore 331 // don't need to create a value or storage location for them. 332 break; 333 default: 334 break; 335 } 336 } 337 338 void VisitUnaryOperator(const UnaryOperator *S) { 339 const Expr *SubExpr = S->getSubExpr(); 340 assert(SubExpr != nullptr); 341 342 switch (S->getOpcode()) { 343 case UO_Deref: { 344 const auto *SubExprVal = Env.get<PointerValue>(*SubExpr); 345 if (SubExprVal == nullptr) 346 break; 347 348 Env.setStorageLocation(*S, SubExprVal->getPointeeLoc()); 349 break; 350 } 351 case UO_AddrOf: { 352 // FIXME: Model pointers to members. 353 if (S->getType()->isMemberPointerType()) 354 break; 355 356 if (StorageLocation *PointeeLoc = Env.getStorageLocation(*SubExpr)) 357 Env.setValue(*S, Env.create<PointerValue>(*PointeeLoc)); 358 break; 359 } 360 case UO_LNot: { 361 auto *SubExprVal = dyn_cast_or_null<BoolValue>(Env.getValue(*SubExpr)); 362 if (SubExprVal == nullptr) 363 break; 364 365 Env.setValue(*S, Env.makeNot(*SubExprVal)); 366 break; 367 } 368 default: 369 break; 370 } 371 } 372 373 void VisitCXXThisExpr(const CXXThisExpr *S) { 374 auto *ThisPointeeLoc = Env.getThisPointeeStorageLocation(); 375 if (ThisPointeeLoc == nullptr) 376 // Unions are not supported yet, and will not have a location for the 377 // `this` expression's pointee. 378 return; 379 380 Env.setValue(*S, Env.create<PointerValue>(*ThisPointeeLoc)); 381 } 382 383 void VisitCXXNewExpr(const CXXNewExpr *S) { 384 if (Value *Val = Env.createValue(S->getType())) 385 Env.setValue(*S, *Val); 386 } 387 388 void VisitCXXDeleteExpr(const CXXDeleteExpr *S) { 389 // Empty method. 390 // We consciously don't do anything on deletes. Diagnosing double deletes 391 // (for example) should be done by a specific analysis, not by the 392 // framework. 393 } 394 395 void VisitReturnStmt(const ReturnStmt *S) { 396 if (!Env.getDataflowAnalysisContext().getOptions().ContextSensitiveOpts) 397 return; 398 399 auto *Ret = S->getRetValue(); 400 if (Ret == nullptr) 401 return; 402 403 if (Ret->isPRValue()) { 404 auto *Val = Env.getValue(*Ret); 405 if (Val == nullptr) 406 return; 407 408 // FIXME: Model NRVO. 409 Env.setReturnValue(Val); 410 } else { 411 auto *Loc = Env.getStorageLocation(*Ret); 412 if (Loc == nullptr) 413 return; 414 415 // FIXME: Model NRVO. 416 Env.setReturnStorageLocation(Loc); 417 } 418 } 419 420 void VisitMemberExpr(const MemberExpr *S) { 421 ValueDecl *Member = S->getMemberDecl(); 422 assert(Member != nullptr); 423 424 // FIXME: Consider assigning pointer values to function member expressions. 425 if (Member->isFunctionOrFunctionTemplate()) 426 return; 427 428 // FIXME: if/when we add support for modeling enums, use that support here. 429 if (isa<EnumConstantDecl>(Member)) 430 return; 431 432 if (auto *D = dyn_cast<VarDecl>(Member)) { 433 if (D->hasGlobalStorage()) { 434 auto *VarDeclLoc = Env.getStorageLocation(*D); 435 if (VarDeclLoc == nullptr) 436 return; 437 438 Env.setStorageLocation(*S, *VarDeclLoc); 439 return; 440 } 441 } 442 443 RecordStorageLocation *BaseLoc = getBaseObjectLocation(*S, Env); 444 if (BaseLoc == nullptr) 445 return; 446 447 auto *MemberLoc = BaseLoc->getChild(*Member); 448 if (MemberLoc == nullptr) 449 return; 450 Env.setStorageLocation(*S, *MemberLoc); 451 } 452 453 void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *S) { 454 const Expr *InitExpr = S->getExpr(); 455 assert(InitExpr != nullptr); 456 propagateValueOrStorageLocation(*InitExpr, *S, Env); 457 } 458 459 void VisitCXXConstructExpr(const CXXConstructExpr *S) { 460 const CXXConstructorDecl *ConstructorDecl = S->getConstructor(); 461 assert(ConstructorDecl != nullptr); 462 463 if (ConstructorDecl->isCopyOrMoveConstructor()) { 464 // It is permissible for a copy/move constructor to have additional 465 // parameters as long as they have default arguments defined for them. 466 assert(S->getNumArgs() != 0); 467 468 const Expr *Arg = S->getArg(0); 469 assert(Arg != nullptr); 470 471 auto *ArgLoc = Env.get<RecordStorageLocation>(*Arg); 472 if (ArgLoc == nullptr) 473 return; 474 475 if (S->isElidable()) { 476 if (Value *Val = Env.getValue(*ArgLoc)) 477 Env.setValue(*S, *Val); 478 } else { 479 auto &Val = *cast<RecordValue>(Env.createValue(S->getType())); 480 Env.setValue(*S, Val); 481 copyRecord(*ArgLoc, Val.getLoc(), Env); 482 } 483 return; 484 } 485 486 // `CXXConstructExpr` can have array type if default-initializing an array 487 // of records, and we currently can't create values for arrays. So check if 488 // we've got a record type. 489 if (S->getType()->isRecordType()) { 490 auto &InitialVal = *cast<RecordValue>(Env.createValue(S->getType())); 491 Env.setValue(*S, InitialVal); 492 } 493 494 transferInlineCall(S, ConstructorDecl); 495 } 496 497 void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) { 498 if (S->getOperator() == OO_Equal) { 499 assert(S->getNumArgs() == 2); 500 501 const Expr *Arg0 = S->getArg(0); 502 assert(Arg0 != nullptr); 503 504 const Expr *Arg1 = S->getArg(1); 505 assert(Arg1 != nullptr); 506 507 // Evaluate only copy and move assignment operators. 508 const auto *Method = 509 dyn_cast_or_null<CXXMethodDecl>(S->getDirectCallee()); 510 if (!Method) 511 return; 512 if (!Method->isCopyAssignmentOperator() && 513 !Method->isMoveAssignmentOperator()) 514 return; 515 516 RecordStorageLocation *LocSrc = nullptr; 517 if (Arg1->isPRValue()) { 518 if (auto *Val = Env.get<RecordValue>(*Arg1)) 519 LocSrc = &Val->getLoc(); 520 } else { 521 LocSrc = Env.get<RecordStorageLocation>(*Arg1); 522 } 523 auto *LocDst = Env.get<RecordStorageLocation>(*Arg0); 524 525 if (LocSrc == nullptr || LocDst == nullptr) 526 return; 527 528 // The assignment operators are different from the type of the destination 529 // in this model (i.e. in one of their base classes). This must be very 530 // rare and we just bail. 531 if (Method->getFunctionObjectParameterType() 532 .getCanonicalType() 533 .getUnqualifiedType() != 534 LocDst->getType().getCanonicalType().getUnqualifiedType()) 535 return; 536 537 copyRecord(*LocSrc, *LocDst, Env); 538 539 // If the expr is a glvalue, we can reasonably assume the operator is 540 // returning T& and thus we can assign it `LocDst`. 541 if (S->isGLValue()) { 542 Env.setStorageLocation(*S, *LocDst); 543 } else if (S->getType()->isRecordType()) { 544 // Make sure that we have a `RecordValue` for this expression so that 545 // `Environment::getResultObjectLocation()` is able to return a location 546 // for it. 547 if (Env.getValue(*S) == nullptr) 548 refreshRecordValue(*S, Env); 549 } 550 551 return; 552 } 553 554 // CXXOperatorCallExpr can be prvalues. Call `VisitCallExpr`() to create 555 // a `RecordValue` for them so that `Environment::getResultObjectLocation()` 556 // can return a value. 557 VisitCallExpr(S); 558 } 559 560 void VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *RBO) { 561 propagateValue(*RBO->getSemanticForm(), *RBO, Env); 562 } 563 564 void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *S) { 565 if (S->getCastKind() == CK_ConstructorConversion) { 566 const Expr *SubExpr = S->getSubExpr(); 567 assert(SubExpr != nullptr); 568 569 propagateValue(*SubExpr, *S, Env); 570 } 571 } 572 573 void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *S) { 574 if (Value *Val = Env.createValue(S->getType())) 575 Env.setValue(*S, *Val); 576 } 577 578 void VisitCallExpr(const CallExpr *S) { 579 // Of clang's builtins, only `__builtin_expect` is handled explicitly, since 580 // others (like trap, debugtrap, and unreachable) are handled by CFG 581 // construction. 582 if (S->isCallToStdMove()) { 583 assert(S->getNumArgs() == 1); 584 585 const Expr *Arg = S->getArg(0); 586 assert(Arg != nullptr); 587 588 auto *ArgLoc = Env.getStorageLocation(*Arg); 589 if (ArgLoc == nullptr) 590 return; 591 592 Env.setStorageLocation(*S, *ArgLoc); 593 } else if (S->getDirectCallee() != nullptr && 594 S->getDirectCallee()->getBuiltinID() == 595 Builtin::BI__builtin_expect) { 596 assert(S->getNumArgs() > 0); 597 assert(S->getArg(0) != nullptr); 598 auto *ArgVal = Env.getValue(*S->getArg(0)); 599 if (ArgVal == nullptr) 600 return; 601 Env.setValue(*S, *ArgVal); 602 } else if (const FunctionDecl *F = S->getDirectCallee()) { 603 transferInlineCall(S, F); 604 605 // If this call produces a prvalue of record type, make sure that we have 606 // a `RecordValue` for it. This is required so that 607 // `Environment::getResultObjectLocation()` is able to return a location 608 // for this `CallExpr`. 609 if (S->getType()->isRecordType() && S->isPRValue()) 610 if (Env.getValue(*S) == nullptr) 611 refreshRecordValue(*S, Env); 612 } 613 } 614 615 void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *S) { 616 const Expr *SubExpr = S->getSubExpr(); 617 assert(SubExpr != nullptr); 618 619 Value *SubExprVal = Env.getValue(*SubExpr); 620 if (SubExprVal == nullptr) 621 return; 622 623 if (RecordValue *RecordVal = dyn_cast<RecordValue>(SubExprVal)) { 624 Env.setStorageLocation(*S, RecordVal->getLoc()); 625 return; 626 } 627 628 StorageLocation &Loc = Env.createStorageLocation(*S); 629 Env.setValue(Loc, *SubExprVal); 630 Env.setStorageLocation(*S, Loc); 631 } 632 633 void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *S) { 634 const Expr *SubExpr = S->getSubExpr(); 635 assert(SubExpr != nullptr); 636 637 propagateValue(*SubExpr, *S, Env); 638 } 639 640 void VisitCXXStaticCastExpr(const CXXStaticCastExpr *S) { 641 if (S->getCastKind() == CK_NoOp) { 642 const Expr *SubExpr = S->getSubExpr(); 643 assert(SubExpr != nullptr); 644 645 propagateValueOrStorageLocation(*SubExpr, *S, Env); 646 } 647 } 648 649 void VisitConditionalOperator(const ConditionalOperator *S) { 650 // FIXME: Revisit this once flow conditions are added to the framework. For 651 // `a = b ? c : d` we can add `b => a == c && !b => a == d` to the flow 652 // condition. 653 // When we do this, we will need to retrieve the values of the operands from 654 // the environments for the basic blocks they are computed in, in a similar 655 // way to how this is done for short-circuited logical operators in 656 // `getLogicOperatorSubExprValue()`. 657 if (S->isGLValue()) 658 Env.setStorageLocation(*S, Env.createObject(S->getType())); 659 else if (Value *Val = Env.createValue(S->getType())) 660 Env.setValue(*S, *Val); 661 } 662 663 void VisitInitListExpr(const InitListExpr *S) { 664 QualType Type = S->getType(); 665 666 if (!Type->isRecordType()) { 667 // Until array initialization is implemented, we skip arrays and don't 668 // need to care about cases where `getNumInits() > 1`. 669 if (!Type->isArrayType() && S->getNumInits() == 1) 670 propagateValueOrStorageLocation(*S->getInit(0), *S, Env); 671 return; 672 } 673 674 // In case the initializer list is transparent, we just need to propagate 675 // the value that it contains. 676 if (S->isSemanticForm() && S->isTransparent()) { 677 propagateValue(*S->getInit(0), *S, Env); 678 return; 679 } 680 681 llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs; 682 683 // This only contains the direct fields for the given type. 684 std::vector<const FieldDecl *> FieldsForInit = getFieldsForInitListExpr(S); 685 686 // `S->inits()` contains all the initializer expressions, including the 687 // ones for direct base classes. 688 ArrayRef<Expr *> Inits = S->inits(); 689 size_t InitIdx = 0; 690 691 // Unions initialized with an empty initializer list need special treatment. 692 // For structs/classes initialized with an empty initializer list, Clang 693 // puts `ImplicitValueInitExpr`s in `InitListExpr::inits()`, but for unions, 694 // it doesn't do this -- so we create an `ImplicitValueInitExpr` ourselves. 695 std::optional<ImplicitValueInitExpr> ImplicitValueInitForUnion; 696 SmallVector<Expr *> InitsForUnion; 697 if (S->getType()->isUnionType() && Inits.empty()) { 698 assert(FieldsForInit.size() == 1); 699 ImplicitValueInitForUnion.emplace(FieldsForInit.front()->getType()); 700 InitsForUnion.push_back(&*ImplicitValueInitForUnion); 701 Inits = InitsForUnion; 702 } 703 704 // Initialize base classes. 705 if (auto* R = S->getType()->getAsCXXRecordDecl()) { 706 assert(FieldsForInit.size() + R->getNumBases() == Inits.size()); 707 for ([[maybe_unused]] const CXXBaseSpecifier &Base : R->bases()) { 708 assert(InitIdx < Inits.size()); 709 auto Init = Inits[InitIdx++]; 710 assert(Base.getType().getCanonicalType() == 711 Init->getType().getCanonicalType()); 712 auto *BaseVal = Env.get<RecordValue>(*Init); 713 if (!BaseVal) 714 BaseVal = cast<RecordValue>(Env.createValue(Init->getType())); 715 // Take ownership of the fields of the `RecordValue` for the base class 716 // and incorporate them into the "flattened" set of fields for the 717 // derived class. 718 auto Children = BaseVal->getLoc().children(); 719 FieldLocs.insert(Children.begin(), Children.end()); 720 } 721 } 722 723 assert(FieldsForInit.size() == Inits.size() - InitIdx); 724 for (auto Field : FieldsForInit) { 725 assert(InitIdx < Inits.size()); 726 auto Init = Inits[InitIdx++]; 727 assert( 728 // The types are same, or 729 Field->getType().getCanonicalType().getUnqualifiedType() == 730 Init->getType().getCanonicalType().getUnqualifiedType() || 731 // The field's type is T&, and initializer is T 732 (Field->getType()->isReferenceType() && 733 Field->getType().getCanonicalType()->getPointeeType() == 734 Init->getType().getCanonicalType())); 735 auto& Loc = Env.createObject(Field->getType(), Init); 736 FieldLocs.insert({Field, &Loc}); 737 } 738 739 // In the case of a union, we don't in general have initializers for all 740 // of the fields. Create storage locations for the remaining fields (but 741 // don't associate them with values). 742 if (Type->isUnionType()) { 743 for (const FieldDecl *Field : 744 Env.getDataflowAnalysisContext().getModeledFields(Type)) { 745 if (auto [it, inserted] = FieldLocs.insert({Field, nullptr}); inserted) 746 it->second = &Env.createStorageLocation(Field->getType()); 747 } 748 } 749 750 // Check that we satisfy the invariant that a `RecordStorageLoation` 751 // contains exactly the set of modeled fields for that type. 752 // `ModeledFields` includes fields from all the bases, but only the 753 // modeled ones. However, if a class type is initialized with an 754 // `InitListExpr`, all fields in the class, including those from base 755 // classes, are included in the set of modeled fields. The code above 756 // should therefore populate exactly the modeled fields. 757 assert(containsSameFields( 758 Env.getDataflowAnalysisContext().getModeledFields(Type), FieldLocs)); 759 760 RecordStorageLocation::SyntheticFieldMap SyntheticFieldLocs; 761 for (const auto &Entry : 762 Env.getDataflowAnalysisContext().getSyntheticFields(Type)) { 763 SyntheticFieldLocs.insert( 764 {Entry.getKey(), &Env.createObject(Entry.getValue())}); 765 } 766 767 auto &Loc = Env.getDataflowAnalysisContext().createRecordStorageLocation( 768 Type, std::move(FieldLocs), std::move(SyntheticFieldLocs)); 769 RecordValue &RecordVal = Env.create<RecordValue>(Loc); 770 771 Env.setValue(Loc, RecordVal); 772 773 Env.setValue(*S, RecordVal); 774 775 // FIXME: Implement array initialization. 776 } 777 778 void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *S) { 779 Env.setValue(*S, Env.getBoolLiteralValue(S->getValue())); 780 } 781 782 void VisitIntegerLiteral(const IntegerLiteral *S) { 783 Env.setValue(*S, Env.getIntLiteralValue(S->getValue())); 784 } 785 786 void VisitParenExpr(const ParenExpr *S) { 787 // The CFG does not contain `ParenExpr` as top-level statements in basic 788 // blocks, however manual traversal to sub-expressions may encounter them. 789 // Redirect to the sub-expression. 790 auto *SubExpr = S->getSubExpr(); 791 assert(SubExpr != nullptr); 792 Visit(SubExpr); 793 } 794 795 void VisitExprWithCleanups(const ExprWithCleanups *S) { 796 // The CFG does not contain `ExprWithCleanups` as top-level statements in 797 // basic blocks, however manual traversal to sub-expressions may encounter 798 // them. Redirect to the sub-expression. 799 auto *SubExpr = S->getSubExpr(); 800 assert(SubExpr != nullptr); 801 Visit(SubExpr); 802 } 803 804 private: 805 /// Returns the value for the sub-expression `SubExpr` of a logic operator. 806 BoolValue &getLogicOperatorSubExprValue(const Expr &SubExpr) { 807 // `SubExpr` and its parent logic operator might be part of different basic 808 // blocks. We try to access the value that is assigned to `SubExpr` in the 809 // corresponding environment. 810 if (const Environment *SubExprEnv = StmtToEnv.getEnvironment(SubExpr)) 811 if (auto *Val = 812 dyn_cast_or_null<BoolValue>(SubExprEnv->getValue(SubExpr))) 813 return *Val; 814 815 // The sub-expression may lie within a basic block that isn't reachable, 816 // even if we need it to evaluate the current (reachable) expression 817 // (see https://discourse.llvm.org/t/70775). In this case, visit `SubExpr` 818 // within the current environment and then try to get the value that gets 819 // assigned to it. 820 if (Env.getValue(SubExpr) == nullptr) 821 Visit(&SubExpr); 822 if (auto *Val = dyn_cast_or_null<BoolValue>(Env.getValue(SubExpr))) 823 return *Val; 824 825 // If the value of `SubExpr` is still unknown, we create a fresh symbolic 826 // boolean value for it. 827 return Env.makeAtomicBoolValue(); 828 } 829 830 // If context sensitivity is enabled, try to analyze the body of the callee 831 // `F` of `S`. The type `E` must be either `CallExpr` or `CXXConstructExpr`. 832 template <typename E> 833 void transferInlineCall(const E *S, const FunctionDecl *F) { 834 const auto &Options = Env.getDataflowAnalysisContext().getOptions(); 835 if (!(Options.ContextSensitiveOpts && 836 Env.canDescend(Options.ContextSensitiveOpts->Depth, F))) 837 return; 838 839 const ControlFlowContext *CFCtx = 840 Env.getDataflowAnalysisContext().getControlFlowContext(F); 841 if (!CFCtx) 842 return; 843 844 // FIXME: We don't support context-sensitive analysis of recursion, so 845 // we should return early here if `F` is the same as the `FunctionDecl` 846 // holding `S` itself. 847 848 auto ExitBlock = CFCtx->getCFG().getExit().getBlockID(); 849 850 auto CalleeEnv = Env.pushCall(S); 851 852 // FIXME: Use the same analysis as the caller for the callee. Note, 853 // though, that doing so would require support for changing the analysis's 854 // ASTContext. 855 auto Analysis = NoopAnalysis(CFCtx->getDecl().getASTContext(), 856 DataflowAnalysisOptions{Options}); 857 858 auto BlockToOutputState = 859 dataflow::runDataflowAnalysis(*CFCtx, Analysis, CalleeEnv); 860 assert(BlockToOutputState); 861 assert(ExitBlock < BlockToOutputState->size()); 862 863 auto &ExitState = (*BlockToOutputState)[ExitBlock]; 864 assert(ExitState); 865 866 Env.popCall(S, ExitState->Env); 867 } 868 869 const StmtToEnvMap &StmtToEnv; 870 Environment &Env; 871 }; 872 873 } // namespace 874 875 void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env) { 876 TransferVisitor(StmtToEnv, Env).Visit(&S); 877 } 878 879 } // namespace dataflow 880 } // namespace clang 881