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