1 //===-- DataflowEnvironment.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 an Environment class that is used by dataflow analyses 10 // that run over Control-Flow Graphs (CFGs) to keep track of the state of the 11 // program at given program points. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" 16 #include "clang/AST/Decl.h" 17 #include "clang/AST/DeclCXX.h" 18 #include "clang/AST/ExprCXX.h" 19 #include "clang/AST/Stmt.h" 20 #include "clang/AST/Type.h" 21 #include "clang/Analysis/FlowSensitive/ASTOps.h" 22 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" 23 #include "clang/Analysis/FlowSensitive/DataflowLattice.h" 24 #include "clang/Analysis/FlowSensitive/Value.h" 25 #include "llvm/ADT/DenseMap.h" 26 #include "llvm/ADT/DenseSet.h" 27 #include "llvm/ADT/MapVector.h" 28 #include "llvm/ADT/STLExtras.h" 29 #include "llvm/ADT/ScopeExit.h" 30 #include "llvm/Support/ErrorHandling.h" 31 #include <cassert> 32 #include <memory> 33 #include <utility> 34 35 #define DEBUG_TYPE "dataflow" 36 37 namespace clang { 38 namespace dataflow { 39 40 // FIXME: convert these to parameters of the analysis or environment. Current 41 // settings have been experimentaly validated, but only for a particular 42 // analysis. 43 static constexpr int MaxCompositeValueDepth = 3; 44 static constexpr int MaxCompositeValueSize = 1000; 45 46 /// Returns a map consisting of key-value entries that are present in both maps. 47 static llvm::DenseMap<const ValueDecl *, StorageLocation *> intersectDeclToLoc( 48 const llvm::DenseMap<const ValueDecl *, StorageLocation *> &DeclToLoc1, 49 const llvm::DenseMap<const ValueDecl *, StorageLocation *> &DeclToLoc2) { 50 llvm::DenseMap<const ValueDecl *, StorageLocation *> Result; 51 for (auto &Entry : DeclToLoc1) { 52 auto It = DeclToLoc2.find(Entry.first); 53 if (It != DeclToLoc2.end() && Entry.second == It->second) 54 Result.insert({Entry.first, Entry.second}); 55 } 56 return Result; 57 } 58 59 // Performs a join on either `ExprToLoc` or `ExprToVal`. 60 // The maps must be consistent in the sense that any entries for the same 61 // expression must map to the same location / value. This is the case if we are 62 // performing a join for control flow within a full-expression (which is the 63 // only case when this function should be used). 64 template <typename MapT> 65 static MapT joinExprMaps(const MapT &Map1, const MapT &Map2) { 66 MapT Result = Map1; 67 68 for (const auto &Entry : Map2) { 69 [[maybe_unused]] auto [It, Inserted] = Result.insert(Entry); 70 // If there was an existing entry, its value should be the same as for the 71 // entry we were trying to insert. 72 assert(It->second == Entry.second); 73 } 74 75 return Result; 76 } 77 78 // Whether to consider equivalent two values with an unknown relation. 79 // 80 // FIXME: this function is a hack enabling unsoundness to support 81 // convergence. Once we have widening support for the reference/pointer and 82 // struct built-in models, this should be unconditionally `false` (and inlined 83 // as such at its call sites). 84 static bool equateUnknownValues(Value::Kind K) { 85 switch (K) { 86 case Value::Kind::Integer: 87 case Value::Kind::Pointer: 88 return true; 89 default: 90 return false; 91 } 92 } 93 94 static bool compareDistinctValues(QualType Type, Value &Val1, 95 const Environment &Env1, Value &Val2, 96 const Environment &Env2, 97 Environment::ValueModel &Model) { 98 // Note: Potentially costly, but, for booleans, we could check whether both 99 // can be proven equivalent in their respective environments. 100 101 // FIXME: move the reference/pointers logic from `areEquivalentValues` to here 102 // and implement separate, join/widen specific handling for 103 // reference/pointers. 104 switch (Model.compare(Type, Val1, Env1, Val2, Env2)) { 105 case ComparisonResult::Same: 106 return true; 107 case ComparisonResult::Different: 108 return false; 109 case ComparisonResult::Unknown: 110 return equateUnknownValues(Val1.getKind()); 111 } 112 llvm_unreachable("All cases covered in switch"); 113 } 114 115 /// Attempts to join distinct values `Val1` and `Val2` in `Env1` and `Env2`, 116 /// respectively, of the same type `Type`. Joining generally produces a single 117 /// value that (soundly) approximates the two inputs, although the actual 118 /// meaning depends on `Model`. 119 static Value *joinDistinctValues(QualType Type, Value &Val1, 120 const Environment &Env1, Value &Val2, 121 const Environment &Env2, 122 Environment &JoinedEnv, 123 Environment::ValueModel &Model) { 124 // Join distinct boolean values preserving information about the constraints 125 // in the respective path conditions. 126 if (isa<BoolValue>(&Val1) && isa<BoolValue>(&Val2)) { 127 // FIXME: Checking both values should be unnecessary, since they should have 128 // a consistent shape. However, right now we can end up with BoolValue's in 129 // integer-typed variables due to our incorrect handling of 130 // boolean-to-integer casts (we just propagate the BoolValue to the result 131 // of the cast). So, a join can encounter an integer in one branch but a 132 // bool in the other. 133 // For example: 134 // ``` 135 // std::optional<bool> o; 136 // int x; 137 // if (o.has_value()) 138 // x = o.value(); 139 // ``` 140 auto &Expr1 = cast<BoolValue>(Val1).formula(); 141 auto &Expr2 = cast<BoolValue>(Val2).formula(); 142 auto &A = JoinedEnv.arena(); 143 auto &JoinedVal = A.makeAtomRef(A.makeAtom()); 144 JoinedEnv.assume( 145 A.makeOr(A.makeAnd(A.makeAtomRef(Env1.getFlowConditionToken()), 146 A.makeEquals(JoinedVal, Expr1)), 147 A.makeAnd(A.makeAtomRef(Env2.getFlowConditionToken()), 148 A.makeEquals(JoinedVal, Expr2)))); 149 return &A.makeBoolValue(JoinedVal); 150 } 151 152 Value *JoinedVal = JoinedEnv.createValue(Type); 153 if (JoinedVal) 154 Model.join(Type, Val1, Env1, Val2, Env2, *JoinedVal, JoinedEnv); 155 156 return JoinedVal; 157 } 158 159 static WidenResult widenDistinctValues(QualType Type, Value &Prev, 160 const Environment &PrevEnv, 161 Value &Current, Environment &CurrentEnv, 162 Environment::ValueModel &Model) { 163 // Boolean-model widening. 164 if (isa<BoolValue>(Prev) && isa<BoolValue>(Current)) { 165 // FIXME: Checking both values should be unnecessary, but we can currently 166 // end up with `BoolValue`s in integer-typed variables. See comment in 167 // `joinDistinctValues()` for details. 168 auto &PrevBool = cast<BoolValue>(Prev); 169 auto &CurBool = cast<BoolValue>(Current); 170 171 if (isa<TopBoolValue>(Prev)) 172 // Safe to return `Prev` here, because Top is never dependent on the 173 // environment. 174 return {&Prev, LatticeEffect::Unchanged}; 175 176 // We may need to widen to Top, but before we do so, check whether both 177 // values are implied to be either true or false in the current environment. 178 // In that case, we can simply return a literal instead. 179 bool TruePrev = PrevEnv.proves(PrevBool.formula()); 180 bool TrueCur = CurrentEnv.proves(CurBool.formula()); 181 if (TruePrev && TrueCur) 182 return {&CurrentEnv.getBoolLiteralValue(true), LatticeEffect::Unchanged}; 183 if (!TruePrev && !TrueCur && 184 PrevEnv.proves(PrevEnv.arena().makeNot(PrevBool.formula())) && 185 CurrentEnv.proves(CurrentEnv.arena().makeNot(CurBool.formula()))) 186 return {&CurrentEnv.getBoolLiteralValue(false), LatticeEffect::Unchanged}; 187 188 return {&CurrentEnv.makeTopBoolValue(), LatticeEffect::Changed}; 189 } 190 191 // FIXME: Add other built-in model widening. 192 193 // Custom-model widening. 194 if (auto Result = Model.widen(Type, Prev, PrevEnv, Current, CurrentEnv)) 195 return *Result; 196 197 return {&Current, equateUnknownValues(Prev.getKind()) 198 ? LatticeEffect::Unchanged 199 : LatticeEffect::Changed}; 200 } 201 202 // Returns whether the values in `Map1` and `Map2` compare equal for those 203 // keys that `Map1` and `Map2` have in common. 204 template <typename Key> 205 static bool compareKeyToValueMaps(const llvm::MapVector<Key, Value *> &Map1, 206 const llvm::MapVector<Key, Value *> &Map2, 207 const Environment &Env1, 208 const Environment &Env2, 209 Environment::ValueModel &Model) { 210 for (auto &Entry : Map1) { 211 Key K = Entry.first; 212 assert(K != nullptr); 213 214 Value *Val = Entry.second; 215 assert(Val != nullptr); 216 217 auto It = Map2.find(K); 218 if (It == Map2.end()) 219 continue; 220 assert(It->second != nullptr); 221 222 if (!areEquivalentValues(*Val, *It->second) && 223 !compareDistinctValues(K->getType(), *Val, Env1, *It->second, Env2, 224 Model)) 225 return false; 226 } 227 228 return true; 229 } 230 231 // Perform a join on two `LocToVal` maps. 232 static llvm::MapVector<const StorageLocation *, Value *> 233 joinLocToVal(const llvm::MapVector<const StorageLocation *, Value *> &LocToVal, 234 const llvm::MapVector<const StorageLocation *, Value *> &LocToVal2, 235 const Environment &Env1, const Environment &Env2, 236 Environment &JoinedEnv, Environment::ValueModel &Model) { 237 llvm::MapVector<const StorageLocation *, Value *> Result; 238 for (auto &Entry : LocToVal) { 239 const StorageLocation *Loc = Entry.first; 240 assert(Loc != nullptr); 241 242 Value *Val = Entry.second; 243 assert(Val != nullptr); 244 245 auto It = LocToVal2.find(Loc); 246 if (It == LocToVal2.end()) 247 continue; 248 assert(It->second != nullptr); 249 250 if (Value *JoinedVal = Environment::joinValues( 251 Loc->getType(), Val, Env1, It->second, Env2, JoinedEnv, Model)) { 252 Result.insert({Loc, JoinedVal}); 253 } 254 } 255 256 return Result; 257 } 258 259 // Perform widening on either `LocToVal` or `ExprToVal`. `Key` must be either 260 // `const StorageLocation *` or `const Expr *`. 261 template <typename Key> 262 static llvm::MapVector<Key, Value *> 263 widenKeyToValueMap(const llvm::MapVector<Key, Value *> &CurMap, 264 const llvm::MapVector<Key, Value *> &PrevMap, 265 Environment &CurEnv, const Environment &PrevEnv, 266 Environment::ValueModel &Model, LatticeEffect &Effect) { 267 llvm::MapVector<Key, Value *> WidenedMap; 268 for (auto &Entry : CurMap) { 269 Key K = Entry.first; 270 assert(K != nullptr); 271 272 Value *Val = Entry.second; 273 assert(Val != nullptr); 274 275 auto PrevIt = PrevMap.find(K); 276 if (PrevIt == PrevMap.end()) 277 continue; 278 assert(PrevIt->second != nullptr); 279 280 if (areEquivalentValues(*Val, *PrevIt->second)) { 281 WidenedMap.insert({K, Val}); 282 continue; 283 } 284 285 auto [WidenedVal, ValEffect] = widenDistinctValues( 286 K->getType(), *PrevIt->second, PrevEnv, *Val, CurEnv, Model); 287 WidenedMap.insert({K, WidenedVal}); 288 if (ValEffect == LatticeEffect::Changed) 289 Effect = LatticeEffect::Changed; 290 } 291 292 return WidenedMap; 293 } 294 295 namespace { 296 297 // Visitor that builds a map from record prvalues to result objects. 298 // For each result object that it encounters, it propagates the storage location 299 // of the result object to all record prvalues that can initialize it. 300 class ResultObjectVisitor : public AnalysisASTVisitor { 301 public: 302 // `ResultObjectMap` will be filled with a map from record prvalues to result 303 // object. If this visitor will traverse a function that returns a record by 304 // value, `LocForRecordReturnVal` is the location to which this record should 305 // be written; otherwise, it is null. 306 explicit ResultObjectVisitor( 307 llvm::DenseMap<const Expr *, RecordStorageLocation *> &ResultObjectMap, 308 RecordStorageLocation *LocForRecordReturnVal, 309 DataflowAnalysisContext &DACtx) 310 : ResultObjectMap(ResultObjectMap), 311 LocForRecordReturnVal(LocForRecordReturnVal), DACtx(DACtx) {} 312 313 // Traverse all member and base initializers of `Ctor`. This function is not 314 // called by `RecursiveASTVisitor`; it should be called manually if we are 315 // analyzing a constructor. `ThisPointeeLoc` is the storage location that 316 // `this` points to. 317 void traverseConstructorInits(const CXXConstructorDecl *Ctor, 318 RecordStorageLocation *ThisPointeeLoc) { 319 assert(ThisPointeeLoc != nullptr); 320 for (const CXXCtorInitializer *Init : Ctor->inits()) { 321 Expr *InitExpr = Init->getInit(); 322 if (FieldDecl *Field = Init->getMember(); 323 Field != nullptr && Field->getType()->isRecordType()) { 324 PropagateResultObject(InitExpr, cast<RecordStorageLocation>( 325 ThisPointeeLoc->getChild(*Field))); 326 } else if (Init->getBaseClass()) { 327 PropagateResultObject(InitExpr, ThisPointeeLoc); 328 } 329 330 // Ensure that any result objects within `InitExpr` (e.g. temporaries) 331 // are also propagated to the prvalues that initialize them. 332 TraverseStmt(InitExpr); 333 334 // If this is a `CXXDefaultInitExpr`, also propagate any result objects 335 // within the default expression. 336 if (auto *DefaultInit = dyn_cast<CXXDefaultInitExpr>(InitExpr)) 337 TraverseStmt(DefaultInit->getExpr()); 338 } 339 } 340 341 bool VisitVarDecl(VarDecl *VD) override { 342 if (VD->getType()->isRecordType() && VD->hasInit()) 343 PropagateResultObject( 344 VD->getInit(), 345 &cast<RecordStorageLocation>(DACtx.getStableStorageLocation(*VD))); 346 return true; 347 } 348 349 bool VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE) override { 350 if (MTE->getType()->isRecordType()) 351 PropagateResultObject( 352 MTE->getSubExpr(), 353 &cast<RecordStorageLocation>(DACtx.getStableStorageLocation(*MTE))); 354 return true; 355 } 356 357 bool VisitReturnStmt(ReturnStmt *Return) override { 358 Expr *RetValue = Return->getRetValue(); 359 if (RetValue != nullptr && RetValue->getType()->isRecordType() && 360 RetValue->isPRValue()) 361 PropagateResultObject(RetValue, LocForRecordReturnVal); 362 return true; 363 } 364 365 bool VisitExpr(Expr *E) override { 366 // Clang's AST can have record-type prvalues without a result object -- for 367 // example as full-expressions contained in a compound statement or as 368 // arguments of call expressions. We notice this if we get here and a 369 // storage location has not yet been associated with `E`. In this case, 370 // treat this as if it was a `MaterializeTemporaryExpr`. 371 if (E->isPRValue() && E->getType()->isRecordType() && 372 !ResultObjectMap.contains(E)) 373 PropagateResultObject( 374 E, &cast<RecordStorageLocation>(DACtx.getStableStorageLocation(*E))); 375 return true; 376 } 377 378 void 379 PropagateResultObjectToRecordInitList(const RecordInitListHelper &InitList, 380 RecordStorageLocation *Loc) { 381 for (auto [Base, Init] : InitList.base_inits()) { 382 assert(Base->getType().getCanonicalType() == 383 Init->getType().getCanonicalType()); 384 385 // Storage location for the base class is the same as that of the 386 // derived class because we "flatten" the object hierarchy and put all 387 // fields in `RecordStorageLocation` of the derived class. 388 PropagateResultObject(Init, Loc); 389 } 390 391 for (auto [Field, Init] : InitList.field_inits()) { 392 // Fields of non-record type are handled in 393 // `TransferVisitor::VisitInitListExpr()`. 394 if (Field->getType()->isRecordType()) 395 PropagateResultObject( 396 Init, cast<RecordStorageLocation>(Loc->getChild(*Field))); 397 } 398 } 399 400 // Assigns `Loc` as the result object location of `E`, then propagates the 401 // location to all lower-level prvalues that initialize the same object as 402 // `E` (or one of its base classes or member variables). 403 void PropagateResultObject(Expr *E, RecordStorageLocation *Loc) { 404 if (!E->isPRValue() || !E->getType()->isRecordType()) { 405 assert(false); 406 // Ensure we don't propagate the result object if we hit this in a 407 // release build. 408 return; 409 } 410 411 ResultObjectMap[E] = Loc; 412 413 // The following AST node kinds are "original initializers": They are the 414 // lowest-level AST node that initializes a given object, and nothing 415 // below them can initialize the same object (or part of it). 416 if (isa<CXXConstructExpr>(E) || isa<CallExpr>(E) || isa<LambdaExpr>(E) || 417 isa<CXXDefaultArgExpr>(E) || isa<CXXStdInitializerListExpr>(E) || 418 isa<AtomicExpr>(E) || isa<CXXInheritedCtorInitExpr>(E) || 419 // We treat `BuiltinBitCastExpr` as an "original initializer" too as 420 // it may not even be casting from a record type -- and even if it is, 421 // the two objects are in general of unrelated type. 422 isa<BuiltinBitCastExpr>(E)) { 423 return; 424 } 425 if (auto *Op = dyn_cast<BinaryOperator>(E); 426 Op && Op->getOpcode() == BO_Cmp) { 427 // Builtin `<=>` returns a `std::strong_ordering` object. 428 return; 429 } 430 431 if (auto *InitList = dyn_cast<InitListExpr>(E)) { 432 if (!InitList->isSemanticForm()) 433 return; 434 if (InitList->isTransparent()) { 435 PropagateResultObject(InitList->getInit(0), Loc); 436 return; 437 } 438 439 PropagateResultObjectToRecordInitList(RecordInitListHelper(InitList), 440 Loc); 441 return; 442 } 443 444 if (auto *ParenInitList = dyn_cast<CXXParenListInitExpr>(E)) { 445 PropagateResultObjectToRecordInitList(RecordInitListHelper(ParenInitList), 446 Loc); 447 return; 448 } 449 450 if (auto *Op = dyn_cast<BinaryOperator>(E); Op && Op->isCommaOp()) { 451 PropagateResultObject(Op->getRHS(), Loc); 452 return; 453 } 454 455 if (auto *Cond = dyn_cast<AbstractConditionalOperator>(E)) { 456 PropagateResultObject(Cond->getTrueExpr(), Loc); 457 PropagateResultObject(Cond->getFalseExpr(), Loc); 458 return; 459 } 460 461 if (auto *SE = dyn_cast<StmtExpr>(E)) { 462 PropagateResultObject(cast<Expr>(SE->getSubStmt()->body_back()), Loc); 463 return; 464 } 465 466 if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(E)) { 467 PropagateResultObject(DIE->getExpr(), Loc); 468 return; 469 } 470 471 // All other expression nodes that propagate a record prvalue should have 472 // exactly one child. 473 SmallVector<Stmt *, 1> Children(E->child_begin(), E->child_end()); 474 LLVM_DEBUG({ 475 if (Children.size() != 1) 476 E->dump(); 477 }); 478 assert(Children.size() == 1); 479 for (Stmt *S : Children) 480 PropagateResultObject(cast<Expr>(S), Loc); 481 } 482 483 private: 484 llvm::DenseMap<const Expr *, RecordStorageLocation *> &ResultObjectMap; 485 RecordStorageLocation *LocForRecordReturnVal; 486 DataflowAnalysisContext &DACtx; 487 }; 488 489 } // namespace 490 491 void Environment::initialize() { 492 if (InitialTargetStmt == nullptr) 493 return; 494 495 if (InitialTargetFunc == nullptr) { 496 initFieldsGlobalsAndFuncs(getReferencedDecls(*InitialTargetStmt)); 497 ResultObjectMap = 498 std::make_shared<PrValueToResultObject>(buildResultObjectMap( 499 DACtx, InitialTargetStmt, getThisPointeeStorageLocation(), 500 /*LocForRecordReturnValue=*/nullptr)); 501 return; 502 } 503 504 initFieldsGlobalsAndFuncs(getReferencedDecls(*InitialTargetFunc)); 505 506 for (const auto *ParamDecl : InitialTargetFunc->parameters()) { 507 assert(ParamDecl != nullptr); 508 setStorageLocation(*ParamDecl, createObject(*ParamDecl, nullptr)); 509 } 510 511 if (InitialTargetFunc->getReturnType()->isRecordType()) 512 LocForRecordReturnVal = &cast<RecordStorageLocation>( 513 createStorageLocation(InitialTargetFunc->getReturnType())); 514 515 if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(InitialTargetFunc)) { 516 auto *Parent = MethodDecl->getParent(); 517 assert(Parent != nullptr); 518 519 if (Parent->isLambda()) { 520 for (const auto &Capture : Parent->captures()) { 521 if (Capture.capturesVariable()) { 522 const auto *VarDecl = Capture.getCapturedVar(); 523 assert(VarDecl != nullptr); 524 setStorageLocation(*VarDecl, createObject(*VarDecl, nullptr)); 525 } else if (Capture.capturesThis()) { 526 if (auto *Ancestor = InitialTargetFunc->getNonClosureAncestor()) { 527 const auto *SurroundingMethodDecl = cast<CXXMethodDecl>(Ancestor); 528 QualType ThisPointeeType = 529 SurroundingMethodDecl->getFunctionObjectParameterType(); 530 setThisPointeeStorageLocation( 531 cast<RecordStorageLocation>(createObject(ThisPointeeType))); 532 } else if (auto *FieldBeingInitialized = 533 dyn_cast<FieldDecl>(Parent->getLambdaContextDecl())) { 534 // This is in a field initializer, rather than a method. 535 setThisPointeeStorageLocation( 536 cast<RecordStorageLocation>(createObject(QualType( 537 FieldBeingInitialized->getParent()->getTypeForDecl(), 0)))); 538 } else { 539 assert(false && "Unexpected this-capturing lambda context."); 540 } 541 } 542 } 543 } else if (MethodDecl->isImplicitObjectMemberFunction()) { 544 QualType ThisPointeeType = MethodDecl->getFunctionObjectParameterType(); 545 auto &ThisLoc = 546 cast<RecordStorageLocation>(createStorageLocation(ThisPointeeType)); 547 setThisPointeeStorageLocation(ThisLoc); 548 // Initialize fields of `*this` with values, but only if we're not 549 // analyzing a constructor; after all, it's the constructor's job to do 550 // this (and we want to be able to test that). 551 if (!isa<CXXConstructorDecl>(MethodDecl)) 552 initializeFieldsWithValues(ThisLoc); 553 } 554 } 555 556 // We do this below the handling of `CXXMethodDecl` above so that we can 557 // be sure that the storage location for `this` has been set. 558 ResultObjectMap = 559 std::make_shared<PrValueToResultObject>(buildResultObjectMap( 560 DACtx, InitialTargetFunc, getThisPointeeStorageLocation(), 561 LocForRecordReturnVal)); 562 } 563 564 // FIXME: Add support for resetting globals after function calls to enable the 565 // implementation of sound analyses. 566 567 void Environment::initFieldsGlobalsAndFuncs(const ReferencedDecls &Referenced) { 568 // These have to be added before the lines that follow to ensure that 569 // `create*` work correctly for structs. 570 DACtx->addModeledFields(Referenced.Fields); 571 572 for (const VarDecl *D : Referenced.Globals) { 573 if (getStorageLocation(*D) != nullptr) 574 continue; 575 576 // We don't run transfer functions on the initializers of global variables, 577 // so they won't be associated with a value or storage location. We 578 // therefore intentionally don't pass an initializer to `createObject()`; in 579 // particular, this ensures that `createObject()` will initialize the fields 580 // of record-type variables with values. 581 setStorageLocation(*D, createObject(*D, nullptr)); 582 } 583 584 for (const FunctionDecl *FD : Referenced.Functions) { 585 if (getStorageLocation(*FD) != nullptr) 586 continue; 587 auto &Loc = createStorageLocation(*FD); 588 setStorageLocation(*FD, Loc); 589 } 590 } 591 592 Environment Environment::fork() const { 593 Environment Copy(*this); 594 Copy.FlowConditionToken = DACtx->forkFlowCondition(FlowConditionToken); 595 return Copy; 596 } 597 598 bool Environment::canDescend(unsigned MaxDepth, 599 const FunctionDecl *Callee) const { 600 return CallStack.size() < MaxDepth && !llvm::is_contained(CallStack, Callee); 601 } 602 603 Environment Environment::pushCall(const CallExpr *Call) const { 604 Environment Env(*this); 605 606 if (const auto *MethodCall = dyn_cast<CXXMemberCallExpr>(Call)) { 607 if (const Expr *Arg = MethodCall->getImplicitObjectArgument()) { 608 if (!isa<CXXThisExpr>(Arg)) 609 Env.ThisPointeeLoc = 610 cast<RecordStorageLocation>(getStorageLocation(*Arg)); 611 // Otherwise (when the argument is `this`), retain the current 612 // environment's `ThisPointeeLoc`. 613 } 614 } 615 616 if (Call->getType()->isRecordType() && Call->isPRValue()) 617 Env.LocForRecordReturnVal = &Env.getResultObjectLocation(*Call); 618 619 Env.pushCallInternal(Call->getDirectCallee(), 620 llvm::ArrayRef(Call->getArgs(), Call->getNumArgs())); 621 622 return Env; 623 } 624 625 Environment Environment::pushCall(const CXXConstructExpr *Call) const { 626 Environment Env(*this); 627 628 Env.ThisPointeeLoc = &Env.getResultObjectLocation(*Call); 629 Env.LocForRecordReturnVal = &Env.getResultObjectLocation(*Call); 630 631 Env.pushCallInternal(Call->getConstructor(), 632 llvm::ArrayRef(Call->getArgs(), Call->getNumArgs())); 633 634 return Env; 635 } 636 637 void Environment::pushCallInternal(const FunctionDecl *FuncDecl, 638 ArrayRef<const Expr *> Args) { 639 // Canonicalize to the definition of the function. This ensures that we're 640 // putting arguments into the same `ParamVarDecl`s` that the callee will later 641 // be retrieving them from. 642 assert(FuncDecl->getDefinition() != nullptr); 643 FuncDecl = FuncDecl->getDefinition(); 644 645 CallStack.push_back(FuncDecl); 646 647 initFieldsGlobalsAndFuncs(getReferencedDecls(*FuncDecl)); 648 649 const auto *ParamIt = FuncDecl->param_begin(); 650 651 // FIXME: Parameters don't always map to arguments 1:1; examples include 652 // overloaded operators implemented as member functions, and parameter packs. 653 for (unsigned ArgIndex = 0; ArgIndex < Args.size(); ++ParamIt, ++ArgIndex) { 654 assert(ParamIt != FuncDecl->param_end()); 655 const VarDecl *Param = *ParamIt; 656 setStorageLocation(*Param, createObject(*Param, Args[ArgIndex])); 657 } 658 659 ResultObjectMap = std::make_shared<PrValueToResultObject>( 660 buildResultObjectMap(DACtx, FuncDecl, getThisPointeeStorageLocation(), 661 LocForRecordReturnVal)); 662 } 663 664 void Environment::popCall(const CallExpr *Call, const Environment &CalleeEnv) { 665 // We ignore some entries of `CalleeEnv`: 666 // - `DACtx` because is already the same in both 667 // - We don't want the callee's `DeclCtx`, `ReturnVal`, `ReturnLoc` or 668 // `ThisPointeeLoc` because they don't apply to us. 669 // - `DeclToLoc`, `ExprToLoc`, and `ExprToVal` capture information from the 670 // callee's local scope, so when popping that scope, we do not propagate 671 // the maps. 672 this->LocToVal = std::move(CalleeEnv.LocToVal); 673 this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken); 674 675 if (Call->isGLValue()) { 676 if (CalleeEnv.ReturnLoc != nullptr) 677 setStorageLocation(*Call, *CalleeEnv.ReturnLoc); 678 } else if (!Call->getType()->isVoidType()) { 679 if (CalleeEnv.ReturnVal != nullptr) 680 setValue(*Call, *CalleeEnv.ReturnVal); 681 } 682 } 683 684 void Environment::popCall(const CXXConstructExpr *Call, 685 const Environment &CalleeEnv) { 686 // See also comment in `popCall(const CallExpr *, const Environment &)` above. 687 this->LocToVal = std::move(CalleeEnv.LocToVal); 688 this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken); 689 } 690 691 bool Environment::equivalentTo(const Environment &Other, 692 Environment::ValueModel &Model) const { 693 assert(DACtx == Other.DACtx); 694 695 if (ReturnVal != Other.ReturnVal) 696 return false; 697 698 if (ReturnLoc != Other.ReturnLoc) 699 return false; 700 701 if (LocForRecordReturnVal != Other.LocForRecordReturnVal) 702 return false; 703 704 if (ThisPointeeLoc != Other.ThisPointeeLoc) 705 return false; 706 707 if (DeclToLoc != Other.DeclToLoc) 708 return false; 709 710 if (ExprToLoc != Other.ExprToLoc) 711 return false; 712 713 if (!compareKeyToValueMaps(ExprToVal, Other.ExprToVal, *this, Other, Model)) 714 return false; 715 716 if (!compareKeyToValueMaps(LocToVal, Other.LocToVal, *this, Other, Model)) 717 return false; 718 719 return true; 720 } 721 722 LatticeEffect Environment::widen(const Environment &PrevEnv, 723 Environment::ValueModel &Model) { 724 assert(DACtx == PrevEnv.DACtx); 725 assert(ReturnVal == PrevEnv.ReturnVal); 726 assert(ReturnLoc == PrevEnv.ReturnLoc); 727 assert(LocForRecordReturnVal == PrevEnv.LocForRecordReturnVal); 728 assert(ThisPointeeLoc == PrevEnv.ThisPointeeLoc); 729 assert(CallStack == PrevEnv.CallStack); 730 assert(ResultObjectMap == PrevEnv.ResultObjectMap); 731 assert(InitialTargetFunc == PrevEnv.InitialTargetFunc); 732 assert(InitialTargetStmt == PrevEnv.InitialTargetStmt); 733 734 auto Effect = LatticeEffect::Unchanged; 735 736 // By the API, `PrevEnv` is a previous version of the environment for the same 737 // block, so we have some guarantees about its shape. In particular, it will 738 // be the result of a join or widen operation on previous values for this 739 // block. For `DeclToLoc`, `ExprToVal`, and `ExprToLoc`, join guarantees that 740 // these maps are subsets of the maps in `PrevEnv`. So, as long as we maintain 741 // this property here, we don't need change their current values to widen. 742 assert(DeclToLoc.size() <= PrevEnv.DeclToLoc.size()); 743 assert(ExprToVal.size() <= PrevEnv.ExprToVal.size()); 744 assert(ExprToLoc.size() <= PrevEnv.ExprToLoc.size()); 745 746 ExprToVal = widenKeyToValueMap(ExprToVal, PrevEnv.ExprToVal, *this, PrevEnv, 747 Model, Effect); 748 749 LocToVal = widenKeyToValueMap(LocToVal, PrevEnv.LocToVal, *this, PrevEnv, 750 Model, Effect); 751 if (DeclToLoc.size() != PrevEnv.DeclToLoc.size() || 752 ExprToLoc.size() != PrevEnv.ExprToLoc.size() || 753 ExprToVal.size() != PrevEnv.ExprToVal.size() || 754 LocToVal.size() != PrevEnv.LocToVal.size()) 755 Effect = LatticeEffect::Changed; 756 757 return Effect; 758 } 759 760 Environment Environment::join(const Environment &EnvA, const Environment &EnvB, 761 Environment::ValueModel &Model, 762 ExprJoinBehavior ExprBehavior) { 763 assert(EnvA.DACtx == EnvB.DACtx); 764 assert(EnvA.LocForRecordReturnVal == EnvB.LocForRecordReturnVal); 765 assert(EnvA.ThisPointeeLoc == EnvB.ThisPointeeLoc); 766 assert(EnvA.CallStack == EnvB.CallStack); 767 assert(EnvA.ResultObjectMap == EnvB.ResultObjectMap); 768 assert(EnvA.InitialTargetFunc == EnvB.InitialTargetFunc); 769 assert(EnvA.InitialTargetStmt == EnvB.InitialTargetStmt); 770 771 Environment JoinedEnv(*EnvA.DACtx); 772 773 JoinedEnv.CallStack = EnvA.CallStack; 774 JoinedEnv.ResultObjectMap = EnvA.ResultObjectMap; 775 JoinedEnv.LocForRecordReturnVal = EnvA.LocForRecordReturnVal; 776 JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc; 777 JoinedEnv.InitialTargetFunc = EnvA.InitialTargetFunc; 778 JoinedEnv.InitialTargetStmt = EnvA.InitialTargetStmt; 779 780 const FunctionDecl *Func = EnvA.getCurrentFunc(); 781 if (!Func) { 782 JoinedEnv.ReturnVal = nullptr; 783 } else { 784 JoinedEnv.ReturnVal = 785 joinValues(Func->getReturnType(), EnvA.ReturnVal, EnvA, EnvB.ReturnVal, 786 EnvB, JoinedEnv, Model); 787 } 788 789 if (EnvA.ReturnLoc == EnvB.ReturnLoc) 790 JoinedEnv.ReturnLoc = EnvA.ReturnLoc; 791 else 792 JoinedEnv.ReturnLoc = nullptr; 793 794 JoinedEnv.DeclToLoc = intersectDeclToLoc(EnvA.DeclToLoc, EnvB.DeclToLoc); 795 796 // FIXME: update join to detect backedges and simplify the flow condition 797 // accordingly. 798 JoinedEnv.FlowConditionToken = EnvA.DACtx->joinFlowConditions( 799 EnvA.FlowConditionToken, EnvB.FlowConditionToken); 800 801 JoinedEnv.LocToVal = 802 joinLocToVal(EnvA.LocToVal, EnvB.LocToVal, EnvA, EnvB, JoinedEnv, Model); 803 804 if (ExprBehavior == KeepExprState) { 805 JoinedEnv.ExprToVal = joinExprMaps(EnvA.ExprToVal, EnvB.ExprToVal); 806 JoinedEnv.ExprToLoc = joinExprMaps(EnvA.ExprToLoc, EnvB.ExprToLoc); 807 } 808 809 return JoinedEnv; 810 } 811 812 Value *Environment::joinValues(QualType Ty, Value *Val1, 813 const Environment &Env1, Value *Val2, 814 const Environment &Env2, Environment &JoinedEnv, 815 Environment::ValueModel &Model) { 816 if (Val1 == nullptr || Val2 == nullptr) 817 // We can't say anything about the joined value -- even if one of the values 818 // is non-null, we don't want to simply propagate it, because it would be 819 // too specific: Because the other value is null, that means we have no 820 // information at all about the value (i.e. the value is unconstrained). 821 return nullptr; 822 823 if (areEquivalentValues(*Val1, *Val2)) 824 // Arbitrarily return one of the two values. 825 return Val1; 826 827 return joinDistinctValues(Ty, *Val1, Env1, *Val2, Env2, JoinedEnv, Model); 828 } 829 830 StorageLocation &Environment::createStorageLocation(QualType Type) { 831 return DACtx->createStorageLocation(Type); 832 } 833 834 StorageLocation &Environment::createStorageLocation(const ValueDecl &D) { 835 // Evaluated declarations are always assigned the same storage locations to 836 // ensure that the environment stabilizes across loop iterations. Storage 837 // locations for evaluated declarations are stored in the analysis context. 838 return DACtx->getStableStorageLocation(D); 839 } 840 841 StorageLocation &Environment::createStorageLocation(const Expr &E) { 842 // Evaluated expressions are always assigned the same storage locations to 843 // ensure that the environment stabilizes across loop iterations. Storage 844 // locations for evaluated expressions are stored in the analysis context. 845 return DACtx->getStableStorageLocation(E); 846 } 847 848 void Environment::setStorageLocation(const ValueDecl &D, StorageLocation &Loc) { 849 assert(!DeclToLoc.contains(&D)); 850 // The only kinds of declarations that may have a "variable" storage location 851 // are declarations of reference type and `BindingDecl`. For all other 852 // declaration, the storage location should be the stable storage location 853 // returned by `createStorageLocation()`. 854 assert(D.getType()->isReferenceType() || isa<BindingDecl>(D) || 855 &Loc == &createStorageLocation(D)); 856 DeclToLoc[&D] = &Loc; 857 } 858 859 StorageLocation *Environment::getStorageLocation(const ValueDecl &D) const { 860 auto It = DeclToLoc.find(&D); 861 if (It == DeclToLoc.end()) 862 return nullptr; 863 864 StorageLocation *Loc = It->second; 865 866 return Loc; 867 } 868 869 void Environment::removeDecl(const ValueDecl &D) { DeclToLoc.erase(&D); } 870 871 void Environment::setStorageLocation(const Expr &E, StorageLocation &Loc) { 872 // `DeclRefExpr`s to builtin function types aren't glvalues, for some reason, 873 // but we still want to be able to associate a `StorageLocation` with them, 874 // so allow these as an exception. 875 assert(E.isGLValue() || 876 E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn)); 877 const Expr &CanonE = ignoreCFGOmittedNodes(E); 878 assert(!ExprToLoc.contains(&CanonE)); 879 ExprToLoc[&CanonE] = &Loc; 880 } 881 882 StorageLocation *Environment::getStorageLocation(const Expr &E) const { 883 // See comment in `setStorageLocation()`. 884 assert(E.isGLValue() || 885 E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn)); 886 auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E)); 887 return It == ExprToLoc.end() ? nullptr : &*It->second; 888 } 889 890 RecordStorageLocation & 891 Environment::getResultObjectLocation(const Expr &RecordPRValue) const { 892 assert(RecordPRValue.getType()->isRecordType()); 893 assert(RecordPRValue.isPRValue()); 894 895 assert(ResultObjectMap != nullptr); 896 RecordStorageLocation *Loc = ResultObjectMap->lookup(&RecordPRValue); 897 assert(Loc != nullptr); 898 // In release builds, use the "stable" storage location if the map lookup 899 // failed. 900 if (Loc == nullptr) 901 return cast<RecordStorageLocation>( 902 DACtx->getStableStorageLocation(RecordPRValue)); 903 return *Loc; 904 } 905 906 PointerValue &Environment::getOrCreateNullPointerValue(QualType PointeeType) { 907 return DACtx->getOrCreateNullPointerValue(PointeeType); 908 } 909 910 void Environment::initializeFieldsWithValues(RecordStorageLocation &Loc, 911 QualType Type) { 912 llvm::DenseSet<QualType> Visited; 913 int CreatedValuesCount = 0; 914 initializeFieldsWithValues(Loc, Type, Visited, 0, CreatedValuesCount); 915 if (CreatedValuesCount > MaxCompositeValueSize) { 916 llvm::errs() << "Attempting to initialize a huge value of type: " << Type 917 << '\n'; 918 } 919 } 920 921 void Environment::setValue(const StorageLocation &Loc, Value &Val) { 922 // Records should not be associated with values. 923 assert(!isa<RecordStorageLocation>(Loc)); 924 LocToVal[&Loc] = &Val; 925 } 926 927 void Environment::setValue(const Expr &E, Value &Val) { 928 const Expr &CanonE = ignoreCFGOmittedNodes(E); 929 930 assert(CanonE.isPRValue()); 931 // Records should not be associated with values. 932 assert(!CanonE.getType()->isRecordType()); 933 ExprToVal[&CanonE] = &Val; 934 } 935 936 Value *Environment::getValue(const StorageLocation &Loc) const { 937 // Records should not be associated with values. 938 assert(!isa<RecordStorageLocation>(Loc)); 939 return LocToVal.lookup(&Loc); 940 } 941 942 Value *Environment::getValue(const ValueDecl &D) const { 943 auto *Loc = getStorageLocation(D); 944 if (Loc == nullptr) 945 return nullptr; 946 return getValue(*Loc); 947 } 948 949 Value *Environment::getValue(const Expr &E) const { 950 // Records should not be associated with values. 951 assert(!E.getType()->isRecordType()); 952 953 if (E.isPRValue()) { 954 auto It = ExprToVal.find(&ignoreCFGOmittedNodes(E)); 955 return It == ExprToVal.end() ? nullptr : It->second; 956 } 957 958 auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E)); 959 if (It == ExprToLoc.end()) 960 return nullptr; 961 return getValue(*It->second); 962 } 963 964 Value *Environment::createValue(QualType Type) { 965 llvm::DenseSet<QualType> Visited; 966 int CreatedValuesCount = 0; 967 Value *Val = createValueUnlessSelfReferential(Type, Visited, /*Depth=*/0, 968 CreatedValuesCount); 969 if (CreatedValuesCount > MaxCompositeValueSize) { 970 llvm::errs() << "Attempting to initialize a huge value of type: " << Type 971 << '\n'; 972 } 973 return Val; 974 } 975 976 Value *Environment::createValueUnlessSelfReferential( 977 QualType Type, llvm::DenseSet<QualType> &Visited, int Depth, 978 int &CreatedValuesCount) { 979 assert(!Type.isNull()); 980 assert(!Type->isReferenceType()); 981 assert(!Type->isRecordType()); 982 983 // Allow unlimited fields at depth 1; only cap at deeper nesting levels. 984 if ((Depth > 1 && CreatedValuesCount > MaxCompositeValueSize) || 985 Depth > MaxCompositeValueDepth) 986 return nullptr; 987 988 if (Type->isBooleanType()) { 989 CreatedValuesCount++; 990 return &makeAtomicBoolValue(); 991 } 992 993 if (Type->isIntegerType()) { 994 // FIXME: consider instead `return nullptr`, given that we do nothing useful 995 // with integers, and so distinguishing them serves no purpose, but could 996 // prevent convergence. 997 CreatedValuesCount++; 998 return &arena().create<IntegerValue>(); 999 } 1000 1001 if (Type->isPointerType()) { 1002 CreatedValuesCount++; 1003 QualType PointeeType = Type->getPointeeType(); 1004 StorageLocation &PointeeLoc = 1005 createLocAndMaybeValue(PointeeType, Visited, Depth, CreatedValuesCount); 1006 1007 return &arena().create<PointerValue>(PointeeLoc); 1008 } 1009 1010 return nullptr; 1011 } 1012 1013 StorageLocation & 1014 Environment::createLocAndMaybeValue(QualType Ty, 1015 llvm::DenseSet<QualType> &Visited, 1016 int Depth, int &CreatedValuesCount) { 1017 if (!Visited.insert(Ty.getCanonicalType()).second) 1018 return createStorageLocation(Ty.getNonReferenceType()); 1019 auto EraseVisited = llvm::make_scope_exit( 1020 [&Visited, Ty] { Visited.erase(Ty.getCanonicalType()); }); 1021 1022 Ty = Ty.getNonReferenceType(); 1023 1024 if (Ty->isRecordType()) { 1025 auto &Loc = cast<RecordStorageLocation>(createStorageLocation(Ty)); 1026 initializeFieldsWithValues(Loc, Ty, Visited, Depth, CreatedValuesCount); 1027 return Loc; 1028 } 1029 1030 StorageLocation &Loc = createStorageLocation(Ty); 1031 1032 if (Value *Val = createValueUnlessSelfReferential(Ty, Visited, Depth, 1033 CreatedValuesCount)) 1034 setValue(Loc, *Val); 1035 1036 return Loc; 1037 } 1038 1039 void Environment::initializeFieldsWithValues(RecordStorageLocation &Loc, 1040 QualType Type, 1041 llvm::DenseSet<QualType> &Visited, 1042 int Depth, 1043 int &CreatedValuesCount) { 1044 auto initField = [&](QualType FieldType, StorageLocation &FieldLoc) { 1045 if (FieldType->isRecordType()) { 1046 auto &FieldRecordLoc = cast<RecordStorageLocation>(FieldLoc); 1047 initializeFieldsWithValues(FieldRecordLoc, FieldRecordLoc.getType(), 1048 Visited, Depth + 1, CreatedValuesCount); 1049 } else { 1050 if (getValue(FieldLoc) != nullptr) 1051 return; 1052 if (!Visited.insert(FieldType.getCanonicalType()).second) 1053 return; 1054 if (Value *Val = createValueUnlessSelfReferential( 1055 FieldType, Visited, Depth + 1, CreatedValuesCount)) 1056 setValue(FieldLoc, *Val); 1057 Visited.erase(FieldType.getCanonicalType()); 1058 } 1059 }; 1060 1061 for (const FieldDecl *Field : DACtx->getModeledFields(Type)) { 1062 assert(Field != nullptr); 1063 QualType FieldType = Field->getType(); 1064 1065 if (FieldType->isReferenceType()) { 1066 Loc.setChild(*Field, 1067 &createLocAndMaybeValue(FieldType, Visited, Depth + 1, 1068 CreatedValuesCount)); 1069 } else { 1070 StorageLocation *FieldLoc = Loc.getChild(*Field); 1071 assert(FieldLoc != nullptr); 1072 initField(FieldType, *FieldLoc); 1073 } 1074 } 1075 for (const auto &[FieldName, FieldType] : DACtx->getSyntheticFields(Type)) { 1076 // Synthetic fields cannot have reference type, so we don't need to deal 1077 // with this case. 1078 assert(!FieldType->isReferenceType()); 1079 initField(FieldType, Loc.getSyntheticField(FieldName)); 1080 } 1081 } 1082 1083 StorageLocation &Environment::createObjectInternal(const ValueDecl *D, 1084 QualType Ty, 1085 const Expr *InitExpr) { 1086 if (Ty->isReferenceType()) { 1087 // Although variables of reference type always need to be initialized, it 1088 // can happen that we can't see the initializer, so `InitExpr` may still 1089 // be null. 1090 if (InitExpr) { 1091 if (auto *InitExprLoc = getStorageLocation(*InitExpr)) 1092 return *InitExprLoc; 1093 } 1094 1095 // Even though we have an initializer, we might not get an 1096 // InitExprLoc, for example if the InitExpr is a CallExpr for which we 1097 // don't have a function body. In this case, we just invent a storage 1098 // location and value -- it's the best we can do. 1099 return createObjectInternal(D, Ty.getNonReferenceType(), nullptr); 1100 } 1101 1102 StorageLocation &Loc = 1103 D ? createStorageLocation(*D) : createStorageLocation(Ty); 1104 1105 if (Ty->isRecordType()) { 1106 auto &RecordLoc = cast<RecordStorageLocation>(Loc); 1107 if (!InitExpr) 1108 initializeFieldsWithValues(RecordLoc); 1109 } else { 1110 Value *Val = nullptr; 1111 if (InitExpr) 1112 // In the (few) cases where an expression is intentionally 1113 // "uninterpreted", `InitExpr` is not associated with a value. There are 1114 // two ways to handle this situation: propagate the status, so that 1115 // uninterpreted initializers result in uninterpreted variables, or 1116 // provide a default value. We choose the latter so that later refinements 1117 // of the variable can be used for reasoning about the surrounding code. 1118 // For this reason, we let this case be handled by the `createValue()` 1119 // call below. 1120 // 1121 // FIXME. If and when we interpret all language cases, change this to 1122 // assert that `InitExpr` is interpreted, rather than supplying a 1123 // default value (assuming we don't update the environment API to return 1124 // references). 1125 Val = getValue(*InitExpr); 1126 if (!Val) 1127 Val = createValue(Ty); 1128 if (Val) 1129 setValue(Loc, *Val); 1130 } 1131 1132 return Loc; 1133 } 1134 1135 void Environment::assume(const Formula &F) { 1136 DACtx->addFlowConditionConstraint(FlowConditionToken, F); 1137 } 1138 1139 bool Environment::proves(const Formula &F) const { 1140 return DACtx->flowConditionImplies(FlowConditionToken, F); 1141 } 1142 1143 bool Environment::allows(const Formula &F) const { 1144 return DACtx->flowConditionAllows(FlowConditionToken, F); 1145 } 1146 1147 void Environment::dump(raw_ostream &OS) const { 1148 llvm::DenseMap<const StorageLocation *, std::string> LocToName; 1149 if (LocForRecordReturnVal != nullptr) 1150 LocToName[LocForRecordReturnVal] = "(returned record)"; 1151 if (ThisPointeeLoc != nullptr) 1152 LocToName[ThisPointeeLoc] = "this"; 1153 1154 OS << "DeclToLoc:\n"; 1155 for (auto [D, L] : DeclToLoc) { 1156 auto Iter = LocToName.insert({L, D->getNameAsString()}).first; 1157 OS << " [" << Iter->second << ", " << L << "]\n"; 1158 } 1159 OS << "ExprToLoc:\n"; 1160 for (auto [E, L] : ExprToLoc) 1161 OS << " [" << E << ", " << L << "]\n"; 1162 1163 OS << "ExprToVal:\n"; 1164 for (auto [E, V] : ExprToVal) 1165 OS << " [" << E << ", " << V << ": " << *V << "]\n"; 1166 1167 OS << "LocToVal:\n"; 1168 for (auto [L, V] : LocToVal) { 1169 OS << " [" << L; 1170 if (auto Iter = LocToName.find(L); Iter != LocToName.end()) 1171 OS << " (" << Iter->second << ")"; 1172 OS << ", " << V << ": " << *V << "]\n"; 1173 } 1174 1175 if (const FunctionDecl *Func = getCurrentFunc()) { 1176 if (Func->getReturnType()->isReferenceType()) { 1177 OS << "ReturnLoc: " << ReturnLoc; 1178 if (auto Iter = LocToName.find(ReturnLoc); Iter != LocToName.end()) 1179 OS << " (" << Iter->second << ")"; 1180 OS << "\n"; 1181 } else if (Func->getReturnType()->isRecordType() || 1182 isa<CXXConstructorDecl>(Func)) { 1183 OS << "LocForRecordReturnVal: " << LocForRecordReturnVal << "\n"; 1184 } else if (!Func->getReturnType()->isVoidType()) { 1185 if (ReturnVal == nullptr) 1186 OS << "ReturnVal: nullptr\n"; 1187 else 1188 OS << "ReturnVal: " << *ReturnVal << "\n"; 1189 } 1190 1191 if (isa<CXXMethodDecl>(Func)) { 1192 OS << "ThisPointeeLoc: " << ThisPointeeLoc << "\n"; 1193 } 1194 } 1195 1196 OS << "\n"; 1197 DACtx->dumpFlowCondition(FlowConditionToken, OS); 1198 } 1199 1200 void Environment::dump() const { dump(llvm::dbgs()); } 1201 1202 Environment::PrValueToResultObject Environment::buildResultObjectMap( 1203 DataflowAnalysisContext *DACtx, const FunctionDecl *FuncDecl, 1204 RecordStorageLocation *ThisPointeeLoc, 1205 RecordStorageLocation *LocForRecordReturnVal) { 1206 assert(FuncDecl->doesThisDeclarationHaveABody()); 1207 1208 PrValueToResultObject Map = buildResultObjectMap( 1209 DACtx, FuncDecl->getBody(), ThisPointeeLoc, LocForRecordReturnVal); 1210 1211 ResultObjectVisitor Visitor(Map, LocForRecordReturnVal, *DACtx); 1212 if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(FuncDecl)) 1213 Visitor.traverseConstructorInits(Ctor, ThisPointeeLoc); 1214 1215 return Map; 1216 } 1217 1218 Environment::PrValueToResultObject Environment::buildResultObjectMap( 1219 DataflowAnalysisContext *DACtx, Stmt *S, 1220 RecordStorageLocation *ThisPointeeLoc, 1221 RecordStorageLocation *LocForRecordReturnVal) { 1222 PrValueToResultObject Map; 1223 ResultObjectVisitor Visitor(Map, LocForRecordReturnVal, *DACtx); 1224 Visitor.TraverseStmt(S); 1225 return Map; 1226 } 1227 1228 RecordStorageLocation *getImplicitObjectLocation(const CXXMemberCallExpr &MCE, 1229 const Environment &Env) { 1230 Expr *ImplicitObject = MCE.getImplicitObjectArgument(); 1231 if (ImplicitObject == nullptr) 1232 return nullptr; 1233 if (ImplicitObject->getType()->isPointerType()) { 1234 if (auto *Val = Env.get<PointerValue>(*ImplicitObject)) 1235 return &cast<RecordStorageLocation>(Val->getPointeeLoc()); 1236 return nullptr; 1237 } 1238 return cast_or_null<RecordStorageLocation>( 1239 Env.getStorageLocation(*ImplicitObject)); 1240 } 1241 1242 RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME, 1243 const Environment &Env) { 1244 Expr *Base = ME.getBase(); 1245 if (Base == nullptr) 1246 return nullptr; 1247 if (ME.isArrow()) { 1248 if (auto *Val = Env.get<PointerValue>(*Base)) 1249 return &cast<RecordStorageLocation>(Val->getPointeeLoc()); 1250 return nullptr; 1251 } 1252 return Env.get<RecordStorageLocation>(*Base); 1253 } 1254 1255 } // namespace dataflow 1256 } // namespace clang 1257