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