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