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