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/Type.h" 19 #include "clang/Analysis/FlowSensitive/DataflowLattice.h" 20 #include "clang/Analysis/FlowSensitive/Value.h" 21 #include "llvm/ADT/DenseMap.h" 22 #include "llvm/ADT/DenseSet.h" 23 #include "llvm/ADT/MapVector.h" 24 #include "llvm/ADT/STLExtras.h" 25 #include "llvm/Support/ErrorHandling.h" 26 #include <cassert> 27 #include <utility> 28 29 namespace clang { 30 namespace dataflow { 31 32 // FIXME: convert these to parameters of the analysis or environment. Current 33 // settings have been experimentaly validated, but only for a particular 34 // analysis. 35 static constexpr int MaxCompositeValueDepth = 3; 36 static constexpr int MaxCompositeValueSize = 1000; 37 38 /// Returns a map consisting of key-value entries that are present in both maps. 39 template <typename K, typename V> 40 llvm::DenseMap<K, V> intersectDenseMaps(const llvm::DenseMap<K, V> &Map1, 41 const llvm::DenseMap<K, V> &Map2) { 42 llvm::DenseMap<K, V> Result; 43 for (auto &Entry : Map1) { 44 auto It = Map2.find(Entry.first); 45 if (It != Map2.end() && Entry.second == It->second) 46 Result.insert({Entry.first, Entry.second}); 47 } 48 return Result; 49 } 50 51 // Whether to consider equivalent two values with an unknown relation. 52 // 53 // FIXME: this function is a hack enabling unsoundness to support 54 // convergence. Once we have widening support for the reference/pointer and 55 // struct built-in models, this should be unconditionally `false` (and inlined 56 // as such at its call sites). 57 static bool equateUnknownValues(Value::Kind K) { 58 switch (K) { 59 case Value::Kind::Integer: 60 case Value::Kind::Pointer: 61 case Value::Kind::Record: 62 return true; 63 default: 64 return false; 65 } 66 } 67 68 static bool compareDistinctValues(QualType Type, Value &Val1, 69 const Environment &Env1, Value &Val2, 70 const Environment &Env2, 71 Environment::ValueModel &Model) { 72 // Note: Potentially costly, but, for booleans, we could check whether both 73 // can be proven equivalent in their respective environments. 74 75 // FIXME: move the reference/pointers logic from `areEquivalentValues` to here 76 // and implement separate, join/widen specific handling for 77 // reference/pointers. 78 switch (Model.compare(Type, Val1, Env1, Val2, Env2)) { 79 case ComparisonResult::Same: 80 return true; 81 case ComparisonResult::Different: 82 return false; 83 case ComparisonResult::Unknown: 84 return equateUnknownValues(Val1.getKind()); 85 } 86 llvm_unreachable("All cases covered in switch"); 87 } 88 89 /// Attempts to merge distinct values `Val1` and `Val2` in `Env1` and `Env2`, 90 /// respectively, of the same type `Type`. Merging generally produces a single 91 /// value that (soundly) approximates the two inputs, although the actual 92 /// meaning depends on `Model`. 93 static Value *mergeDistinctValues(QualType Type, Value &Val1, 94 const Environment &Env1, Value &Val2, 95 const Environment &Env2, 96 Environment &MergedEnv, 97 Environment::ValueModel &Model) { 98 // Join distinct boolean values preserving information about the constraints 99 // in the respective path conditions. 100 if (isa<BoolValue>(&Val1) && isa<BoolValue>(&Val2)) { 101 // FIXME: Checking both values should be unnecessary, since they should have 102 // a consistent shape. However, right now we can end up with BoolValue's in 103 // integer-typed variables due to our incorrect handling of 104 // boolean-to-integer casts (we just propagate the BoolValue to the result 105 // of the cast). So, a join can encounter an integer in one branch but a 106 // bool in the other. 107 // For example: 108 // ``` 109 // std::optional<bool> o; 110 // int x; 111 // if (o.has_value()) 112 // x = o.value(); 113 // ``` 114 auto &Expr1 = cast<BoolValue>(Val1).formula(); 115 auto &Expr2 = cast<BoolValue>(Val2).formula(); 116 auto &A = MergedEnv.arena(); 117 auto &MergedVal = A.makeAtomRef(A.makeAtom()); 118 MergedEnv.addToFlowCondition( 119 A.makeOr(A.makeAnd(A.makeAtomRef(Env1.getFlowConditionToken()), 120 A.makeEquals(MergedVal, Expr1)), 121 A.makeAnd(A.makeAtomRef(Env2.getFlowConditionToken()), 122 A.makeEquals(MergedVal, Expr2)))); 123 return &A.makeBoolValue(MergedVal); 124 } 125 126 Value *MergedVal = nullptr; 127 if (auto *RecordVal1 = dyn_cast<RecordValue>(&Val1)) { 128 auto *RecordVal2 = cast<RecordValue>(&Val2); 129 130 if (&RecordVal1->getLoc() == &RecordVal2->getLoc()) 131 // `RecordVal1` and `RecordVal2` may have different properties associated 132 // with them. Create a new `RecordValue` with the same location but 133 // without any properties so that we soundly approximate both values. If a 134 // particular analysis needs to merge properties, it should do so in 135 // `DataflowAnalysis::merge()`. 136 MergedVal = &MergedEnv.create<RecordValue>(RecordVal1->getLoc()); 137 else 138 // If the locations for the two records are different, need to create a 139 // completely new value. 140 MergedVal = MergedEnv.createValue(Type); 141 } else { 142 MergedVal = MergedEnv.createValue(Type); 143 } 144 145 // FIXME: Consider destroying `MergedValue` immediately if `ValueModel::merge` 146 // returns false to avoid storing unneeded values in `DACtx`. 147 if (MergedVal) 148 if (Model.merge(Type, Val1, Env1, Val2, Env2, *MergedVal, MergedEnv)) 149 return MergedVal; 150 151 return nullptr; 152 } 153 154 // When widening does not change `Current`, return value will equal `&Prev`. 155 static Value &widenDistinctValues(QualType Type, Value &Prev, 156 const Environment &PrevEnv, Value &Current, 157 Environment &CurrentEnv, 158 Environment::ValueModel &Model) { 159 // Boolean-model widening. 160 if (isa<BoolValue>(&Prev)) { 161 assert(isa<BoolValue>(Current)); 162 // Widen to Top, because we know they are different values. If previous was 163 // already Top, re-use that to (implicitly) indicate that no change occured. 164 if (isa<TopBoolValue>(Prev)) 165 return Prev; 166 return CurrentEnv.makeTopBoolValue(); 167 } 168 169 // FIXME: Add other built-in model widening. 170 171 // Custom-model widening. 172 if (auto *W = Model.widen(Type, Prev, PrevEnv, Current, CurrentEnv)) 173 return *W; 174 175 return equateUnknownValues(Prev.getKind()) ? Prev : Current; 176 } 177 178 // Returns whether the values in `Map1` and `Map2` compare equal for those 179 // keys that `Map1` and `Map2` have in common. 180 template <typename Key> 181 bool compareKeyToValueMaps(const llvm::MapVector<Key, Value *> &Map1, 182 const llvm::MapVector<Key, Value *> &Map2, 183 const Environment &Env1, const Environment &Env2, 184 Environment::ValueModel &Model) { 185 for (auto &Entry : Map1) { 186 Key K = Entry.first; 187 assert(K != nullptr); 188 189 Value *Val = Entry.second; 190 assert(Val != nullptr); 191 192 auto It = Map2.find(K); 193 if (It == Map2.end()) 194 continue; 195 assert(It->second != nullptr); 196 197 if (!areEquivalentValues(*Val, *It->second) && 198 !compareDistinctValues(K->getType(), *Val, Env1, *It->second, Env2, 199 Model)) 200 return false; 201 } 202 203 return true; 204 } 205 206 // Perform a join on either `LocToVal` or `ExprToVal`. `Key` must be either 207 // `const StorageLocation *` or `const Expr *`. 208 template <typename Key> 209 llvm::MapVector<Key, Value *> 210 joinKeyToValueMap(const llvm::MapVector<Key, Value *> &Map1, 211 const llvm::MapVector<Key, Value *> &Map2, 212 const Environment &Env1, const Environment &Env2, 213 Environment &JoinedEnv, Environment::ValueModel &Model) { 214 llvm::MapVector<Key, Value *> MergedMap; 215 for (auto &Entry : Map1) { 216 Key K = Entry.first; 217 assert(K != nullptr); 218 219 Value *Val = Entry.second; 220 assert(Val != nullptr); 221 222 auto It = Map2.find(K); 223 if (It == Map2.end()) 224 continue; 225 assert(It->second != nullptr); 226 227 if (areEquivalentValues(*Val, *It->second)) { 228 MergedMap.insert({K, Val}); 229 continue; 230 } 231 232 if (Value *MergedVal = mergeDistinctValues( 233 K->getType(), *Val, Env1, *It->second, Env2, JoinedEnv, Model)) { 234 MergedMap.insert({K, MergedVal}); 235 } 236 } 237 238 return MergedMap; 239 } 240 241 // Perform widening on either `LocToVal` or `ExprToVal`. `Key` must be either 242 // `const StorageLocation *` or `const Expr *`. 243 template <typename Key> 244 llvm::MapVector<Key, Value *> 245 widenKeyToValueMap(const llvm::MapVector<Key, Value *> &CurMap, 246 const llvm::MapVector<Key, Value *> &PrevMap, 247 Environment &CurEnv, const Environment &PrevEnv, 248 Environment::ValueModel &Model, LatticeJoinEffect &Effect) { 249 llvm::MapVector<Key, Value *> WidenedMap; 250 for (auto &Entry : CurMap) { 251 Key K = Entry.first; 252 assert(K != nullptr); 253 254 Value *Val = Entry.second; 255 assert(Val != nullptr); 256 257 auto PrevIt = PrevMap.find(K); 258 if (PrevIt == PrevMap.end()) 259 continue; 260 assert(PrevIt->second != nullptr); 261 262 if (areEquivalentValues(*Val, *PrevIt->second)) { 263 WidenedMap.insert({K, Val}); 264 continue; 265 } 266 267 Value &WidenedVal = widenDistinctValues(K->getType(), *PrevIt->second, 268 PrevEnv, *Val, CurEnv, Model); 269 WidenedMap.insert({K, &WidenedVal}); 270 if (&WidenedVal != PrevIt->second) 271 Effect = LatticeJoinEffect::Changed; 272 } 273 274 return WidenedMap; 275 } 276 277 /// Initializes a global storage value. 278 static void insertIfGlobal(const Decl &D, 279 llvm::DenseSet<const VarDecl *> &Vars) { 280 if (auto *V = dyn_cast<VarDecl>(&D)) 281 if (V->hasGlobalStorage()) 282 Vars.insert(V); 283 } 284 285 static void insertIfFunction(const Decl &D, 286 llvm::DenseSet<const FunctionDecl *> &Funcs) { 287 if (auto *FD = dyn_cast<FunctionDecl>(&D)) 288 Funcs.insert(FD); 289 } 290 291 static MemberExpr *getMemberForAccessor(const CXXMemberCallExpr &C) { 292 auto *Body = dyn_cast_or_null<CompoundStmt>(C.getMethodDecl()->getBody()); 293 if (!Body || Body->size() != 1) 294 return nullptr; 295 if (auto *RS = dyn_cast<ReturnStmt>(*Body->body_begin())) 296 return dyn_cast<MemberExpr>(RS->getRetValue()->IgnoreParenImpCasts()); 297 return nullptr; 298 } 299 300 static void 301 getFieldsGlobalsAndFuncs(const Decl &D, FieldSet &Fields, 302 llvm::DenseSet<const VarDecl *> &Vars, 303 llvm::DenseSet<const FunctionDecl *> &Funcs) { 304 insertIfGlobal(D, Vars); 305 insertIfFunction(D, Funcs); 306 if (const auto *Decomp = dyn_cast<DecompositionDecl>(&D)) 307 for (const auto *B : Decomp->bindings()) 308 if (auto *ME = dyn_cast_or_null<MemberExpr>(B->getBinding())) 309 // FIXME: should we be using `E->getFoundDecl()`? 310 if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) 311 Fields.insert(FD); 312 } 313 314 /// Traverses `S` and inserts into `Fields`, `Vars` and `Funcs` any fields, 315 /// global variables and functions that are declared in or referenced from 316 /// sub-statements. 317 static void 318 getFieldsGlobalsAndFuncs(const Stmt &S, FieldSet &Fields, 319 llvm::DenseSet<const VarDecl *> &Vars, 320 llvm::DenseSet<const FunctionDecl *> &Funcs) { 321 for (auto *Child : S.children()) 322 if (Child != nullptr) 323 getFieldsGlobalsAndFuncs(*Child, Fields, Vars, Funcs); 324 if (const auto *DefaultInit = dyn_cast<CXXDefaultInitExpr>(&S)) 325 getFieldsGlobalsAndFuncs(*DefaultInit->getExpr(), Fields, Vars, Funcs); 326 327 if (auto *DS = dyn_cast<DeclStmt>(&S)) { 328 if (DS->isSingleDecl()) 329 getFieldsGlobalsAndFuncs(*DS->getSingleDecl(), Fields, Vars, Funcs); 330 else 331 for (auto *D : DS->getDeclGroup()) 332 getFieldsGlobalsAndFuncs(*D, Fields, Vars, Funcs); 333 } else if (auto *E = dyn_cast<DeclRefExpr>(&S)) { 334 insertIfGlobal(*E->getDecl(), Vars); 335 insertIfFunction(*E->getDecl(), Funcs); 336 } else if (const auto *C = dyn_cast<CXXMemberCallExpr>(&S)) { 337 // If this is a method that returns a member variable but does nothing else, 338 // model the field of the return value. 339 if (MemberExpr *E = getMemberForAccessor(*C)) 340 if (const auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl())) 341 Fields.insert(FD); 342 } else if (auto *E = dyn_cast<MemberExpr>(&S)) { 343 // FIXME: should we be using `E->getFoundDecl()`? 344 const ValueDecl *VD = E->getMemberDecl(); 345 insertIfGlobal(*VD, Vars); 346 insertIfFunction(*VD, Funcs); 347 if (const auto *FD = dyn_cast<FieldDecl>(VD)) 348 Fields.insert(FD); 349 } else if (auto *InitList = dyn_cast<InitListExpr>(&S)) { 350 if (RecordDecl *RD = InitList->getType()->getAsRecordDecl()) 351 for (const auto *FD : getFieldsForInitListExpr(RD)) 352 Fields.insert(FD); 353 } 354 } 355 356 // FIXME: Add support for resetting globals after function calls to enable 357 // the implementation of sound analyses. 358 void Environment::initFieldsGlobalsAndFuncs(const FunctionDecl *FuncDecl) { 359 assert(FuncDecl->getBody() != nullptr); 360 361 FieldSet Fields; 362 llvm::DenseSet<const VarDecl *> Vars; 363 llvm::DenseSet<const FunctionDecl *> Funcs; 364 365 // Look for global variable and field references in the 366 // constructor-initializers. 367 if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FuncDecl)) { 368 for (const auto *Init : CtorDecl->inits()) { 369 if (Init->isMemberInitializer()) { 370 Fields.insert(Init->getMember()); 371 } else if (Init->isIndirectMemberInitializer()) { 372 for (const auto *I : Init->getIndirectMember()->chain()) 373 Fields.insert(cast<FieldDecl>(I)); 374 } 375 const Expr *E = Init->getInit(); 376 assert(E != nullptr); 377 getFieldsGlobalsAndFuncs(*E, Fields, Vars, Funcs); 378 } 379 // Add all fields mentioned in default member initializers. 380 for (const FieldDecl *F : CtorDecl->getParent()->fields()) 381 if (const auto *I = F->getInClassInitializer()) 382 getFieldsGlobalsAndFuncs(*I, Fields, Vars, Funcs); 383 } 384 getFieldsGlobalsAndFuncs(*FuncDecl->getBody(), Fields, Vars, Funcs); 385 386 // These have to be added before the lines that follow to ensure that 387 // `create*` work correctly for structs. 388 DACtx->addModeledFields(Fields); 389 390 for (const VarDecl *D : Vars) { 391 if (getStorageLocation(*D) != nullptr) 392 continue; 393 394 setStorageLocation(*D, createObject(*D)); 395 } 396 397 for (const FunctionDecl *FD : Funcs) { 398 if (getStorageLocation(*FD) != nullptr) 399 continue; 400 auto &Loc = createStorageLocation(FD->getType()); 401 setStorageLocation(*FD, Loc); 402 } 403 } 404 405 Environment::Environment(DataflowAnalysisContext &DACtx) 406 : DACtx(&DACtx), 407 FlowConditionToken(DACtx.arena().makeFlowConditionToken()) {} 408 409 Environment Environment::fork() const { 410 Environment Copy(*this); 411 Copy.FlowConditionToken = DACtx->forkFlowCondition(FlowConditionToken); 412 return Copy; 413 } 414 415 Environment::Environment(DataflowAnalysisContext &DACtx, 416 const DeclContext &DeclCtx) 417 : Environment(DACtx) { 418 CallStack.push_back(&DeclCtx); 419 420 if (const auto *FuncDecl = dyn_cast<FunctionDecl>(&DeclCtx)) { 421 assert(FuncDecl->getBody() != nullptr); 422 423 initFieldsGlobalsAndFuncs(FuncDecl); 424 425 for (const auto *ParamDecl : FuncDecl->parameters()) { 426 assert(ParamDecl != nullptr); 427 setStorageLocation(*ParamDecl, createObject(*ParamDecl, nullptr)); 428 } 429 } 430 431 if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(&DeclCtx)) { 432 auto *Parent = MethodDecl->getParent(); 433 assert(Parent != nullptr); 434 if (Parent->isLambda()) 435 MethodDecl = dyn_cast<CXXMethodDecl>(Parent->getDeclContext()); 436 437 // FIXME: Initialize the ThisPointeeLoc of lambdas too. 438 if (MethodDecl && !MethodDecl->isStatic()) { 439 QualType ThisPointeeType = MethodDecl->getThisObjectType(); 440 ThisPointeeLoc = 441 &cast<RecordValue>(createValue(ThisPointeeType))->getLoc(); 442 } 443 } 444 } 445 446 bool Environment::canDescend(unsigned MaxDepth, 447 const DeclContext *Callee) const { 448 return CallStack.size() <= MaxDepth && !llvm::is_contained(CallStack, Callee); 449 } 450 451 Environment Environment::pushCall(const CallExpr *Call) const { 452 Environment Env(*this); 453 454 if (const auto *MethodCall = dyn_cast<CXXMemberCallExpr>(Call)) { 455 if (const Expr *Arg = MethodCall->getImplicitObjectArgument()) { 456 if (!isa<CXXThisExpr>(Arg)) 457 Env.ThisPointeeLoc = 458 cast<RecordStorageLocation>(getStorageLocation(*Arg)); 459 // Otherwise (when the argument is `this`), retain the current 460 // environment's `ThisPointeeLoc`. 461 } 462 } 463 464 Env.pushCallInternal(Call->getDirectCallee(), 465 llvm::ArrayRef(Call->getArgs(), Call->getNumArgs())); 466 467 return Env; 468 } 469 470 Environment Environment::pushCall(const CXXConstructExpr *Call) const { 471 Environment Env(*this); 472 473 Env.ThisPointeeLoc = &Env.getResultObjectLocation(*Call); 474 475 Env.pushCallInternal(Call->getConstructor(), 476 llvm::ArrayRef(Call->getArgs(), Call->getNumArgs())); 477 478 return Env; 479 } 480 481 void Environment::pushCallInternal(const FunctionDecl *FuncDecl, 482 ArrayRef<const Expr *> Args) { 483 // Canonicalize to the definition of the function. This ensures that we're 484 // putting arguments into the same `ParamVarDecl`s` that the callee will later 485 // be retrieving them from. 486 assert(FuncDecl->getDefinition() != nullptr); 487 FuncDecl = FuncDecl->getDefinition(); 488 489 CallStack.push_back(FuncDecl); 490 491 initFieldsGlobalsAndFuncs(FuncDecl); 492 493 const auto *ParamIt = FuncDecl->param_begin(); 494 495 // FIXME: Parameters don't always map to arguments 1:1; examples include 496 // overloaded operators implemented as member functions, and parameter packs. 497 for (unsigned ArgIndex = 0; ArgIndex < Args.size(); ++ParamIt, ++ArgIndex) { 498 assert(ParamIt != FuncDecl->param_end()); 499 const VarDecl *Param = *ParamIt; 500 setStorageLocation(*Param, createObject(*Param, Args[ArgIndex])); 501 } 502 } 503 504 void Environment::popCall(const CallExpr *Call, const Environment &CalleeEnv) { 505 // We ignore some entries of `CalleeEnv`: 506 // - `DACtx` because is already the same in both 507 // - We don't want the callee's `DeclCtx`, `ReturnVal`, `ReturnLoc` or 508 // `ThisPointeeLoc` because they don't apply to us. 509 // - `DeclToLoc`, `ExprToLoc`, and `ExprToVal` capture information from the 510 // callee's local scope, so when popping that scope, we do not propagate 511 // the maps. 512 this->LocToVal = std::move(CalleeEnv.LocToVal); 513 this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken); 514 515 if (Call->isGLValue()) { 516 if (CalleeEnv.ReturnLoc != nullptr) 517 setStorageLocation(*Call, *CalleeEnv.ReturnLoc); 518 } else if (!Call->getType()->isVoidType()) { 519 if (CalleeEnv.ReturnVal != nullptr) 520 setValue(*Call, *CalleeEnv.ReturnVal); 521 } 522 } 523 524 void Environment::popCall(const CXXConstructExpr *Call, 525 const Environment &CalleeEnv) { 526 // See also comment in `popCall(const CallExpr *, const Environment &)` above. 527 this->LocToVal = std::move(CalleeEnv.LocToVal); 528 this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken); 529 530 if (Value *Val = CalleeEnv.getValue(*CalleeEnv.ThisPointeeLoc)) { 531 setValue(*Call, *Val); 532 } 533 } 534 535 bool Environment::equivalentTo(const Environment &Other, 536 Environment::ValueModel &Model) const { 537 assert(DACtx == Other.DACtx); 538 539 if (ReturnVal != Other.ReturnVal) 540 return false; 541 542 if (ReturnLoc != Other.ReturnLoc) 543 return false; 544 545 if (ThisPointeeLoc != Other.ThisPointeeLoc) 546 return false; 547 548 if (DeclToLoc != Other.DeclToLoc) 549 return false; 550 551 if (ExprToLoc != Other.ExprToLoc) 552 return false; 553 554 if (!compareKeyToValueMaps(ExprToVal, Other.ExprToVal, *this, Other, Model)) 555 return false; 556 557 if (!compareKeyToValueMaps(LocToVal, Other.LocToVal, *this, Other, Model)) 558 return false; 559 560 return true; 561 } 562 563 LatticeJoinEffect Environment::widen(const Environment &PrevEnv, 564 Environment::ValueModel &Model) { 565 assert(DACtx == PrevEnv.DACtx); 566 assert(ReturnVal == PrevEnv.ReturnVal); 567 assert(ReturnLoc == PrevEnv.ReturnLoc); 568 assert(ThisPointeeLoc == PrevEnv.ThisPointeeLoc); 569 assert(CallStack == PrevEnv.CallStack); 570 571 auto Effect = LatticeJoinEffect::Unchanged; 572 573 // By the API, `PrevEnv` is a previous version of the environment for the same 574 // block, so we have some guarantees about its shape. In particular, it will 575 // be the result of a join or widen operation on previous values for this 576 // block. For `DeclToLoc`, `ExprToVal`, and `ExprToLoc`, join guarantees that 577 // these maps are subsets of the maps in `PrevEnv`. So, as long as we maintain 578 // this property here, we don't need change their current values to widen. 579 assert(DeclToLoc.size() <= PrevEnv.DeclToLoc.size()); 580 assert(ExprToVal.size() <= PrevEnv.ExprToVal.size()); 581 assert(ExprToLoc.size() <= PrevEnv.ExprToLoc.size()); 582 583 ExprToVal = widenKeyToValueMap(ExprToVal, PrevEnv.ExprToVal, *this, PrevEnv, 584 Model, Effect); 585 586 LocToVal = widenKeyToValueMap(LocToVal, PrevEnv.LocToVal, *this, PrevEnv, 587 Model, Effect); 588 if (DeclToLoc.size() != PrevEnv.DeclToLoc.size() || 589 ExprToLoc.size() != PrevEnv.ExprToLoc.size() || 590 ExprToVal.size() != PrevEnv.ExprToVal.size() || 591 LocToVal.size() != PrevEnv.LocToVal.size()) 592 Effect = LatticeJoinEffect::Changed; 593 594 return Effect; 595 } 596 597 Environment Environment::join(const Environment &EnvA, const Environment &EnvB, 598 Environment::ValueModel &Model) { 599 assert(EnvA.DACtx == EnvB.DACtx); 600 assert(EnvA.ThisPointeeLoc == EnvB.ThisPointeeLoc); 601 assert(EnvA.CallStack == EnvB.CallStack); 602 603 Environment JoinedEnv(*EnvA.DACtx); 604 605 JoinedEnv.CallStack = EnvA.CallStack; 606 JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc; 607 608 if (EnvA.ReturnVal == nullptr || EnvB.ReturnVal == nullptr) { 609 // `ReturnVal` might not always get set -- for example if we have a return 610 // statement of the form `return some_other_func()` and we decide not to 611 // analyze `some_other_func()`. 612 // In this case, we can't say anything about the joined return value -- we 613 // don't simply want to propagate the return value that we do have, because 614 // it might not be the correct one. 615 // This occurs for example in the test `ContextSensitiveMutualRecursion`. 616 JoinedEnv.ReturnVal = nullptr; 617 } else if (areEquivalentValues(*EnvA.ReturnVal, *EnvB.ReturnVal)) { 618 JoinedEnv.ReturnVal = EnvA.ReturnVal; 619 } else { 620 assert(!EnvA.CallStack.empty()); 621 // FIXME: Make `CallStack` a vector of `FunctionDecl` so we don't need this 622 // cast. 623 auto *Func = dyn_cast<FunctionDecl>(EnvA.CallStack.back()); 624 assert(Func != nullptr); 625 if (Value *MergedVal = 626 mergeDistinctValues(Func->getReturnType(), *EnvA.ReturnVal, EnvA, 627 *EnvB.ReturnVal, EnvB, JoinedEnv, Model)) 628 JoinedEnv.ReturnVal = MergedVal; 629 } 630 631 if (EnvA.ReturnLoc == EnvB.ReturnLoc) 632 JoinedEnv.ReturnLoc = EnvA.ReturnLoc; 633 else 634 JoinedEnv.ReturnLoc = nullptr; 635 636 // FIXME: Once we're able to remove declarations from `DeclToLoc` when their 637 // lifetime ends, add an assertion that there aren't any entries in 638 // `DeclToLoc` and `Other.DeclToLoc` that map the same declaration to 639 // different storage locations. 640 JoinedEnv.DeclToLoc = intersectDenseMaps(EnvA.DeclToLoc, EnvB.DeclToLoc); 641 642 JoinedEnv.ExprToLoc = intersectDenseMaps(EnvA.ExprToLoc, EnvB.ExprToLoc); 643 644 // FIXME: update join to detect backedges and simplify the flow condition 645 // accordingly. 646 JoinedEnv.FlowConditionToken = EnvA.DACtx->joinFlowConditions( 647 EnvA.FlowConditionToken, EnvB.FlowConditionToken); 648 649 JoinedEnv.ExprToVal = joinKeyToValueMap(EnvA.ExprToVal, EnvB.ExprToVal, EnvA, 650 EnvB, JoinedEnv, Model); 651 652 JoinedEnv.LocToVal = joinKeyToValueMap(EnvA.LocToVal, EnvB.LocToVal, EnvA, 653 EnvB, JoinedEnv, Model); 654 655 return JoinedEnv; 656 } 657 658 StorageLocation &Environment::createStorageLocation(QualType Type) { 659 return DACtx->createStorageLocation(Type); 660 } 661 662 StorageLocation &Environment::createStorageLocation(const VarDecl &D) { 663 // Evaluated declarations are always assigned the same storage locations to 664 // ensure that the environment stabilizes across loop iterations. Storage 665 // locations for evaluated declarations are stored in the analysis context. 666 return DACtx->getStableStorageLocation(D); 667 } 668 669 StorageLocation &Environment::createStorageLocation(const Expr &E) { 670 // Evaluated expressions are always assigned the same storage locations to 671 // ensure that the environment stabilizes across loop iterations. Storage 672 // locations for evaluated expressions are stored in the analysis context. 673 return DACtx->getStableStorageLocation(E); 674 } 675 676 void Environment::setStorageLocation(const ValueDecl &D, StorageLocation &Loc) { 677 assert(!DeclToLoc.contains(&D)); 678 DeclToLoc[&D] = &Loc; 679 } 680 681 StorageLocation *Environment::getStorageLocation(const ValueDecl &D) const { 682 auto It = DeclToLoc.find(&D); 683 if (It == DeclToLoc.end()) 684 return nullptr; 685 686 StorageLocation *Loc = It->second; 687 688 return Loc; 689 } 690 691 void Environment::setStorageLocation(const Expr &E, StorageLocation &Loc) { 692 // `DeclRefExpr`s to builtin function types aren't glvalues, for some reason, 693 // but we still want to be able to associate a `StorageLocation` with them, 694 // so allow these as an exception. 695 assert(E.isGLValue() || 696 E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn)); 697 setStorageLocationInternal(E, Loc); 698 } 699 700 StorageLocation *Environment::getStorageLocation(const Expr &E) const { 701 // See comment in `setStorageLocation()`. 702 assert(E.isGLValue() || 703 E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn)); 704 return getStorageLocationInternal(E); 705 } 706 707 RecordStorageLocation *Environment::getThisPointeeStorageLocation() const { 708 return ThisPointeeLoc; 709 } 710 711 RecordStorageLocation & 712 Environment::getResultObjectLocation(const Expr &RecordPRValue) { 713 assert(RecordPRValue.getType()->isRecordType()); 714 assert(RecordPRValue.isPRValue()); 715 716 if (StorageLocation *ExistingLoc = getStorageLocationInternal(RecordPRValue)) 717 return *cast<RecordStorageLocation>(ExistingLoc); 718 auto &Loc = cast<RecordStorageLocation>( 719 DACtx->getStableStorageLocation(RecordPRValue)); 720 setStorageLocationInternal(RecordPRValue, Loc); 721 return Loc; 722 } 723 724 PointerValue &Environment::getOrCreateNullPointerValue(QualType PointeeType) { 725 return DACtx->getOrCreateNullPointerValue(PointeeType); 726 } 727 728 void Environment::setValue(const StorageLocation &Loc, Value &Val) { 729 assert(!isa<RecordValue>(&Val) || &cast<RecordValue>(&Val)->getLoc() == &Loc); 730 731 LocToVal[&Loc] = &Val; 732 } 733 734 void Environment::setValue(const Expr &E, Value &Val) { 735 assert(E.isPRValue()); 736 ExprToVal[&E] = &Val; 737 } 738 739 Value *Environment::getValue(const StorageLocation &Loc) const { 740 return LocToVal.lookup(&Loc); 741 } 742 743 Value *Environment::getValue(const ValueDecl &D) const { 744 auto *Loc = getStorageLocation(D); 745 if (Loc == nullptr) 746 return nullptr; 747 return getValue(*Loc); 748 } 749 750 Value *Environment::getValue(const Expr &E) const { 751 if (E.isPRValue()) { 752 auto It = ExprToVal.find(&ignoreCFGOmittedNodes(E)); 753 return It == ExprToVal.end() ? nullptr : It->second; 754 } 755 756 auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E)); 757 if (It == ExprToLoc.end()) 758 return nullptr; 759 return getValue(*It->second); 760 } 761 762 Value *Environment::createValue(QualType Type) { 763 llvm::DenseSet<QualType> Visited; 764 int CreatedValuesCount = 0; 765 Value *Val = createValueUnlessSelfReferential(Type, Visited, /*Depth=*/0, 766 CreatedValuesCount); 767 if (CreatedValuesCount > MaxCompositeValueSize) { 768 llvm::errs() << "Attempting to initialize a huge value of type: " << Type 769 << '\n'; 770 } 771 return Val; 772 } 773 774 void Environment::setStorageLocationInternal(const Expr &E, 775 StorageLocation &Loc) { 776 const Expr &CanonE = ignoreCFGOmittedNodes(E); 777 assert(!ExprToLoc.contains(&CanonE)); 778 ExprToLoc[&CanonE] = &Loc; 779 } 780 781 StorageLocation *Environment::getStorageLocationInternal(const Expr &E) const { 782 auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E)); 783 return It == ExprToLoc.end() ? nullptr : &*It->second; 784 } 785 786 Value *Environment::createValueUnlessSelfReferential( 787 QualType Type, llvm::DenseSet<QualType> &Visited, int Depth, 788 int &CreatedValuesCount) { 789 assert(!Type.isNull()); 790 assert(!Type->isReferenceType()); 791 792 // Allow unlimited fields at depth 1; only cap at deeper nesting levels. 793 if ((Depth > 1 && CreatedValuesCount > MaxCompositeValueSize) || 794 Depth > MaxCompositeValueDepth) 795 return nullptr; 796 797 if (Type->isBooleanType()) { 798 CreatedValuesCount++; 799 return &makeAtomicBoolValue(); 800 } 801 802 if (Type->isIntegerType()) { 803 // FIXME: consider instead `return nullptr`, given that we do nothing useful 804 // with integers, and so distinguishing them serves no purpose, but could 805 // prevent convergence. 806 CreatedValuesCount++; 807 return &arena().create<IntegerValue>(); 808 } 809 810 if (Type->isPointerType()) { 811 CreatedValuesCount++; 812 QualType PointeeType = Type->getPointeeType(); 813 StorageLocation &PointeeLoc = 814 createLocAndMaybeValue(PointeeType, Visited, Depth, CreatedValuesCount); 815 816 return &arena().create<PointerValue>(PointeeLoc); 817 } 818 819 if (Type->isRecordType()) { 820 CreatedValuesCount++; 821 llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs; 822 for (const FieldDecl *Field : DACtx->getModeledFields(Type)) { 823 assert(Field != nullptr); 824 825 QualType FieldType = Field->getType(); 826 827 FieldLocs.insert( 828 {Field, &createLocAndMaybeValue(FieldType, Visited, Depth + 1, 829 CreatedValuesCount)}); 830 } 831 832 RecordStorageLocation &Loc = 833 arena().create<RecordStorageLocation>(Type, std::move(FieldLocs)); 834 RecordValue &RecordVal = create<RecordValue>(Loc); 835 836 // As we already have a storage location for the `RecordValue`, we can and 837 // should associate them in the environment. 838 setValue(Loc, RecordVal); 839 840 return &RecordVal; 841 } 842 843 return nullptr; 844 } 845 846 StorageLocation & 847 Environment::createLocAndMaybeValue(QualType Ty, 848 llvm::DenseSet<QualType> &Visited, 849 int Depth, int &CreatedValuesCount) { 850 if (!Visited.insert(Ty.getCanonicalType()).second) 851 return createStorageLocation(Ty.getNonReferenceType()); 852 Value *Val = createValueUnlessSelfReferential( 853 Ty.getNonReferenceType(), Visited, Depth, CreatedValuesCount); 854 Visited.erase(Ty.getCanonicalType()); 855 856 Ty = Ty.getNonReferenceType(); 857 858 if (Val == nullptr) 859 return createStorageLocation(Ty); 860 861 if (Ty->isRecordType()) 862 return cast<RecordValue>(Val)->getLoc(); 863 864 StorageLocation &Loc = createStorageLocation(Ty); 865 setValue(Loc, *Val); 866 return Loc; 867 } 868 869 StorageLocation &Environment::createObjectInternal(const VarDecl *D, 870 QualType Ty, 871 const Expr *InitExpr) { 872 if (Ty->isReferenceType()) { 873 // Although variables of reference type always need to be initialized, it 874 // can happen that we can't see the initializer, so `InitExpr` may still 875 // be null. 876 if (InitExpr) { 877 if (auto *InitExprLoc = getStorageLocation(*InitExpr)) 878 return *InitExprLoc; 879 } 880 881 // Even though we have an initializer, we might not get an 882 // InitExprLoc, for example if the InitExpr is a CallExpr for which we 883 // don't have a function body. In this case, we just invent a storage 884 // location and value -- it's the best we can do. 885 return createObjectInternal(D, Ty.getNonReferenceType(), nullptr); 886 } 887 888 Value *Val = nullptr; 889 if (InitExpr) 890 // In the (few) cases where an expression is intentionally 891 // "uninterpreted", `InitExpr` is not associated with a value. There are 892 // two ways to handle this situation: propagate the status, so that 893 // uninterpreted initializers result in uninterpreted variables, or 894 // provide a default value. We choose the latter so that later refinements 895 // of the variable can be used for reasoning about the surrounding code. 896 // For this reason, we let this case be handled by the `createValue()` 897 // call below. 898 // 899 // FIXME. If and when we interpret all language cases, change this to 900 // assert that `InitExpr` is interpreted, rather than supplying a 901 // default value (assuming we don't update the environment API to return 902 // references). 903 Val = getValue(*InitExpr); 904 if (!Val) 905 Val = createValue(Ty); 906 907 if (Ty->isRecordType()) 908 return cast<RecordValue>(Val)->getLoc(); 909 910 StorageLocation &Loc = 911 D ? createStorageLocation(*D) : createStorageLocation(Ty); 912 913 if (Val) 914 setValue(Loc, *Val); 915 916 return Loc; 917 } 918 919 void Environment::addToFlowCondition(const Formula &Val) { 920 DACtx->addFlowConditionConstraint(FlowConditionToken, Val); 921 } 922 923 bool Environment::flowConditionImplies(const Formula &Val) const { 924 return DACtx->flowConditionImplies(FlowConditionToken, Val); 925 } 926 927 void Environment::dump(raw_ostream &OS) const { 928 // FIXME: add printing for remaining fields and allow caller to decide what 929 // fields are printed. 930 OS << "DeclToLoc:\n"; 931 for (auto [D, L] : DeclToLoc) 932 OS << " [" << D->getNameAsString() << ", " << L << "]\n"; 933 934 OS << "ExprToLoc:\n"; 935 for (auto [E, L] : ExprToLoc) 936 OS << " [" << E << ", " << L << "]\n"; 937 938 OS << "ExprToVal:\n"; 939 for (auto [E, V] : ExprToVal) 940 OS << " [" << E << ", " << V << ": " << *V << "]\n"; 941 942 OS << "LocToVal:\n"; 943 for (auto [L, V] : LocToVal) { 944 OS << " [" << L << ", " << V << ": " << *V << "]\n"; 945 } 946 947 OS << "FlowConditionToken:\n"; 948 DACtx->dumpFlowCondition(FlowConditionToken, OS); 949 } 950 951 void Environment::dump() const { 952 dump(llvm::dbgs()); 953 } 954 955 RecordStorageLocation *getImplicitObjectLocation(const CXXMemberCallExpr &MCE, 956 const Environment &Env) { 957 Expr *ImplicitObject = MCE.getImplicitObjectArgument(); 958 if (ImplicitObject == nullptr) 959 return nullptr; 960 if (ImplicitObject->getType()->isPointerType()) { 961 if (auto *Val = cast_or_null<PointerValue>(Env.getValue(*ImplicitObject))) 962 return &cast<RecordStorageLocation>(Val->getPointeeLoc()); 963 return nullptr; 964 } 965 return cast_or_null<RecordStorageLocation>( 966 Env.getStorageLocation(*ImplicitObject)); 967 } 968 969 RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME, 970 const Environment &Env) { 971 Expr *Base = ME.getBase(); 972 if (Base == nullptr) 973 return nullptr; 974 if (ME.isArrow()) { 975 if (auto *Val = cast_or_null<PointerValue>(Env.getValue(*Base))) 976 return &cast<RecordStorageLocation>(Val->getPointeeLoc()); 977 return nullptr; 978 } 979 return cast_or_null<RecordStorageLocation>(Env.getStorageLocation(*Base)); 980 } 981 982 std::vector<FieldDecl *> getFieldsForInitListExpr(const RecordDecl *RD) { 983 // Unnamed bitfields are only used for padding and do not appear in 984 // `InitListExpr`'s inits. However, those fields do appear in `RecordDecl`'s 985 // field list, and we thus need to remove them before mapping inits to 986 // fields to avoid mapping inits to the wrongs fields. 987 std::vector<FieldDecl *> Fields; 988 llvm::copy_if( 989 RD->fields(), std::back_inserter(Fields), 990 [](const FieldDecl *Field) { return !Field->isUnnamedBitfield(); }); 991 return Fields; 992 } 993 994 RecordValue &refreshRecordValue(RecordStorageLocation &Loc, Environment &Env) { 995 auto &NewVal = Env.create<RecordValue>(Loc); 996 Env.setValue(Loc, NewVal); 997 return NewVal; 998 } 999 1000 RecordValue &refreshRecordValue(const Expr &Expr, Environment &Env) { 1001 assert(Expr.getType()->isRecordType()); 1002 1003 if (Expr.isPRValue()) { 1004 if (auto *ExistingVal = cast_or_null<RecordValue>(Env.getValue(Expr))) { 1005 auto &NewVal = Env.create<RecordValue>(ExistingVal->getLoc()); 1006 Env.setValue(Expr, NewVal); 1007 return NewVal; 1008 } 1009 1010 auto &NewVal = *cast<RecordValue>(Env.createValue(Expr.getType())); 1011 Env.setValue(Expr, NewVal); 1012 return NewVal; 1013 } 1014 1015 if (auto *Loc = 1016 cast_or_null<RecordStorageLocation>(Env.getStorageLocation(Expr))) { 1017 auto &NewVal = Env.create<RecordValue>(*Loc); 1018 Env.setValue(*Loc, NewVal); 1019 return NewVal; 1020 } 1021 1022 auto &NewVal = *cast<RecordValue>(Env.createValue(Expr.getType())); 1023 Env.setStorageLocation(Expr, NewVal.getLoc()); 1024 return NewVal; 1025 } 1026 1027 } // namespace dataflow 1028 } // namespace clang 1029