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