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