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