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