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