1 //===- unittests/Analysis/FlowSensitive/TransferTest.cpp ------------------===// 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 #include "TestingSupport.h" 10 #include "clang/AST/ASTContext.h" 11 #include "clang/AST/Decl.h" 12 #include "clang/ASTMatchers/ASTMatchers.h" 13 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" 14 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" 15 #include "clang/Analysis/FlowSensitive/NoopAnalysis.h" 16 #include "clang/Analysis/FlowSensitive/StorageLocation.h" 17 #include "clang/Analysis/FlowSensitive/Value.h" 18 #include "clang/Basic/LangStandard.h" 19 #include "llvm/ADT/ArrayRef.h" 20 #include "llvm/ADT/SmallVector.h" 21 #include "llvm/ADT/StringRef.h" 22 #include "llvm/Support/Casting.h" 23 #include "llvm/Testing/Support/Error.h" 24 #include "gmock/gmock.h" 25 #include "gtest/gtest.h" 26 #include <optional> 27 #include <string> 28 #include <utility> 29 30 namespace { 31 32 using namespace clang; 33 using namespace dataflow; 34 using namespace test; 35 using ::testing::IsNull; 36 using ::testing::NotNull; 37 using ::testing::UnorderedElementsAre; 38 39 using BuiltinOptions = DataflowAnalysisContext::Options; 40 41 template <typename Matcher> 42 void runDataflow(llvm::StringRef Code, Matcher Match, 43 DataflowAnalysisOptions Options, 44 LangStandard::Kind Std = LangStandard::lang_cxx17, 45 llvm::StringRef TargetFun = "target") { 46 using ast_matchers::hasName; 47 llvm::SmallVector<std::string, 3> ASTBuildArgs = { 48 "-fsyntax-only", "-fno-delayed-template-parsing", 49 "-std=" + 50 std::string(LangStandard::getLangStandardForKind(Std).getName())}; 51 AnalysisInputs<NoopAnalysis> AI( 52 Code, hasName(TargetFun), 53 [UseBuiltinModel = Options.BuiltinOpts.has_value()](ASTContext &C, 54 Environment &Env) { 55 return NoopAnalysis( 56 C, 57 DataflowAnalysisOptions{ 58 UseBuiltinModel ? Env.getDataflowAnalysisContext().getOptions() 59 : std::optional<BuiltinOptions>()}); 60 }); 61 AI.ASTBuildArgs = ASTBuildArgs; 62 if (Options.BuiltinOpts) 63 AI.BuiltinOptions = *Options.BuiltinOpts; 64 ASSERT_THAT_ERROR( 65 checkDataflow<NoopAnalysis>( 66 std::move(AI), 67 /*VerifyResults=*/ 68 [&Match](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> 69 &Results, 70 const AnalysisOutputs &AO) { Match(Results, AO.ASTCtx); }), 71 llvm::Succeeded()); 72 } 73 74 template <typename Matcher> 75 void runDataflow(llvm::StringRef Code, Matcher Match, 76 LangStandard::Kind Std = LangStandard::lang_cxx17, 77 bool ApplyBuiltinTransfer = true, 78 llvm::StringRef TargetFun = "target") { 79 runDataflow(Code, std::move(Match), 80 {ApplyBuiltinTransfer ? BuiltinOptions{} 81 : std::optional<BuiltinOptions>()}, 82 Std, TargetFun); 83 } 84 85 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) { 86 std::string Code = R"( 87 void target() { 88 int Foo; 89 // [[p]] 90 } 91 )"; 92 runDataflow( 93 Code, 94 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 95 ASTContext &ASTCtx) { 96 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 97 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 98 99 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 100 ASSERT_THAT(FooDecl, NotNull()); 101 102 EXPECT_EQ(Env.getStorageLocation(*FooDecl), nullptr); 103 }, 104 LangStandard::lang_cxx17, 105 /*ApplyBuiltinTransfer=*/false); 106 } 107 108 TEST(TransferTest, BoolVarDecl) { 109 std::string Code = R"( 110 void target() { 111 bool Foo; 112 // [[p]] 113 } 114 )"; 115 runDataflow( 116 Code, 117 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 118 ASTContext &ASTCtx) { 119 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 120 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 121 122 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 123 ASSERT_THAT(FooDecl, NotNull()); 124 125 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 126 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 127 128 const Value *FooVal = Env.getValue(*FooLoc); 129 EXPECT_TRUE(isa_and_nonnull<BoolValue>(FooVal)); 130 }); 131 } 132 133 TEST(TransferTest, IntVarDecl) { 134 std::string Code = R"( 135 void target() { 136 int Foo; 137 // [[p]] 138 } 139 )"; 140 runDataflow( 141 Code, 142 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 143 ASTContext &ASTCtx) { 144 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 145 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 146 147 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 148 ASSERT_THAT(FooDecl, NotNull()); 149 150 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 151 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 152 153 const Value *FooVal = Env.getValue(*FooLoc); 154 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 155 }); 156 } 157 158 TEST(TransferTest, StructIncomplete) { 159 std::string Code = R"( 160 struct A; 161 162 void target() { 163 A* Foo; 164 // [[p]] 165 } 166 )"; 167 runDataflow( 168 Code, 169 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 170 ASTContext &ASTCtx) { 171 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 172 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 173 174 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 175 ASSERT_THAT(FooDecl, NotNull()); 176 auto *FooValue = dyn_cast_or_null<PointerValue>(Env.getValue(*FooDecl)); 177 ASSERT_THAT(FooValue, NotNull()); 178 179 EXPECT_TRUE(isa<AggregateStorageLocation>(FooValue->getPointeeLoc())); 180 auto *FooPointeeValue = Env.getValue(FooValue->getPointeeLoc()); 181 ASSERT_THAT(FooPointeeValue, NotNull()); 182 EXPECT_TRUE(isa<StructValue>(FooPointeeValue)); 183 }); 184 } 185 186 // As a memory optimization, we prevent modeling fields nested below a certain 187 // level (currently, depth 3). This test verifies this lack of modeling. We also 188 // include a regression test for the case that the unmodeled field is a 189 // reference to a struct; previously, we crashed when accessing such a field. 190 TEST(TransferTest, StructFieldUnmodeled) { 191 std::string Code = R"( 192 struct S { int X; }; 193 S GlobalS; 194 struct A { S &Unmodeled = GlobalS; }; 195 struct B { A F3; }; 196 struct C { B F2; }; 197 struct D { C F1; }; 198 199 void target() { 200 D Bar; 201 A Foo = Bar.F1.F2.F3; 202 int Zab = Foo.Unmodeled.X; 203 // [[p]] 204 } 205 )"; 206 runDataflow( 207 Code, 208 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 209 ASTContext &ASTCtx) { 210 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 211 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 212 213 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 214 ASSERT_THAT(FooDecl, NotNull()); 215 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 216 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 217 218 FieldDecl *UnmodeledDecl = nullptr; 219 for (FieldDecl *Field : FooFields) { 220 if (Field->getNameAsString() == "Unmodeled") { 221 UnmodeledDecl = Field; 222 } else { 223 FAIL() << "Unexpected field: " << Field->getNameAsString(); 224 } 225 } 226 ASSERT_THAT(UnmodeledDecl, NotNull()); 227 228 const auto *FooLoc = 229 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 230 const auto *UnmodeledLoc = &FooLoc->getChild(*UnmodeledDecl); 231 ASSERT_TRUE(isa<ScalarStorageLocation>(UnmodeledLoc)); 232 ASSERT_THAT(Env.getValue(*UnmodeledLoc), IsNull()); 233 234 const ValueDecl *ZabDecl = findValueDecl(ASTCtx, "Zab"); 235 ASSERT_THAT(ZabDecl, NotNull()); 236 EXPECT_THAT(Env.getValue(*ZabDecl), NotNull()); 237 }); 238 } 239 240 TEST(TransferTest, StructVarDecl) { 241 std::string Code = R"( 242 struct A { 243 int Bar; 244 }; 245 246 void target() { 247 A Foo; 248 (void)Foo.Bar; 249 // [[p]] 250 } 251 )"; 252 runDataflow( 253 Code, 254 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 255 ASTContext &ASTCtx) { 256 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 257 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 258 259 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 260 ASSERT_THAT(FooDecl, NotNull()); 261 262 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 263 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 264 265 FieldDecl *BarDecl = nullptr; 266 for (FieldDecl *Field : FooFields) { 267 if (Field->getNameAsString() == "Bar") { 268 BarDecl = Field; 269 } else { 270 FAIL() << "Unexpected field: " << Field->getNameAsString(); 271 } 272 } 273 ASSERT_THAT(BarDecl, NotNull()); 274 275 const auto *FooLoc = 276 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 277 const auto *BarLoc = 278 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 279 280 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 281 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 282 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 283 }); 284 } 285 286 TEST(TransferTest, StructVarDeclWithInit) { 287 std::string Code = R"( 288 struct A { 289 int Bar; 290 }; 291 292 A Gen(); 293 294 void target() { 295 A Foo = Gen(); 296 (void)Foo.Bar; 297 // [[p]] 298 } 299 )"; 300 runDataflow( 301 Code, 302 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 303 ASTContext &ASTCtx) { 304 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 305 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 306 307 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 308 ASSERT_THAT(FooDecl, NotNull()); 309 310 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 311 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 312 313 FieldDecl *BarDecl = nullptr; 314 for (FieldDecl *Field : FooFields) { 315 if (Field->getNameAsString() == "Bar") { 316 BarDecl = Field; 317 } else { 318 FAIL() << "Unexpected field: " << Field->getNameAsString(); 319 } 320 } 321 ASSERT_THAT(BarDecl, NotNull()); 322 323 const auto *FooLoc = 324 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 325 const auto *BarLoc = 326 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 327 328 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 329 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 330 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 331 }); 332 } 333 334 TEST(TransferTest, ClassVarDecl) { 335 std::string Code = R"( 336 class A { 337 public: 338 int Bar; 339 }; 340 341 void target() { 342 A Foo; 343 (void)Foo.Bar; 344 // [[p]] 345 } 346 )"; 347 runDataflow( 348 Code, 349 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 350 ASTContext &ASTCtx) { 351 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 352 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 353 354 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 355 ASSERT_THAT(FooDecl, NotNull()); 356 357 ASSERT_TRUE(FooDecl->getType()->isClassType()); 358 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 359 360 FieldDecl *BarDecl = nullptr; 361 for (FieldDecl *Field : FooFields) { 362 if (Field->getNameAsString() == "Bar") { 363 BarDecl = Field; 364 } else { 365 FAIL() << "Unexpected field: " << Field->getNameAsString(); 366 } 367 } 368 ASSERT_THAT(BarDecl, NotNull()); 369 370 const auto *FooLoc = 371 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 372 const auto *BarLoc = 373 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 374 375 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 376 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 377 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 378 }); 379 } 380 381 TEST(TransferTest, ReferenceVarDecl) { 382 std::string Code = R"( 383 struct A {}; 384 385 A &getA(); 386 387 void target() { 388 A &Foo = getA(); 389 // [[p]] 390 } 391 )"; 392 runDataflow( 393 Code, 394 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 395 ASTContext &ASTCtx) { 396 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 397 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 398 399 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 400 ASSERT_THAT(FooDecl, NotNull()); 401 402 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 403 ASSERT_TRUE(isa_and_nonnull<AggregateStorageLocation>(FooLoc)); 404 405 const Value *FooReferentVal = Env.getValue(*FooLoc); 406 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooReferentVal)); 407 }); 408 } 409 410 TEST(TransferTest, SelfReferentialReferenceVarDecl) { 411 std::string Code = R"( 412 struct A; 413 414 struct B {}; 415 416 struct C { 417 A &FooRef; 418 A *FooPtr; 419 B &BazRef; 420 B *BazPtr; 421 }; 422 423 struct A { 424 C &Bar; 425 }; 426 427 A &getA(); 428 429 void target() { 430 A &Foo = getA(); 431 (void)Foo.Bar.FooRef; 432 (void)Foo.Bar.FooPtr; 433 (void)Foo.Bar.BazRef; 434 (void)Foo.Bar.BazPtr; 435 // [[p]] 436 } 437 )"; 438 runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> 439 &Results, 440 ASTContext &ASTCtx) { 441 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 442 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 443 444 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 445 ASSERT_THAT(FooDecl, NotNull()); 446 447 ASSERT_TRUE(FooDecl->getType()->isReferenceType()); 448 ASSERT_TRUE(FooDecl->getType().getNonReferenceType()->isStructureType()); 449 const auto FooFields = 450 FooDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields(); 451 452 FieldDecl *BarDecl = nullptr; 453 for (FieldDecl *Field : FooFields) { 454 if (Field->getNameAsString() == "Bar") { 455 BarDecl = Field; 456 } else { 457 FAIL() << "Unexpected field: " << Field->getNameAsString(); 458 } 459 } 460 ASSERT_THAT(BarDecl, NotNull()); 461 462 ASSERT_TRUE(BarDecl->getType()->isReferenceType()); 463 ASSERT_TRUE(BarDecl->getType().getNonReferenceType()->isStructureType()); 464 const auto BarFields = 465 BarDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields(); 466 467 FieldDecl *FooRefDecl = nullptr; 468 FieldDecl *FooPtrDecl = nullptr; 469 FieldDecl *BazRefDecl = nullptr; 470 FieldDecl *BazPtrDecl = nullptr; 471 for (FieldDecl *Field : BarFields) { 472 if (Field->getNameAsString() == "FooRef") { 473 FooRefDecl = Field; 474 } else if (Field->getNameAsString() == "FooPtr") { 475 FooPtrDecl = Field; 476 } else if (Field->getNameAsString() == "BazRef") { 477 BazRefDecl = Field; 478 } else if (Field->getNameAsString() == "BazPtr") { 479 BazPtrDecl = Field; 480 } else { 481 FAIL() << "Unexpected field: " << Field->getNameAsString(); 482 } 483 } 484 ASSERT_THAT(FooRefDecl, NotNull()); 485 ASSERT_THAT(FooPtrDecl, NotNull()); 486 ASSERT_THAT(BazRefDecl, NotNull()); 487 ASSERT_THAT(BazPtrDecl, NotNull()); 488 489 const auto *FooLoc = 490 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 491 const auto *FooReferentVal = cast<StructValue>(Env.getValue(*FooLoc)); 492 493 const auto *BarVal = 494 cast<ReferenceValue>(FooReferentVal->getChild(*BarDecl)); 495 const auto *BarReferentVal = 496 cast<StructValue>(Env.getValue(BarVal->getReferentLoc())); 497 498 const auto *FooRefVal = 499 cast<ReferenceValue>(BarReferentVal->getChild(*FooRefDecl)); 500 const auto &FooReferentLoc = 501 cast<AggregateStorageLocation>(FooRefVal->getReferentLoc()); 502 EXPECT_THAT(Env.getValue(FooReferentLoc), NotNull()); 503 EXPECT_THAT(Env.getValue(FooReferentLoc.getChild(*BarDecl)), IsNull()); 504 505 const auto *FooPtrVal = 506 cast<PointerValue>(BarReferentVal->getChild(*FooPtrDecl)); 507 const auto &FooPtrPointeeLoc = 508 cast<AggregateStorageLocation>(FooPtrVal->getPointeeLoc()); 509 EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), NotNull()); 510 EXPECT_THAT(Env.getValue(FooPtrPointeeLoc.getChild(*BarDecl)), IsNull()); 511 512 const auto *BazRefVal = 513 cast<ReferenceValue>(BarReferentVal->getChild(*BazRefDecl)); 514 const StorageLocation &BazReferentLoc = BazRefVal->getReferentLoc(); 515 EXPECT_THAT(Env.getValue(BazReferentLoc), NotNull()); 516 517 const auto *BazPtrVal = 518 cast<PointerValue>(BarReferentVal->getChild(*BazPtrDecl)); 519 const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc(); 520 EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull()); 521 }); 522 } 523 524 TEST(TransferTest, PointerVarDecl) { 525 std::string Code = R"( 526 struct A {}; 527 528 A *getA(); 529 530 void target() { 531 A *Foo = getA(); 532 // [[p]] 533 } 534 )"; 535 runDataflow( 536 Code, 537 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 538 ASTContext &ASTCtx) { 539 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 540 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 541 542 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 543 ASSERT_THAT(FooDecl, NotNull()); 544 545 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 546 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 547 548 const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 549 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); 550 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc)); 551 552 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); 553 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal)); 554 }); 555 } 556 557 TEST(TransferTest, SelfReferentialPointerVarDecl) { 558 std::string Code = R"( 559 struct A; 560 561 struct B {}; 562 563 struct C { 564 A &FooRef; 565 A *FooPtr; 566 B &BazRef; 567 B *BazPtr; 568 }; 569 570 struct A { 571 C *Bar; 572 }; 573 574 A *getA(); 575 576 void target() { 577 A *Foo = getA(); 578 (void)Foo->Bar->FooRef; 579 (void)Foo->Bar->FooPtr; 580 (void)Foo->Bar->BazRef; 581 (void)Foo->Bar->BazPtr; 582 // [[p]] 583 } 584 )"; 585 runDataflow( 586 Code, 587 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 588 ASTContext &ASTCtx) { 589 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 590 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 591 592 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 593 ASSERT_THAT(FooDecl, NotNull()); 594 595 ASSERT_TRUE(FooDecl->getType()->isPointerType()); 596 ASSERT_TRUE(FooDecl->getType() 597 ->getAs<PointerType>() 598 ->getPointeeType() 599 ->isStructureType()); 600 const auto FooFields = FooDecl->getType() 601 ->getAs<PointerType>() 602 ->getPointeeType() 603 ->getAsRecordDecl() 604 ->fields(); 605 606 FieldDecl *BarDecl = nullptr; 607 for (FieldDecl *Field : FooFields) { 608 if (Field->getNameAsString() == "Bar") { 609 BarDecl = Field; 610 } else { 611 FAIL() << "Unexpected field: " << Field->getNameAsString(); 612 } 613 } 614 ASSERT_THAT(BarDecl, NotNull()); 615 616 ASSERT_TRUE(BarDecl->getType()->isPointerType()); 617 ASSERT_TRUE(BarDecl->getType() 618 ->getAs<PointerType>() 619 ->getPointeeType() 620 ->isStructureType()); 621 const auto BarFields = BarDecl->getType() 622 ->getAs<PointerType>() 623 ->getPointeeType() 624 ->getAsRecordDecl() 625 ->fields(); 626 627 FieldDecl *FooRefDecl = nullptr; 628 FieldDecl *FooPtrDecl = nullptr; 629 FieldDecl *BazRefDecl = nullptr; 630 FieldDecl *BazPtrDecl = nullptr; 631 for (FieldDecl *Field : BarFields) { 632 if (Field->getNameAsString() == "FooRef") { 633 FooRefDecl = Field; 634 } else if (Field->getNameAsString() == "FooPtr") { 635 FooPtrDecl = Field; 636 } else if (Field->getNameAsString() == "BazRef") { 637 BazRefDecl = Field; 638 } else if (Field->getNameAsString() == "BazPtr") { 639 BazPtrDecl = Field; 640 } else { 641 FAIL() << "Unexpected field: " << Field->getNameAsString(); 642 } 643 } 644 ASSERT_THAT(FooRefDecl, NotNull()); 645 ASSERT_THAT(FooPtrDecl, NotNull()); 646 ASSERT_THAT(BazRefDecl, NotNull()); 647 ASSERT_THAT(BazPtrDecl, NotNull()); 648 649 const auto *FooLoc = 650 cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl)); 651 const auto *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 652 const auto *FooPointeeVal = 653 cast<StructValue>(Env.getValue(FooVal->getPointeeLoc())); 654 655 const auto *BarVal = 656 cast<PointerValue>(FooPointeeVal->getChild(*BarDecl)); 657 const auto *BarPointeeVal = 658 cast<StructValue>(Env.getValue(BarVal->getPointeeLoc())); 659 660 const auto *FooRefVal = 661 cast<ReferenceValue>(BarPointeeVal->getChild(*FooRefDecl)); 662 const StorageLocation &FooReferentLoc = FooRefVal->getReferentLoc(); 663 EXPECT_THAT(Env.getValue(FooReferentLoc), IsNull()); 664 665 const auto *FooPtrVal = 666 cast<PointerValue>(BarPointeeVal->getChild(*FooPtrDecl)); 667 const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc(); 668 EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull()); 669 670 const auto *BazRefVal = 671 cast<ReferenceValue>(BarPointeeVal->getChild(*BazRefDecl)); 672 const StorageLocation &BazReferentLoc = BazRefVal->getReferentLoc(); 673 EXPECT_THAT(Env.getValue(BazReferentLoc), NotNull()); 674 675 const auto *BazPtrVal = 676 cast<PointerValue>(BarPointeeVal->getChild(*BazPtrDecl)); 677 const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc(); 678 EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull()); 679 }); 680 } 681 682 TEST(TransferTest, MultipleVarsDecl) { 683 std::string Code = R"( 684 void target() { 685 int Foo, Bar; 686 (void)0; 687 // [[p]] 688 } 689 )"; 690 runDataflow( 691 Code, 692 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 693 ASTContext &ASTCtx) { 694 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 695 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 696 697 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 698 ASSERT_THAT(FooDecl, NotNull()); 699 700 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 701 ASSERT_THAT(BarDecl, NotNull()); 702 703 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 704 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 705 706 const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl); 707 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 708 709 const Value *FooVal = Env.getValue(*FooLoc); 710 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 711 712 const Value *BarVal = Env.getValue(*BarLoc); 713 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 714 }); 715 } 716 717 TEST(TransferTest, JoinVarDecl) { 718 std::string Code = R"( 719 void target(bool B) { 720 int Foo; 721 // [[p1]] 722 if (B) { 723 int Bar; 724 // [[p2]] 725 } else { 726 int Baz; 727 // [[p3]] 728 } 729 (void)0; 730 // [[p4]] 731 } 732 )"; 733 runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> 734 &Results, 735 ASTContext &ASTCtx) { 736 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2", "p3", "p4")); 737 738 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 739 ASSERT_THAT(FooDecl, NotNull()); 740 741 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 742 ASSERT_THAT(BarDecl, NotNull()); 743 744 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 745 ASSERT_THAT(BazDecl, NotNull()); 746 747 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 748 749 const StorageLocation *FooLoc = Env1.getStorageLocation(*FooDecl); 750 EXPECT_THAT(FooLoc, NotNull()); 751 EXPECT_THAT(Env1.getStorageLocation(*BarDecl), IsNull()); 752 EXPECT_THAT(Env1.getStorageLocation(*BazDecl), IsNull()); 753 754 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 755 EXPECT_EQ(Env2.getStorageLocation(*FooDecl), FooLoc); 756 EXPECT_THAT(Env2.getStorageLocation(*BarDecl), NotNull()); 757 EXPECT_THAT(Env2.getStorageLocation(*BazDecl), IsNull()); 758 759 const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3"); 760 EXPECT_EQ(Env3.getStorageLocation(*FooDecl), FooLoc); 761 EXPECT_THAT(Env3.getStorageLocation(*BarDecl), IsNull()); 762 EXPECT_THAT(Env3.getStorageLocation(*BazDecl), NotNull()); 763 764 const Environment &Env4 = getEnvironmentAtAnnotation(Results, "p4"); 765 EXPECT_EQ(Env4.getStorageLocation(*FooDecl), FooLoc); 766 EXPECT_THAT(Env4.getStorageLocation(*BarDecl), IsNull()); 767 EXPECT_THAT(Env4.getStorageLocation(*BazDecl), IsNull()); 768 }); 769 } 770 771 TEST(TransferTest, BinaryOperatorAssign) { 772 std::string Code = R"( 773 void target() { 774 int Foo; 775 int Bar; 776 (Bar) = (Foo); 777 // [[p]] 778 } 779 )"; 780 runDataflow( 781 Code, 782 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 783 ASTContext &ASTCtx) { 784 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 785 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 786 787 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 788 ASSERT_THAT(FooDecl, NotNull()); 789 790 const Value *FooVal = Env.getValue(*FooDecl); 791 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 792 793 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 794 ASSERT_THAT(BarDecl, NotNull()); 795 796 EXPECT_EQ(Env.getValue(*BarDecl), FooVal); 797 }); 798 } 799 800 TEST(TransferTest, VarDeclInitAssign) { 801 std::string Code = R"( 802 void target() { 803 int Foo; 804 int Bar = Foo; 805 // [[p]] 806 } 807 )"; 808 runDataflow( 809 Code, 810 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 811 ASTContext &ASTCtx) { 812 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 813 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 814 815 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 816 ASSERT_THAT(FooDecl, NotNull()); 817 818 const Value *FooVal = Env.getValue(*FooDecl); 819 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 820 821 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 822 ASSERT_THAT(BarDecl, NotNull()); 823 824 EXPECT_EQ(Env.getValue(*BarDecl), FooVal); 825 }); 826 } 827 828 TEST(TransferTest, VarDeclInitAssignChained) { 829 std::string Code = R"( 830 void target() { 831 int Foo; 832 int Bar; 833 int Baz = (Bar = Foo); 834 // [[p]] 835 } 836 )"; 837 runDataflow( 838 Code, 839 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 840 ASTContext &ASTCtx) { 841 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 842 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 843 844 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 845 ASSERT_THAT(FooDecl, NotNull()); 846 847 const Value *FooVal = Env.getValue(*FooDecl); 848 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 849 850 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 851 ASSERT_THAT(BarDecl, NotNull()); 852 853 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 854 ASSERT_THAT(BazDecl, NotNull()); 855 856 EXPECT_EQ(Env.getValue(*BarDecl), FooVal); 857 EXPECT_EQ(Env.getValue(*BazDecl), FooVal); 858 }); 859 } 860 861 TEST(TransferTest, VarDeclInitAssignPtrDeref) { 862 std::string Code = R"( 863 void target() { 864 int Foo; 865 int *Bar; 866 *(Bar) = Foo; 867 int Baz = *(Bar); 868 // [[p]] 869 } 870 )"; 871 runDataflow( 872 Code, 873 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 874 ASTContext &ASTCtx) { 875 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 876 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 877 878 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 879 ASSERT_THAT(FooDecl, NotNull()); 880 881 const Value *FooVal = Env.getValue(*FooDecl); 882 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 883 884 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 885 ASSERT_THAT(BarDecl, NotNull()); 886 887 const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl)); 888 EXPECT_EQ(Env.getValue(BarVal->getPointeeLoc()), FooVal); 889 890 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 891 ASSERT_THAT(BazDecl, NotNull()); 892 893 EXPECT_EQ(Env.getValue(*BazDecl), FooVal); 894 }); 895 } 896 897 TEST(TransferTest, AssignToAndFromReference) { 898 std::string Code = R"( 899 void target() { 900 int Foo; 901 int Bar; 902 int &Baz = Foo; 903 // [[p1]] 904 Baz = Bar; 905 int Qux = Baz; 906 int &Quux = Baz; 907 // [[p2]] 908 } 909 )"; 910 runDataflow( 911 Code, 912 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 913 ASTContext &ASTCtx) { 914 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 915 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 916 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 917 918 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 919 ASSERT_THAT(FooDecl, NotNull()); 920 921 const Value *FooVal = Env1.getValue(*FooDecl); 922 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 923 924 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 925 ASSERT_THAT(BarDecl, NotNull()); 926 927 const Value *BarVal = Env1.getValue(*BarDecl); 928 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 929 930 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 931 ASSERT_THAT(BazDecl, NotNull()); 932 933 EXPECT_EQ(Env1.getValue(*BazDecl), FooVal); 934 935 EXPECT_EQ(Env2.getValue(*BazDecl), BarVal); 936 EXPECT_EQ(Env2.getValue(*FooDecl), BarVal); 937 938 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 939 ASSERT_THAT(QuxDecl, NotNull()); 940 EXPECT_EQ(Env2.getValue(*QuxDecl), BarVal); 941 942 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 943 ASSERT_THAT(QuuxDecl, NotNull()); 944 EXPECT_EQ(Env2.getValue(*QuuxDecl), BarVal); 945 }); 946 } 947 948 TEST(TransferTest, MultipleParamDecls) { 949 std::string Code = R"( 950 void target(int Foo, int Bar) { 951 (void)0; 952 // [[p]] 953 } 954 )"; 955 runDataflow( 956 Code, 957 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 958 ASTContext &ASTCtx) { 959 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 960 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 961 962 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 963 ASSERT_THAT(FooDecl, NotNull()); 964 965 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 966 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 967 968 const Value *FooVal = Env.getValue(*FooLoc); 969 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 970 971 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 972 ASSERT_THAT(BarDecl, NotNull()); 973 974 const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl); 975 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 976 977 const Value *BarVal = Env.getValue(*BarLoc); 978 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 979 }); 980 } 981 982 TEST(TransferTest, StructParamDecl) { 983 std::string Code = R"( 984 struct A { 985 int Bar; 986 }; 987 988 void target(A Foo) { 989 (void)Foo.Bar; 990 // [[p]] 991 } 992 )"; 993 runDataflow( 994 Code, 995 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 996 ASTContext &ASTCtx) { 997 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 998 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 999 1000 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1001 ASSERT_THAT(FooDecl, NotNull()); 1002 1003 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 1004 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1005 1006 FieldDecl *BarDecl = nullptr; 1007 for (FieldDecl *Field : FooFields) { 1008 if (Field->getNameAsString() == "Bar") { 1009 BarDecl = Field; 1010 } else { 1011 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1012 } 1013 } 1014 ASSERT_THAT(BarDecl, NotNull()); 1015 1016 const auto *FooLoc = 1017 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 1018 const auto *BarLoc = 1019 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1020 1021 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1022 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1023 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1024 }); 1025 } 1026 1027 TEST(TransferTest, ReferenceParamDecl) { 1028 std::string Code = R"( 1029 struct A {}; 1030 1031 void target(A &Foo) { 1032 (void)0; 1033 // [[p]] 1034 } 1035 )"; 1036 runDataflow( 1037 Code, 1038 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1039 ASTContext &ASTCtx) { 1040 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1041 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1042 1043 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1044 ASSERT_THAT(FooDecl, NotNull()); 1045 1046 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 1047 ASSERT_TRUE(isa_and_nonnull<AggregateStorageLocation>(FooLoc)); 1048 1049 const Value *FooReferentVal = Env.getValue(*FooLoc); 1050 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooReferentVal)); 1051 }); 1052 } 1053 1054 TEST(TransferTest, PointerParamDecl) { 1055 std::string Code = R"( 1056 struct A {}; 1057 1058 void target(A *Foo) { 1059 (void)0; 1060 // [[p]] 1061 } 1062 )"; 1063 runDataflow( 1064 Code, 1065 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1066 ASTContext &ASTCtx) { 1067 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1068 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1069 1070 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1071 ASSERT_THAT(FooDecl, NotNull()); 1072 1073 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 1074 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 1075 1076 const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc)); 1077 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc(); 1078 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc)); 1079 1080 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc); 1081 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal)); 1082 }); 1083 } 1084 1085 TEST(TransferTest, StructMember) { 1086 std::string Code = R"( 1087 struct A { 1088 int Bar; 1089 }; 1090 1091 void target(A Foo) { 1092 int Baz = Foo.Bar; 1093 // [[p]] 1094 } 1095 )"; 1096 runDataflow( 1097 Code, 1098 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1099 ASTContext &ASTCtx) { 1100 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1101 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1102 1103 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1104 ASSERT_THAT(FooDecl, NotNull()); 1105 1106 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 1107 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1108 1109 FieldDecl *BarDecl = nullptr; 1110 for (FieldDecl *Field : FooFields) { 1111 if (Field->getNameAsString() == "Bar") { 1112 BarDecl = Field; 1113 } else { 1114 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1115 } 1116 } 1117 ASSERT_THAT(BarDecl, NotNull()); 1118 1119 const auto *FooLoc = 1120 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 1121 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1122 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1123 1124 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1125 ASSERT_THAT(BazDecl, NotNull()); 1126 1127 EXPECT_EQ(Env.getValue(*BazDecl), BarVal); 1128 }); 1129 } 1130 1131 TEST(TransferTest, StructMemberEnum) { 1132 std::string Code = R"( 1133 struct A { 1134 int Bar; 1135 enum E { ONE, TWO }; 1136 }; 1137 1138 void target(A Foo) { 1139 A::E Baz = Foo.ONE; 1140 // [[p]] 1141 } 1142 )"; 1143 // Minimal expectations -- we're just testing that it doesn't crash, since 1144 // enums aren't interpreted. 1145 runDataflow( 1146 Code, 1147 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1148 ASTContext &ASTCtx) { 1149 EXPECT_THAT(Results.keys(), UnorderedElementsAre("p")); 1150 }); 1151 } 1152 1153 TEST(TransferTest, DerivedBaseMemberClass) { 1154 std::string Code = R"( 1155 class A { 1156 int ADefault; 1157 protected: 1158 int AProtected; 1159 private: 1160 int APrivate; 1161 public: 1162 int APublic; 1163 1164 private: 1165 friend void target(); 1166 }; 1167 1168 class B : public A { 1169 int BDefault; 1170 protected: 1171 int BProtected; 1172 private: 1173 int BPrivate; 1174 1175 private: 1176 friend void target(); 1177 }; 1178 1179 void target() { 1180 B Foo; 1181 (void)Foo.ADefault; 1182 (void)Foo.AProtected; 1183 (void)Foo.APrivate; 1184 (void)Foo.APublic; 1185 (void)Foo.BDefault; 1186 (void)Foo.BProtected; 1187 (void)Foo.BPrivate; 1188 // [[p]] 1189 } 1190 )"; 1191 runDataflow( 1192 Code, 1193 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1194 ASTContext &ASTCtx) { 1195 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1196 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1197 1198 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1199 ASSERT_THAT(FooDecl, NotNull()); 1200 ASSERT_TRUE(FooDecl->getType()->isRecordType()); 1201 1202 // Derived-class fields. 1203 const FieldDecl *BDefaultDecl = nullptr; 1204 const FieldDecl *BProtectedDecl = nullptr; 1205 const FieldDecl *BPrivateDecl = nullptr; 1206 for (const FieldDecl *Field : 1207 FooDecl->getType()->getAsRecordDecl()->fields()) { 1208 if (Field->getNameAsString() == "BDefault") { 1209 BDefaultDecl = Field; 1210 } else if (Field->getNameAsString() == "BProtected") { 1211 BProtectedDecl = Field; 1212 } else if (Field->getNameAsString() == "BPrivate") { 1213 BPrivateDecl = Field; 1214 } else { 1215 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1216 } 1217 } 1218 ASSERT_THAT(BDefaultDecl, NotNull()); 1219 ASSERT_THAT(BProtectedDecl, NotNull()); 1220 ASSERT_THAT(BPrivateDecl, NotNull()); 1221 1222 // Base-class fields. 1223 const FieldDecl *ADefaultDecl = nullptr; 1224 const FieldDecl *APrivateDecl = nullptr; 1225 const FieldDecl *AProtectedDecl = nullptr; 1226 const FieldDecl *APublicDecl = nullptr; 1227 for (const clang::CXXBaseSpecifier &Base : 1228 FooDecl->getType()->getAsCXXRecordDecl()->bases()) { 1229 QualType BaseType = Base.getType(); 1230 ASSERT_TRUE(BaseType->isRecordType()); 1231 for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) { 1232 if (Field->getNameAsString() == "ADefault") { 1233 ADefaultDecl = Field; 1234 } else if (Field->getNameAsString() == "AProtected") { 1235 AProtectedDecl = Field; 1236 } else if (Field->getNameAsString() == "APrivate") { 1237 APrivateDecl = Field; 1238 } else if (Field->getNameAsString() == "APublic") { 1239 APublicDecl = Field; 1240 } else { 1241 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1242 } 1243 } 1244 } 1245 ASSERT_THAT(ADefaultDecl, NotNull()); 1246 ASSERT_THAT(AProtectedDecl, NotNull()); 1247 ASSERT_THAT(APrivateDecl, NotNull()); 1248 ASSERT_THAT(APublicDecl, NotNull()); 1249 1250 const auto &FooLoc = 1251 *cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 1252 const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc)); 1253 1254 // Note: we can't test presence of children in `FooLoc`, because 1255 // `getChild` requires its argument be present (or fails an assert). So, 1256 // we limit to testing presence in `FooVal` and coherence between the 1257 // two. 1258 1259 // Base-class fields. 1260 EXPECT_THAT(FooVal.getChild(*ADefaultDecl), NotNull()); 1261 EXPECT_THAT(FooVal.getChild(*APrivateDecl), NotNull()); 1262 1263 EXPECT_THAT(FooVal.getChild(*AProtectedDecl), NotNull()); 1264 EXPECT_EQ(Env.getValue(FooLoc.getChild(*APublicDecl)), 1265 FooVal.getChild(*APublicDecl)); 1266 EXPECT_THAT(FooVal.getChild(*APublicDecl), NotNull()); 1267 EXPECT_EQ(Env.getValue(FooLoc.getChild(*AProtectedDecl)), 1268 FooVal.getChild(*AProtectedDecl)); 1269 1270 // Derived-class fields. 1271 EXPECT_THAT(FooVal.getChild(*BDefaultDecl), NotNull()); 1272 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BDefaultDecl)), 1273 FooVal.getChild(*BDefaultDecl)); 1274 EXPECT_THAT(FooVal.getChild(*BProtectedDecl), NotNull()); 1275 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BProtectedDecl)), 1276 FooVal.getChild(*BProtectedDecl)); 1277 EXPECT_THAT(FooVal.getChild(*BPrivateDecl), NotNull()); 1278 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BPrivateDecl)), 1279 FooVal.getChild(*BPrivateDecl)); 1280 }); 1281 } 1282 1283 static void derivedBaseMemberExpectations( 1284 const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1285 ASTContext &ASTCtx) { 1286 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1287 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1288 1289 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1290 ASSERT_THAT(FooDecl, NotNull()); 1291 1292 ASSERT_TRUE(FooDecl->getType()->isRecordType()); 1293 const FieldDecl *BarDecl = nullptr; 1294 for (const clang::CXXBaseSpecifier &Base : 1295 FooDecl->getType()->getAsCXXRecordDecl()->bases()) { 1296 QualType BaseType = Base.getType(); 1297 ASSERT_TRUE(BaseType->isStructureType()); 1298 1299 for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) { 1300 if (Field->getNameAsString() == "Bar") { 1301 BarDecl = Field; 1302 } else { 1303 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1304 } 1305 } 1306 } 1307 ASSERT_THAT(BarDecl, NotNull()); 1308 1309 const auto &FooLoc = 1310 *cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 1311 const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc)); 1312 EXPECT_THAT(FooVal.getChild(*BarDecl), NotNull()); 1313 EXPECT_EQ(Env.getValue(FooLoc.getChild(*BarDecl)), FooVal.getChild(*BarDecl)); 1314 } 1315 1316 TEST(TransferTest, DerivedBaseMemberStructDefault) { 1317 std::string Code = R"( 1318 struct A { 1319 int Bar; 1320 }; 1321 struct B : public A { 1322 }; 1323 1324 void target() { 1325 B Foo; 1326 (void)Foo.Bar; 1327 // [[p]] 1328 } 1329 )"; 1330 runDataflow(Code, derivedBaseMemberExpectations); 1331 } 1332 1333 TEST(TransferTest, DerivedBaseMemberPrivateFriend) { 1334 // Include an access to `Foo.Bar` to verify the analysis doesn't crash on that 1335 // access. 1336 std::string Code = R"( 1337 struct A { 1338 private: 1339 friend void target(); 1340 int Bar; 1341 }; 1342 struct B : public A { 1343 }; 1344 1345 void target() { 1346 B Foo; 1347 (void)Foo.Bar; 1348 // [[p]] 1349 } 1350 )"; 1351 runDataflow(Code, derivedBaseMemberExpectations); 1352 } 1353 1354 TEST(TransferTest, ClassMember) { 1355 std::string Code = R"( 1356 class A { 1357 public: 1358 int Bar; 1359 }; 1360 1361 void target(A Foo) { 1362 int Baz = Foo.Bar; 1363 // [[p]] 1364 } 1365 )"; 1366 runDataflow( 1367 Code, 1368 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1369 ASTContext &ASTCtx) { 1370 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1371 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1372 1373 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1374 ASSERT_THAT(FooDecl, NotNull()); 1375 1376 ASSERT_TRUE(FooDecl->getType()->isClassType()); 1377 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1378 1379 FieldDecl *BarDecl = nullptr; 1380 for (FieldDecl *Field : FooFields) { 1381 if (Field->getNameAsString() == "Bar") { 1382 BarDecl = Field; 1383 } else { 1384 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1385 } 1386 } 1387 ASSERT_THAT(BarDecl, NotNull()); 1388 1389 const auto *FooLoc = 1390 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 1391 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1392 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1393 1394 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1395 ASSERT_THAT(BazDecl, NotNull()); 1396 1397 EXPECT_EQ(Env.getValue(*BazDecl), BarVal); 1398 }); 1399 } 1400 1401 TEST(TransferTest, BaseClassInitializer) { 1402 using ast_matchers::cxxConstructorDecl; 1403 using ast_matchers::hasName; 1404 using ast_matchers::ofClass; 1405 1406 std::string Code = R"( 1407 class A { 1408 public: 1409 A(int I) : Bar(I) {} 1410 int Bar; 1411 }; 1412 1413 class B : public A { 1414 public: 1415 B(int I) : A(I) { 1416 (void)0; 1417 // [[p]] 1418 } 1419 }; 1420 )"; 1421 ASSERT_THAT_ERROR( 1422 checkDataflow<NoopAnalysis>( 1423 AnalysisInputs<NoopAnalysis>( 1424 Code, cxxConstructorDecl(ofClass(hasName("B"))), 1425 [](ASTContext &C, Environment &) { 1426 return NoopAnalysis(C, /*ApplyBuiltinTransfer=*/true); 1427 }) 1428 .withASTBuildArgs( 1429 {"-fsyntax-only", "-fno-delayed-template-parsing", 1430 "-std=" + std::string(LangStandard::getLangStandardForKind( 1431 LangStandard::lang_cxx17) 1432 .getName())}), 1433 /*VerifyResults=*/ 1434 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1435 const AnalysisOutputs &) { 1436 // Regression test to verify that base-class initializers do not 1437 // trigger an assertion. If we add support for such initializers in 1438 // the future, we can expand this test to check more specific 1439 // properties. 1440 EXPECT_THAT(Results.keys(), UnorderedElementsAre("p")); 1441 }), 1442 llvm::Succeeded()); 1443 } 1444 1445 TEST(TransferTest, ReferenceMember) { 1446 std::string Code = R"( 1447 struct A { 1448 int &Bar; 1449 }; 1450 1451 void target(A Foo) { 1452 int Baz = Foo.Bar; 1453 // [[p]] 1454 } 1455 )"; 1456 runDataflow( 1457 Code, 1458 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1459 ASTContext &ASTCtx) { 1460 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1461 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1462 1463 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1464 ASSERT_THAT(FooDecl, NotNull()); 1465 1466 ASSERT_TRUE(FooDecl->getType()->isStructureType()); 1467 auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields(); 1468 1469 FieldDecl *BarDecl = nullptr; 1470 for (FieldDecl *Field : FooFields) { 1471 if (Field->getNameAsString() == "Bar") { 1472 BarDecl = Field; 1473 } else { 1474 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1475 } 1476 } 1477 ASSERT_THAT(BarDecl, NotNull()); 1478 1479 const auto *FooLoc = 1480 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 1481 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1482 const auto *BarVal = cast<ReferenceValue>(FooVal->getChild(*BarDecl)); 1483 const auto *BarReferentVal = 1484 cast<IntegerValue>(Env.getValue(BarVal->getReferentLoc())); 1485 1486 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1487 ASSERT_THAT(BazDecl, NotNull()); 1488 1489 EXPECT_EQ(Env.getValue(*BazDecl), BarReferentVal); 1490 }); 1491 } 1492 1493 TEST(TransferTest, StructThisMember) { 1494 std::string Code = R"( 1495 struct A { 1496 int Bar; 1497 1498 struct B { 1499 int Baz; 1500 }; 1501 1502 B Qux; 1503 1504 void target() { 1505 int Foo = Bar; 1506 int Quux = Qux.Baz; 1507 // [[p]] 1508 } 1509 }; 1510 )"; 1511 runDataflow( 1512 Code, 1513 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1514 ASTContext &ASTCtx) { 1515 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1516 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1517 1518 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1519 Env.getThisPointeeStorageLocation()); 1520 ASSERT_THAT(ThisLoc, NotNull()); 1521 1522 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1523 ASSERT_THAT(BarDecl, NotNull()); 1524 1525 const auto *BarLoc = 1526 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1527 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1528 1529 const Value *BarVal = Env.getValue(*BarLoc); 1530 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1531 1532 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1533 ASSERT_THAT(FooDecl, NotNull()); 1534 EXPECT_EQ(Env.getValue(*FooDecl), BarVal); 1535 1536 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1537 ASSERT_THAT(QuxDecl, NotNull()); 1538 1539 ASSERT_TRUE(QuxDecl->getType()->isStructureType()); 1540 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1541 1542 FieldDecl *BazDecl = nullptr; 1543 for (FieldDecl *Field : QuxFields) { 1544 if (Field->getNameAsString() == "Baz") { 1545 BazDecl = Field; 1546 } else { 1547 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1548 } 1549 } 1550 ASSERT_THAT(BazDecl, NotNull()); 1551 1552 const auto *QuxLoc = 1553 cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl)); 1554 const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc)); 1555 ASSERT_THAT(QuxVal, NotNull()); 1556 1557 const auto *BazLoc = 1558 cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl)); 1559 const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl)); 1560 EXPECT_EQ(Env.getValue(*BazLoc), BazVal); 1561 1562 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1563 ASSERT_THAT(QuuxDecl, NotNull()); 1564 EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal); 1565 }); 1566 } 1567 1568 TEST(TransferTest, ClassThisMember) { 1569 std::string Code = R"( 1570 class A { 1571 int Bar; 1572 1573 class B { 1574 public: 1575 int Baz; 1576 }; 1577 1578 B Qux; 1579 1580 void target() { 1581 int Foo = Bar; 1582 int Quux = Qux.Baz; 1583 // [[p]] 1584 } 1585 }; 1586 )"; 1587 runDataflow( 1588 Code, 1589 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1590 ASTContext &ASTCtx) { 1591 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1592 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1593 1594 const auto *ThisLoc = 1595 cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation()); 1596 1597 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1598 ASSERT_THAT(BarDecl, NotNull()); 1599 1600 const auto *BarLoc = 1601 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1602 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1603 1604 const Value *BarVal = Env.getValue(*BarLoc); 1605 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1606 1607 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1608 ASSERT_THAT(FooDecl, NotNull()); 1609 EXPECT_EQ(Env.getValue(*FooDecl), BarVal); 1610 1611 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1612 ASSERT_THAT(QuxDecl, NotNull()); 1613 1614 ASSERT_TRUE(QuxDecl->getType()->isClassType()); 1615 auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields(); 1616 1617 FieldDecl *BazDecl = nullptr; 1618 for (FieldDecl *Field : QuxFields) { 1619 if (Field->getNameAsString() == "Baz") { 1620 BazDecl = Field; 1621 } else { 1622 FAIL() << "Unexpected field: " << Field->getNameAsString(); 1623 } 1624 } 1625 ASSERT_THAT(BazDecl, NotNull()); 1626 1627 const auto *QuxLoc = 1628 cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl)); 1629 const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc)); 1630 ASSERT_THAT(QuxVal, NotNull()); 1631 1632 const auto *BazLoc = 1633 cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl)); 1634 const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl)); 1635 EXPECT_EQ(Env.getValue(*BazLoc), BazVal); 1636 1637 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 1638 ASSERT_THAT(QuuxDecl, NotNull()); 1639 EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal); 1640 }); 1641 } 1642 1643 TEST(TransferTest, UnionThisMember) { 1644 std::string Code = R"( 1645 union A { 1646 int Foo; 1647 int Bar; 1648 1649 void target() { 1650 A a; 1651 // Mention the fields to ensure they're included in the analysis. 1652 (void)a.Foo; 1653 (void)a.Bar; 1654 // [[p]] 1655 } 1656 }; 1657 )"; 1658 runDataflow( 1659 Code, 1660 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1661 ASTContext &ASTCtx) { 1662 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1663 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1664 1665 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1666 Env.getThisPointeeStorageLocation()); 1667 ASSERT_THAT(ThisLoc, NotNull()); 1668 1669 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1670 ASSERT_THAT(FooDecl, NotNull()); 1671 1672 const auto *FooLoc = 1673 cast<ScalarStorageLocation>(&ThisLoc->getChild(*FooDecl)); 1674 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 1675 1676 const Value *FooVal = Env.getValue(*FooLoc); 1677 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 1678 1679 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1680 ASSERT_THAT(BarDecl, NotNull()); 1681 1682 const auto *BarLoc = 1683 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1684 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1685 1686 const Value *BarVal = Env.getValue(*BarLoc); 1687 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1688 }); 1689 } 1690 1691 TEST(TransferTest, StructThisInLambda) { 1692 std::string ThisCaptureCode = R"( 1693 struct A { 1694 void frob() { 1695 [this]() { 1696 int Foo = Bar; 1697 // [[p1]] 1698 }(); 1699 } 1700 1701 int Bar; 1702 }; 1703 )"; 1704 runDataflow( 1705 ThisCaptureCode, 1706 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1707 ASTContext &ASTCtx) { 1708 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1")); 1709 const Environment &Env = getEnvironmentAtAnnotation(Results, "p1"); 1710 1711 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1712 Env.getThisPointeeStorageLocation()); 1713 ASSERT_THAT(ThisLoc, NotNull()); 1714 1715 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1716 ASSERT_THAT(BarDecl, NotNull()); 1717 1718 const auto *BarLoc = 1719 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1720 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1721 1722 const Value *BarVal = Env.getValue(*BarLoc); 1723 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1724 1725 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1726 ASSERT_THAT(FooDecl, NotNull()); 1727 EXPECT_EQ(Env.getValue(*FooDecl), BarVal); 1728 }, 1729 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1730 1731 std::string RefCaptureDefaultCode = R"( 1732 struct A { 1733 void frob() { 1734 [&]() { 1735 int Foo = Bar; 1736 // [[p2]] 1737 }(); 1738 } 1739 1740 int Bar; 1741 }; 1742 )"; 1743 runDataflow( 1744 RefCaptureDefaultCode, 1745 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1746 ASTContext &ASTCtx) { 1747 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p2")); 1748 const Environment &Env = getEnvironmentAtAnnotation(Results, "p2"); 1749 1750 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1751 Env.getThisPointeeStorageLocation()); 1752 ASSERT_THAT(ThisLoc, NotNull()); 1753 1754 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1755 ASSERT_THAT(BarDecl, NotNull()); 1756 1757 const auto *BarLoc = 1758 cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl)); 1759 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 1760 1761 const Value *BarVal = Env.getValue(*BarLoc); 1762 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 1763 1764 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1765 ASSERT_THAT(FooDecl, NotNull()); 1766 EXPECT_EQ(Env.getValue(*FooDecl), BarVal); 1767 }, 1768 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1769 1770 std::string FreeFunctionLambdaCode = R"( 1771 void foo() { 1772 int Bar; 1773 [&]() { 1774 int Foo = Bar; 1775 // [[p3]] 1776 }(); 1777 } 1778 )"; 1779 runDataflow( 1780 FreeFunctionLambdaCode, 1781 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1782 ASTContext &ASTCtx) { 1783 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p3")); 1784 const Environment &Env = getEnvironmentAtAnnotation(Results, "p3"); 1785 1786 EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull()); 1787 }, 1788 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()"); 1789 } 1790 1791 TEST(TransferTest, ConstructorInitializer) { 1792 std::string Code = R"( 1793 struct target { 1794 int Bar; 1795 1796 target(int Foo) : Bar(Foo) { 1797 int Qux = Bar; 1798 // [[p]] 1799 } 1800 }; 1801 )"; 1802 runDataflow( 1803 Code, 1804 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1805 ASTContext &ASTCtx) { 1806 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1807 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1808 1809 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1810 Env.getThisPointeeStorageLocation()); 1811 ASSERT_THAT(ThisLoc, NotNull()); 1812 1813 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1814 ASSERT_THAT(FooDecl, NotNull()); 1815 1816 const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl)); 1817 1818 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1819 ASSERT_THAT(QuxDecl, NotNull()); 1820 EXPECT_EQ(Env.getValue(*QuxDecl), FooVal); 1821 }); 1822 } 1823 1824 TEST(TransferTest, DefaultInitializer) { 1825 std::string Code = R"( 1826 struct target { 1827 int Bar; 1828 int Baz = Bar; 1829 1830 target(int Foo) : Bar(Foo) { 1831 int Qux = Baz; 1832 // [[p]] 1833 } 1834 }; 1835 )"; 1836 runDataflow( 1837 Code, 1838 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1839 ASTContext &ASTCtx) { 1840 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1841 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1842 1843 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1844 Env.getThisPointeeStorageLocation()); 1845 ASSERT_THAT(ThisLoc, NotNull()); 1846 1847 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1848 ASSERT_THAT(FooDecl, NotNull()); 1849 1850 const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl)); 1851 1852 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1853 ASSERT_THAT(QuxDecl, NotNull()); 1854 EXPECT_EQ(Env.getValue(*QuxDecl), FooVal); 1855 }); 1856 } 1857 1858 TEST(TransferTest, DefaultInitializerReference) { 1859 std::string Code = R"( 1860 struct target { 1861 int &Bar; 1862 int &Baz = Bar; 1863 1864 target(int &Foo) : Bar(Foo) { 1865 int &Qux = Baz; 1866 // [[p]] 1867 } 1868 }; 1869 )"; 1870 runDataflow( 1871 Code, 1872 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1873 ASTContext &ASTCtx) { 1874 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1875 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1876 1877 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>( 1878 Env.getThisPointeeStorageLocation()); 1879 ASSERT_THAT(ThisLoc, NotNull()); 1880 1881 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1882 ASSERT_THAT(FooDecl, NotNull()); 1883 1884 const auto *FooLoc = Env.getStorageLocation(*FooDecl); 1885 1886 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 1887 ASSERT_THAT(QuxDecl, NotNull()); 1888 1889 const auto *QuxLoc = Env.getStorageLocation(*QuxDecl); 1890 EXPECT_EQ(QuxLoc, FooLoc); 1891 }); 1892 } 1893 1894 TEST(TransferTest, TemporaryObject) { 1895 std::string Code = R"( 1896 struct A { 1897 int Bar; 1898 }; 1899 1900 void target() { 1901 A Foo = A(); 1902 (void)Foo.Bar; 1903 // [[p]] 1904 } 1905 )"; 1906 runDataflow( 1907 Code, 1908 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1909 ASTContext &ASTCtx) { 1910 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1911 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1912 1913 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1914 ASSERT_THAT(FooDecl, NotNull()); 1915 1916 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1917 ASSERT_THAT(BarDecl, NotNull()); 1918 1919 const auto *FooLoc = 1920 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 1921 const auto *BarLoc = 1922 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1923 1924 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1925 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1926 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1927 }); 1928 } 1929 1930 TEST(TransferTest, ElidableConstructor) { 1931 // This test is effectively the same as TransferTest.TemporaryObject, but 1932 // the code is compiled as C++ 14. 1933 std::string Code = R"( 1934 struct A { 1935 int Bar; 1936 }; 1937 1938 void target() { 1939 A Foo = A(); 1940 (void)Foo.Bar; 1941 // [[p]] 1942 } 1943 )"; 1944 runDataflow( 1945 Code, 1946 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1947 ASTContext &ASTCtx) { 1948 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 1949 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 1950 1951 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1952 ASSERT_THAT(FooDecl, NotNull()); 1953 1954 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1955 ASSERT_THAT(BarDecl, NotNull()); 1956 1957 const auto *FooLoc = 1958 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 1959 const auto *BarLoc = 1960 cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl)); 1961 1962 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 1963 const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl)); 1964 EXPECT_EQ(Env.getValue(*BarLoc), BarVal); 1965 }, 1966 LangStandard::lang_cxx14); 1967 } 1968 1969 TEST(TransferTest, AssignmentOperator) { 1970 std::string Code = R"( 1971 struct A { 1972 int Baz; 1973 }; 1974 1975 void target() { 1976 A Foo; 1977 A Bar; 1978 (void)Foo.Baz; 1979 // [[p1]] 1980 Foo = Bar; 1981 // [[p2]] 1982 } 1983 )"; 1984 runDataflow( 1985 Code, 1986 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 1987 ASTContext &ASTCtx) { 1988 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 1989 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 1990 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 1991 1992 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 1993 ASSERT_THAT(FooDecl, NotNull()); 1994 1995 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 1996 ASSERT_THAT(BarDecl, NotNull()); 1997 1998 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 1999 ASSERT_THAT(BazDecl, NotNull()); 2000 2001 const auto *FooLoc1 = 2002 cast<AggregateStorageLocation>(Env1.getStorageLocation(*FooDecl)); 2003 const auto *BarLoc1 = 2004 cast<AggregateStorageLocation>(Env1.getStorageLocation(*BarDecl)); 2005 2006 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 2007 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 2008 EXPECT_NE(FooVal1, BarVal1); 2009 2010 const auto *FooBazVal1 = 2011 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 2012 const auto *BarBazVal1 = 2013 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 2014 EXPECT_NE(FooBazVal1, BarBazVal1); 2015 2016 const auto *FooLoc2 = 2017 cast<AggregateStorageLocation>(Env2.getStorageLocation(*FooDecl)); 2018 const auto *BarLoc2 = 2019 cast<AggregateStorageLocation>(Env2.getStorageLocation(*BarDecl)); 2020 2021 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 2022 const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2)); 2023 EXPECT_EQ(FooVal2, BarVal2); 2024 2025 const auto *FooBazVal2 = 2026 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 2027 const auto *BarBazVal2 = 2028 cast<IntegerValue>(Env2.getValue(BarLoc1->getChild(*BazDecl))); 2029 EXPECT_EQ(FooBazVal2, BarBazVal2); 2030 }); 2031 } 2032 2033 TEST(TransferTest, CopyConstructor) { 2034 std::string Code = R"( 2035 struct A { 2036 int Baz; 2037 }; 2038 2039 void target() { 2040 A Foo; 2041 (void)Foo.Baz; 2042 A Bar = Foo; 2043 // [[p]] 2044 } 2045 )"; 2046 runDataflow( 2047 Code, 2048 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2049 ASTContext &ASTCtx) { 2050 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2051 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2052 2053 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2054 ASSERT_THAT(FooDecl, NotNull()); 2055 2056 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2057 ASSERT_THAT(BarDecl, NotNull()); 2058 2059 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2060 ASSERT_THAT(BazDecl, NotNull()); 2061 2062 const auto *FooLoc = 2063 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 2064 const auto *BarLoc = 2065 cast<AggregateStorageLocation>(Env.getStorageLocation(*BarDecl)); 2066 2067 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 2068 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 2069 EXPECT_EQ(FooVal, BarVal); 2070 2071 const auto *FooBazVal = 2072 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 2073 const auto *BarBazVal = 2074 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 2075 EXPECT_EQ(FooBazVal, BarBazVal); 2076 }); 2077 } 2078 2079 TEST(TransferTest, CopyConstructorWithDefaultArgument) { 2080 std::string Code = R"( 2081 struct A { 2082 int Baz; 2083 A() = default; 2084 A(const A& a, bool def = true) { Baz = a.Baz; } 2085 }; 2086 2087 void target() { 2088 A Foo; 2089 (void)Foo.Baz; 2090 A Bar = Foo; 2091 // [[p]] 2092 } 2093 )"; 2094 runDataflow( 2095 Code, 2096 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2097 ASTContext &ASTCtx) { 2098 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2099 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2100 2101 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2102 ASSERT_THAT(FooDecl, NotNull()); 2103 2104 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2105 ASSERT_THAT(BarDecl, NotNull()); 2106 2107 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2108 ASSERT_THAT(BazDecl, NotNull()); 2109 2110 const auto *FooLoc = 2111 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 2112 const auto *BarLoc = 2113 cast<AggregateStorageLocation>(Env.getStorageLocation(*BarDecl)); 2114 2115 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 2116 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 2117 EXPECT_EQ(FooVal, BarVal); 2118 2119 const auto *FooBazVal = 2120 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 2121 const auto *BarBazVal = 2122 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 2123 EXPECT_EQ(FooBazVal, BarBazVal); 2124 }); 2125 } 2126 2127 TEST(TransferTest, CopyConstructorWithParens) { 2128 std::string Code = R"( 2129 struct A { 2130 int Baz; 2131 }; 2132 2133 void target() { 2134 A Foo; 2135 (void)Foo.Baz; 2136 A Bar((A(Foo))); 2137 // [[p]] 2138 } 2139 )"; 2140 runDataflow( 2141 Code, 2142 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2143 ASTContext &ASTCtx) { 2144 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2145 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2146 2147 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2148 ASSERT_THAT(FooDecl, NotNull()); 2149 2150 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2151 ASSERT_THAT(BarDecl, NotNull()); 2152 2153 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2154 ASSERT_THAT(BazDecl, NotNull()); 2155 2156 const auto *FooLoc = 2157 cast<AggregateStorageLocation>(Env.getStorageLocation(*FooDecl)); 2158 const auto *BarLoc = 2159 cast<AggregateStorageLocation>(Env.getStorageLocation(*BarDecl)); 2160 2161 const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc)); 2162 const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc)); 2163 EXPECT_EQ(FooVal, BarVal); 2164 2165 const auto *FooBazVal = 2166 cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl))); 2167 const auto *BarBazVal = 2168 cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl))); 2169 EXPECT_EQ(FooBazVal, BarBazVal); 2170 }); 2171 } 2172 2173 TEST(TransferTest, MoveConstructor) { 2174 std::string Code = R"( 2175 namespace std { 2176 2177 template <typename T> struct remove_reference { using type = T; }; 2178 template <typename T> struct remove_reference<T&> { using type = T; }; 2179 template <typename T> struct remove_reference<T&&> { using type = T; }; 2180 2181 template <typename T> 2182 using remove_reference_t = typename remove_reference<T>::type; 2183 2184 template <typename T> 2185 std::remove_reference_t<T>&& move(T&& x); 2186 2187 } // namespace std 2188 2189 struct A { 2190 int Baz; 2191 }; 2192 2193 void target() { 2194 A Foo; 2195 A Bar; 2196 (void)Foo.Baz; 2197 // [[p1]] 2198 Foo = std::move(Bar); 2199 // [[p2]] 2200 } 2201 )"; 2202 runDataflow( 2203 Code, 2204 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2205 ASTContext &ASTCtx) { 2206 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 2207 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 2208 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 2209 2210 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2211 ASSERT_THAT(FooDecl, NotNull()); 2212 2213 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2214 ASSERT_THAT(BarDecl, NotNull()); 2215 2216 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2217 ASSERT_THAT(BazDecl, NotNull()); 2218 2219 const auto *FooLoc1 = 2220 cast<AggregateStorageLocation>(Env1.getStorageLocation(*FooDecl)); 2221 const auto *BarLoc1 = 2222 cast<AggregateStorageLocation>(Env1.getStorageLocation(*BarDecl)); 2223 2224 const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1)); 2225 const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1)); 2226 EXPECT_NE(FooVal1, BarVal1); 2227 2228 const auto *FooBazVal1 = 2229 cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl))); 2230 const auto *BarBazVal1 = 2231 cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl))); 2232 EXPECT_NE(FooBazVal1, BarBazVal1); 2233 2234 const auto *FooLoc2 = 2235 cast<AggregateStorageLocation>(Env2.getStorageLocation(*FooDecl)); 2236 const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2)); 2237 EXPECT_EQ(FooVal2, BarVal1); 2238 2239 const auto *FooBazVal2 = 2240 cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl))); 2241 EXPECT_EQ(FooBazVal2, BarBazVal1); 2242 }); 2243 } 2244 2245 TEST(TransferTest, BindTemporary) { 2246 std::string Code = R"( 2247 struct A { 2248 virtual ~A() = default; 2249 2250 int Baz; 2251 }; 2252 2253 void target(A Foo) { 2254 int Bar = A(Foo).Baz; 2255 // [[p]] 2256 } 2257 )"; 2258 runDataflow( 2259 Code, 2260 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2261 ASTContext &ASTCtx) { 2262 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2263 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2264 2265 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2266 ASSERT_THAT(FooDecl, NotNull()); 2267 2268 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2269 ASSERT_THAT(BarDecl, NotNull()); 2270 2271 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2272 ASSERT_THAT(BazDecl, NotNull()); 2273 2274 const auto &FooVal = *cast<StructValue>(Env.getValue(*FooDecl)); 2275 const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 2276 EXPECT_EQ(BarVal, FooVal.getChild(*BazDecl)); 2277 }); 2278 } 2279 2280 TEST(TransferTest, StaticCast) { 2281 std::string Code = R"( 2282 void target(int Foo) { 2283 int Bar = static_cast<int>(Foo); 2284 // [[p]] 2285 } 2286 )"; 2287 runDataflow( 2288 Code, 2289 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2290 ASTContext &ASTCtx) { 2291 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2292 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2293 2294 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2295 ASSERT_THAT(FooDecl, NotNull()); 2296 2297 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2298 ASSERT_THAT(BarDecl, NotNull()); 2299 2300 const auto *FooVal = Env.getValue(*FooDecl); 2301 const auto *BarVal = Env.getValue(*BarDecl); 2302 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2303 EXPECT_TRUE(isa<IntegerValue>(BarVal)); 2304 EXPECT_EQ(FooVal, BarVal); 2305 }); 2306 } 2307 2308 TEST(TransferTest, IntegralCast) { 2309 std::string Code = R"( 2310 void target(int Foo) { 2311 long Bar = Foo; 2312 // [[p]] 2313 } 2314 )"; 2315 runDataflow( 2316 Code, 2317 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2318 ASTContext &ASTCtx) { 2319 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2320 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2321 2322 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2323 ASSERT_THAT(FooDecl, NotNull()); 2324 2325 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2326 ASSERT_THAT(BarDecl, NotNull()); 2327 2328 const auto *FooVal = Env.getValue(*FooDecl); 2329 const auto *BarVal = Env.getValue(*BarDecl); 2330 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2331 EXPECT_TRUE(isa<IntegerValue>(BarVal)); 2332 EXPECT_EQ(FooVal, BarVal); 2333 }); 2334 } 2335 2336 TEST(TransferTest, IntegraltoBooleanCast) { 2337 std::string Code = R"( 2338 void target(int Foo) { 2339 bool Bar = Foo; 2340 // [[p]] 2341 } 2342 )"; 2343 runDataflow( 2344 Code, 2345 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2346 ASTContext &ASTCtx) { 2347 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2348 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2349 2350 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2351 ASSERT_THAT(FooDecl, NotNull()); 2352 2353 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2354 ASSERT_THAT(BarDecl, NotNull()); 2355 2356 const auto *FooVal = Env.getValue(*FooDecl); 2357 const auto *BarVal = Env.getValue(*BarDecl); 2358 EXPECT_TRUE(isa<IntegerValue>(FooVal)); 2359 EXPECT_TRUE(isa<BoolValue>(BarVal)); 2360 }); 2361 } 2362 2363 TEST(TransferTest, IntegralToBooleanCastFromBool) { 2364 std::string Code = R"( 2365 void target(bool Foo) { 2366 int Zab = Foo; 2367 bool Bar = Zab; 2368 // [[p]] 2369 } 2370 )"; 2371 runDataflow( 2372 Code, 2373 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2374 ASTContext &ASTCtx) { 2375 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2376 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2377 2378 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2379 ASSERT_THAT(FooDecl, NotNull()); 2380 2381 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2382 ASSERT_THAT(BarDecl, NotNull()); 2383 2384 const auto *FooVal = Env.getValue(*FooDecl); 2385 const auto *BarVal = Env.getValue(*BarDecl); 2386 EXPECT_TRUE(isa<BoolValue>(FooVal)); 2387 EXPECT_TRUE(isa<BoolValue>(BarVal)); 2388 EXPECT_EQ(FooVal, BarVal); 2389 }); 2390 } 2391 2392 TEST(TransferTest, NullToPointerCast) { 2393 std::string Code = R"( 2394 using my_nullptr_t = decltype(nullptr); 2395 struct Baz {}; 2396 void target() { 2397 int *FooX = nullptr; 2398 int *FooY = nullptr; 2399 bool **Bar = nullptr; 2400 Baz *Baz = nullptr; 2401 my_nullptr_t Null = 0; 2402 // [[p]] 2403 } 2404 )"; 2405 runDataflow( 2406 Code, 2407 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2408 ASTContext &ASTCtx) { 2409 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2410 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2411 2412 const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX"); 2413 ASSERT_THAT(FooXDecl, NotNull()); 2414 2415 const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY"); 2416 ASSERT_THAT(FooYDecl, NotNull()); 2417 2418 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2419 ASSERT_THAT(BarDecl, NotNull()); 2420 2421 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2422 ASSERT_THAT(BazDecl, NotNull()); 2423 2424 const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null"); 2425 ASSERT_THAT(NullDecl, NotNull()); 2426 2427 const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl)); 2428 const auto *FooYVal = cast<PointerValue>(Env.getValue(*FooYDecl)); 2429 const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl)); 2430 const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl)); 2431 const auto *NullVal = cast<PointerValue>(Env.getValue(*NullDecl)); 2432 2433 EXPECT_EQ(FooXVal, FooYVal); 2434 EXPECT_NE(FooXVal, BarVal); 2435 EXPECT_NE(FooXVal, BazVal); 2436 EXPECT_NE(BarVal, BazVal); 2437 2438 const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc(); 2439 EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc)); 2440 EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull()); 2441 2442 const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc(); 2443 EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc)); 2444 EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull()); 2445 2446 const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc(); 2447 EXPECT_TRUE(isa<AggregateStorageLocation>(BazPointeeLoc)); 2448 EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull()); 2449 2450 const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc(); 2451 EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc)); 2452 EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull()); 2453 }); 2454 } 2455 2456 TEST(TransferTest, NullToMemberPointerCast) { 2457 std::string Code = R"( 2458 struct Foo {}; 2459 void target(Foo *Foo) { 2460 int Foo::*MemberPointer = nullptr; 2461 // [[p]] 2462 } 2463 )"; 2464 runDataflow( 2465 Code, 2466 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2467 ASTContext &ASTCtx) { 2468 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2469 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2470 2471 const ValueDecl *MemberPointerDecl = 2472 findValueDecl(ASTCtx, "MemberPointer"); 2473 ASSERT_THAT(MemberPointerDecl, NotNull()); 2474 2475 const auto *MemberPointerVal = 2476 cast<PointerValue>(Env.getValue(*MemberPointerDecl)); 2477 2478 const StorageLocation &MemberLoc = MemberPointerVal->getPointeeLoc(); 2479 EXPECT_THAT(Env.getValue(MemberLoc), IsNull()); 2480 }); 2481 } 2482 2483 TEST(TransferTest, AddrOfValue) { 2484 std::string Code = R"( 2485 void target() { 2486 int Foo; 2487 int *Bar = &Foo; 2488 // [[p]] 2489 } 2490 )"; 2491 runDataflow( 2492 Code, 2493 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2494 ASTContext &ASTCtx) { 2495 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2496 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2497 2498 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2499 ASSERT_THAT(FooDecl, NotNull()); 2500 2501 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2502 ASSERT_THAT(BarDecl, NotNull()); 2503 2504 const auto *FooLoc = 2505 cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl)); 2506 const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl)); 2507 EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc); 2508 }); 2509 } 2510 2511 TEST(TransferTest, AddrOfReference) { 2512 std::string Code = R"( 2513 void target(int *Foo) { 2514 int *Bar = &(*Foo); 2515 // [[p]] 2516 } 2517 )"; 2518 runDataflow( 2519 Code, 2520 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2521 ASTContext &ASTCtx) { 2522 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2523 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2524 2525 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2526 ASSERT_THAT(FooDecl, NotNull()); 2527 2528 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2529 ASSERT_THAT(BarDecl, NotNull()); 2530 2531 const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl)); 2532 const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl)); 2533 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc()); 2534 }); 2535 } 2536 2537 TEST(TransferTest, DerefDependentPtr) { 2538 std::string Code = R"( 2539 template <typename T> 2540 void target(T *Foo) { 2541 T &Bar = *Foo; 2542 /*[[p]]*/ 2543 } 2544 )"; 2545 runDataflow( 2546 Code, 2547 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2548 ASTContext &ASTCtx) { 2549 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2550 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2551 2552 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2553 ASSERT_THAT(FooDecl, NotNull()); 2554 2555 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2556 ASSERT_THAT(BarDecl, NotNull()); 2557 2558 const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl)); 2559 const auto *BarLoc = Env.getStorageLocation(*BarDecl); 2560 EXPECT_EQ(BarLoc, &FooVal->getPointeeLoc()); 2561 }); 2562 } 2563 2564 TEST(TransferTest, VarDeclInitAssignConditionalOperator) { 2565 std::string Code = R"( 2566 struct A {}; 2567 2568 void target(A Foo, A Bar, bool Cond) { 2569 A Baz = Cond ? Foo : Bar; 2570 /*[[p]]*/ 2571 } 2572 )"; 2573 runDataflow( 2574 Code, 2575 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2576 ASTContext &ASTCtx) { 2577 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2578 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2579 2580 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2581 ASSERT_THAT(FooDecl, NotNull()); 2582 2583 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2584 ASSERT_THAT(BarDecl, NotNull()); 2585 2586 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2587 ASSERT_THAT(BazDecl, NotNull()); 2588 2589 const auto *FooVal = cast<StructValue>(Env.getValue(*FooDecl)); 2590 const auto *BarVal = cast<StructValue>(Env.getValue(*BarDecl)); 2591 2592 const auto *BazVal = dyn_cast<StructValue>(Env.getValue(*BazDecl)); 2593 ASSERT_THAT(BazVal, NotNull()); 2594 2595 EXPECT_NE(BazVal, FooVal); 2596 EXPECT_NE(BazVal, BarVal); 2597 }); 2598 } 2599 2600 TEST(TransferTest, VarDeclInDoWhile) { 2601 std::string Code = R"( 2602 void target(int *Foo) { 2603 do { 2604 int Bar = *Foo; 2605 // [[in_loop]] 2606 } while (false); 2607 (void)0; 2608 // [[after_loop]] 2609 } 2610 )"; 2611 runDataflow( 2612 Code, 2613 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2614 ASTContext &ASTCtx) { 2615 const Environment &EnvInLoop = 2616 getEnvironmentAtAnnotation(Results, "in_loop"); 2617 const Environment &EnvAfterLoop = 2618 getEnvironmentAtAnnotation(Results, "after_loop"); 2619 2620 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2621 ASSERT_THAT(FooDecl, NotNull()); 2622 2623 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2624 ASSERT_THAT(BarDecl, NotNull()); 2625 2626 const auto *FooVal = 2627 cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl)); 2628 const auto *FooPointeeVal = 2629 cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc())); 2630 2631 const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl)); 2632 EXPECT_EQ(BarVal, FooPointeeVal); 2633 2634 // FIXME: This assertion documents current behavior, but we would prefer 2635 // declarations to be removed from the environment when their lifetime 2636 // ends. Once this is the case, change this assertion accordingly. 2637 ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), BarVal); 2638 }); 2639 } 2640 2641 TEST(TransferTest, UnreachableAfterWhileTrue) { 2642 std::string Code = R"( 2643 void target() { 2644 while (true) {} 2645 (void)0; 2646 /*[[p]]*/ 2647 } 2648 )"; 2649 runDataflow( 2650 Code, 2651 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2652 ASTContext &ASTCtx) { 2653 // The node after the while-true is pruned because it is trivially 2654 // known to be unreachable. 2655 ASSERT_TRUE(Results.empty()); 2656 }); 2657 } 2658 2659 TEST(TransferTest, AggregateInitialization) { 2660 std::string BracesCode = R"( 2661 struct A { 2662 int Foo; 2663 }; 2664 2665 struct B { 2666 int Bar; 2667 A Baz; 2668 int Qux; 2669 }; 2670 2671 void target(int BarArg, int FooArg, int QuxArg) { 2672 B Quux{BarArg, {FooArg}, QuxArg}; 2673 /*[[p]]*/ 2674 } 2675 )"; 2676 std::string BraceEllisionCode = R"( 2677 struct A { 2678 int Foo; 2679 }; 2680 2681 struct B { 2682 int Bar; 2683 A Baz; 2684 int Qux; 2685 }; 2686 2687 void target(int BarArg, int FooArg, int QuxArg) { 2688 B Quux = {BarArg, FooArg, QuxArg}; 2689 /*[[p]]*/ 2690 } 2691 )"; 2692 for (const std::string &Code : {BracesCode, BraceEllisionCode}) { 2693 runDataflow( 2694 Code, 2695 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2696 ASTContext &ASTCtx) { 2697 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2698 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2699 2700 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2701 ASSERT_THAT(FooDecl, NotNull()); 2702 2703 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2704 ASSERT_THAT(BarDecl, NotNull()); 2705 2706 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2707 ASSERT_THAT(BazDecl, NotNull()); 2708 2709 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2710 ASSERT_THAT(QuxDecl, NotNull()); 2711 2712 const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg"); 2713 ASSERT_THAT(FooArgDecl, NotNull()); 2714 2715 const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg"); 2716 ASSERT_THAT(BarArgDecl, NotNull()); 2717 2718 const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg"); 2719 ASSERT_THAT(QuxArgDecl, NotNull()); 2720 2721 const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux"); 2722 ASSERT_THAT(QuuxDecl, NotNull()); 2723 2724 const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl)); 2725 const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl)); 2726 const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl)); 2727 2728 const auto *QuuxVal = cast<StructValue>(Env.getValue(*QuuxDecl)); 2729 ASSERT_THAT(QuuxVal, NotNull()); 2730 2731 const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl)); 2732 ASSERT_THAT(BazVal, NotNull()); 2733 2734 EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal); 2735 EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal); 2736 EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal); 2737 }); 2738 } 2739 } 2740 2741 TEST(TransferTest, AssignToUnionMember) { 2742 std::string Code = R"( 2743 union A { 2744 int Foo; 2745 }; 2746 2747 void target(int Bar) { 2748 A Baz; 2749 Baz.Foo = Bar; 2750 // [[p]] 2751 } 2752 )"; 2753 runDataflow( 2754 Code, 2755 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2756 ASTContext &ASTCtx) { 2757 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2758 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2759 2760 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2761 ASSERT_THAT(BazDecl, NotNull()); 2762 ASSERT_TRUE(BazDecl->getType()->isUnionType()); 2763 2764 auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields(); 2765 FieldDecl *FooDecl = nullptr; 2766 for (FieldDecl *Field : BazFields) { 2767 if (Field->getNameAsString() == "Foo") { 2768 FooDecl = Field; 2769 } else { 2770 FAIL() << "Unexpected field: " << Field->getNameAsString(); 2771 } 2772 } 2773 ASSERT_THAT(FooDecl, NotNull()); 2774 2775 const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>( 2776 Env.getStorageLocation(*BazDecl)); 2777 ASSERT_THAT(BazLoc, NotNull()); 2778 ASSERT_THAT(Env.getValue(*BazLoc), NotNull()); 2779 2780 const auto *BazVal = cast<StructValue>(Env.getValue(*BazLoc)); 2781 const auto *FooValFromBazVal = cast<IntegerValue>(BazVal->getChild(*FooDecl)); 2782 const auto *FooValFromBazLoc = cast<IntegerValue>(Env.getValue(BazLoc->getChild(*FooDecl))); 2783 EXPECT_EQ(FooValFromBazLoc, FooValFromBazVal); 2784 2785 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2786 ASSERT_THAT(BarDecl, NotNull()); 2787 const auto *BarLoc = Env.getStorageLocation(*BarDecl); 2788 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 2789 2790 EXPECT_EQ(Env.getValue(*BarLoc), FooValFromBazVal); 2791 EXPECT_EQ(Env.getValue(*BarLoc), FooValFromBazLoc); 2792 }); 2793 } 2794 2795 TEST(TransferTest, AssignFromBoolLiteral) { 2796 std::string Code = R"( 2797 void target() { 2798 bool Foo = true; 2799 bool Bar = false; 2800 // [[p]] 2801 } 2802 )"; 2803 runDataflow( 2804 Code, 2805 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2806 ASTContext &ASTCtx) { 2807 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2808 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2809 2810 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2811 ASSERT_THAT(FooDecl, NotNull()); 2812 2813 const auto *FooVal = 2814 dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl)); 2815 ASSERT_THAT(FooVal, NotNull()); 2816 2817 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2818 ASSERT_THAT(BarDecl, NotNull()); 2819 2820 const auto *BarVal = 2821 dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*BarDecl)); 2822 ASSERT_THAT(BarVal, NotNull()); 2823 2824 EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true)); 2825 EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false)); 2826 }); 2827 } 2828 2829 TEST(TransferTest, AssignFromCompositeBoolExpression) { 2830 { 2831 std::string Code = R"( 2832 void target(bool Foo, bool Bar, bool Qux) { 2833 bool Baz = (Foo) && (Bar || Qux); 2834 // [[p]] 2835 } 2836 )"; 2837 runDataflow( 2838 Code, 2839 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2840 ASTContext &ASTCtx) { 2841 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2842 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2843 2844 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2845 ASSERT_THAT(FooDecl, NotNull()); 2846 2847 const auto *FooVal = 2848 dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl)); 2849 ASSERT_THAT(FooVal, NotNull()); 2850 2851 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2852 ASSERT_THAT(BarDecl, NotNull()); 2853 2854 const auto *BarVal = 2855 dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl)); 2856 ASSERT_THAT(BarVal, NotNull()); 2857 2858 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2859 ASSERT_THAT(QuxDecl, NotNull()); 2860 2861 const auto *QuxVal = 2862 dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl)); 2863 ASSERT_THAT(QuxVal, NotNull()); 2864 2865 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2866 ASSERT_THAT(BazDecl, NotNull()); 2867 2868 const auto *BazVal = 2869 dyn_cast_or_null<ConjunctionValue>(Env.getValue(*BazDecl)); 2870 ASSERT_THAT(BazVal, NotNull()); 2871 EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal); 2872 2873 const auto *BazRightSubValVal = 2874 cast<DisjunctionValue>(&BazVal->getRightSubValue()); 2875 EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal); 2876 EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal); 2877 }); 2878 } 2879 2880 { 2881 std::string Code = R"( 2882 void target(bool Foo, bool Bar, bool Qux) { 2883 bool Baz = (Foo && Qux) || (Bar); 2884 // [[p]] 2885 } 2886 )"; 2887 runDataflow( 2888 Code, 2889 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2890 ASTContext &ASTCtx) { 2891 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2892 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2893 2894 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2895 ASSERT_THAT(FooDecl, NotNull()); 2896 2897 const auto *FooVal = 2898 dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl)); 2899 ASSERT_THAT(FooVal, NotNull()); 2900 2901 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 2902 ASSERT_THAT(BarDecl, NotNull()); 2903 2904 const auto *BarVal = 2905 dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl)); 2906 ASSERT_THAT(BarVal, NotNull()); 2907 2908 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 2909 ASSERT_THAT(QuxDecl, NotNull()); 2910 2911 const auto *QuxVal = 2912 dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl)); 2913 ASSERT_THAT(QuxVal, NotNull()); 2914 2915 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 2916 ASSERT_THAT(BazDecl, NotNull()); 2917 2918 const auto *BazVal = 2919 dyn_cast_or_null<DisjunctionValue>(Env.getValue(*BazDecl)); 2920 ASSERT_THAT(BazVal, NotNull()); 2921 2922 const auto *BazLeftSubValVal = 2923 cast<ConjunctionValue>(&BazVal->getLeftSubValue()); 2924 EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal); 2925 EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal); 2926 2927 EXPECT_EQ(&BazVal->getRightSubValue(), BarVal); 2928 }); 2929 } 2930 2931 { 2932 std::string Code = R"( 2933 void target(bool A, bool B, bool C, bool D) { 2934 bool Foo = ((A && B) && C) && D; 2935 // [[p]] 2936 } 2937 )"; 2938 runDataflow( 2939 Code, 2940 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2941 ASTContext &ASTCtx) { 2942 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 2943 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 2944 2945 const ValueDecl *ADecl = findValueDecl(ASTCtx, "A"); 2946 ASSERT_THAT(ADecl, NotNull()); 2947 2948 const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl)); 2949 ASSERT_THAT(AVal, NotNull()); 2950 2951 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 2952 ASSERT_THAT(BDecl, NotNull()); 2953 2954 const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl)); 2955 ASSERT_THAT(BVal, NotNull()); 2956 2957 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 2958 ASSERT_THAT(CDecl, NotNull()); 2959 2960 const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl)); 2961 ASSERT_THAT(CVal, NotNull()); 2962 2963 const ValueDecl *DDecl = findValueDecl(ASTCtx, "D"); 2964 ASSERT_THAT(DDecl, NotNull()); 2965 2966 const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl)); 2967 ASSERT_THAT(DVal, NotNull()); 2968 2969 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 2970 ASSERT_THAT(FooDecl, NotNull()); 2971 2972 const auto *FooVal = 2973 dyn_cast_or_null<ConjunctionValue>(Env.getValue(*FooDecl)); 2974 ASSERT_THAT(FooVal, NotNull()); 2975 2976 const auto &FooLeftSubVal = 2977 cast<ConjunctionValue>(FooVal->getLeftSubValue()); 2978 const auto &FooLeftLeftSubVal = 2979 cast<ConjunctionValue>(FooLeftSubVal.getLeftSubValue()); 2980 EXPECT_EQ(&FooLeftLeftSubVal.getLeftSubValue(), AVal); 2981 EXPECT_EQ(&FooLeftLeftSubVal.getRightSubValue(), BVal); 2982 EXPECT_EQ(&FooLeftSubVal.getRightSubValue(), CVal); 2983 EXPECT_EQ(&FooVal->getRightSubValue(), DVal); 2984 }); 2985 } 2986 } 2987 2988 TEST(TransferTest, AssignFromBoolNegation) { 2989 std::string Code = R"( 2990 void target() { 2991 bool Foo = true; 2992 bool Bar = !(Foo); 2993 // [[p]] 2994 } 2995 )"; 2996 runDataflow( 2997 Code, 2998 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 2999 ASTContext &ASTCtx) { 3000 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3001 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3002 3003 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3004 ASSERT_THAT(FooDecl, NotNull()); 3005 3006 const auto *FooVal = 3007 dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl)); 3008 ASSERT_THAT(FooVal, NotNull()); 3009 3010 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3011 ASSERT_THAT(BarDecl, NotNull()); 3012 3013 const auto *BarVal = 3014 dyn_cast_or_null<NegationValue>(Env.getValue(*BarDecl)); 3015 ASSERT_THAT(BarVal, NotNull()); 3016 3017 EXPECT_EQ(&BarVal->getSubVal(), FooVal); 3018 }); 3019 } 3020 3021 TEST(TransferTest, BuiltinExpect) { 3022 std::string Code = R"( 3023 void target(long Foo) { 3024 long Bar = __builtin_expect(Foo, true); 3025 /*[[p]]*/ 3026 } 3027 )"; 3028 runDataflow( 3029 Code, 3030 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3031 ASTContext &ASTCtx) { 3032 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3033 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3034 3035 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3036 ASSERT_THAT(FooDecl, NotNull()); 3037 3038 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3039 ASSERT_THAT(BarDecl, NotNull()); 3040 3041 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3042 }); 3043 } 3044 3045 // `__builtin_expect` takes and returns a `long` argument, so other types 3046 // involve casts. This verifies that we identify the input and output in that 3047 // case. 3048 TEST(TransferTest, BuiltinExpectBoolArg) { 3049 std::string Code = R"( 3050 void target(bool Foo) { 3051 bool Bar = __builtin_expect(Foo, true); 3052 /*[[p]]*/ 3053 } 3054 )"; 3055 runDataflow( 3056 Code, 3057 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3058 ASTContext &ASTCtx) { 3059 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3060 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3061 3062 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3063 ASSERT_THAT(FooDecl, NotNull()); 3064 3065 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3066 ASSERT_THAT(BarDecl, NotNull()); 3067 3068 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3069 }); 3070 } 3071 3072 TEST(TransferTest, BuiltinUnreachable) { 3073 std::string Code = R"( 3074 void target(bool Foo) { 3075 bool Bar = false; 3076 if (Foo) 3077 Bar = Foo; 3078 else 3079 __builtin_unreachable(); 3080 (void)0; 3081 /*[[p]]*/ 3082 } 3083 )"; 3084 runDataflow( 3085 Code, 3086 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3087 ASTContext &ASTCtx) { 3088 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3089 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3090 3091 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3092 ASSERT_THAT(FooDecl, NotNull()); 3093 3094 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3095 ASSERT_THAT(BarDecl, NotNull()); 3096 3097 // `__builtin_unreachable` promises that the code is 3098 // unreachable, so the compiler treats the "then" branch as the 3099 // only possible predecessor of this statement. 3100 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3101 }); 3102 } 3103 3104 TEST(TransferTest, BuiltinTrap) { 3105 std::string Code = R"( 3106 void target(bool Foo) { 3107 bool Bar = false; 3108 if (Foo) 3109 Bar = Foo; 3110 else 3111 __builtin_trap(); 3112 (void)0; 3113 /*[[p]]*/ 3114 } 3115 )"; 3116 runDataflow( 3117 Code, 3118 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3119 ASTContext &ASTCtx) { 3120 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3121 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3122 3123 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3124 ASSERT_THAT(FooDecl, NotNull()); 3125 3126 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3127 ASSERT_THAT(BarDecl, NotNull()); 3128 3129 // `__builtin_trap` ensures program termination, so only the 3130 // "then" branch is a predecessor of this statement. 3131 EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3132 }); 3133 } 3134 3135 TEST(TransferTest, BuiltinDebugTrap) { 3136 std::string Code = R"( 3137 void target(bool Foo) { 3138 bool Bar = false; 3139 if (Foo) 3140 Bar = Foo; 3141 else 3142 __builtin_debugtrap(); 3143 (void)0; 3144 /*[[p]]*/ 3145 } 3146 )"; 3147 runDataflow( 3148 Code, 3149 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3150 ASTContext &ASTCtx) { 3151 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3152 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3153 3154 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3155 ASSERT_THAT(FooDecl, NotNull()); 3156 3157 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3158 ASSERT_THAT(BarDecl, NotNull()); 3159 3160 // `__builtin_debugtrap` doesn't ensure program termination. 3161 EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl)); 3162 }); 3163 } 3164 3165 TEST(TransferTest, StaticIntSingleVarDecl) { 3166 std::string Code = R"( 3167 void target() { 3168 static int Foo; 3169 // [[p]] 3170 } 3171 )"; 3172 runDataflow( 3173 Code, 3174 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3175 ASTContext &ASTCtx) { 3176 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3177 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3178 3179 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3180 ASSERT_THAT(FooDecl, NotNull()); 3181 3182 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 3183 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 3184 3185 const Value *FooVal = Env.getValue(*FooLoc); 3186 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 3187 }); 3188 } 3189 3190 TEST(TransferTest, StaticIntGroupVarDecl) { 3191 std::string Code = R"( 3192 void target() { 3193 static int Foo, Bar; 3194 (void)0; 3195 // [[p]] 3196 } 3197 )"; 3198 runDataflow( 3199 Code, 3200 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3201 ASTContext &ASTCtx) { 3202 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3203 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3204 3205 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3206 ASSERT_THAT(FooDecl, NotNull()); 3207 3208 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3209 ASSERT_THAT(BarDecl, NotNull()); 3210 3211 const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl); 3212 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc)); 3213 3214 const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl); 3215 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc)); 3216 3217 const Value *FooVal = Env.getValue(*FooLoc); 3218 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal)); 3219 3220 const Value *BarVal = Env.getValue(*BarLoc); 3221 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal)); 3222 3223 EXPECT_NE(FooVal, BarVal); 3224 }); 3225 } 3226 3227 TEST(TransferTest, GlobalIntVarDecl) { 3228 std::string Code = R"( 3229 static int Foo; 3230 3231 void target() { 3232 int Bar = Foo; 3233 int Baz = Foo; 3234 // [[p]] 3235 } 3236 )"; 3237 runDataflow( 3238 Code, 3239 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3240 ASTContext &ASTCtx) { 3241 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3242 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3243 3244 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3245 ASSERT_THAT(BarDecl, NotNull()); 3246 3247 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3248 ASSERT_THAT(BazDecl, NotNull()); 3249 3250 const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3251 const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl)); 3252 EXPECT_EQ(BarVal, BazVal); 3253 }); 3254 } 3255 3256 TEST(TransferTest, StaticMemberIntVarDecl) { 3257 std::string Code = R"( 3258 struct A { 3259 static int Foo; 3260 }; 3261 3262 void target(A a) { 3263 int Bar = a.Foo; 3264 int Baz = a.Foo; 3265 // [[p]] 3266 } 3267 )"; 3268 runDataflow( 3269 Code, 3270 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3271 ASTContext &ASTCtx) { 3272 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3273 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3274 3275 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3276 ASSERT_THAT(BarDecl, NotNull()); 3277 3278 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3279 ASSERT_THAT(BazDecl, NotNull()); 3280 3281 const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3282 const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl)); 3283 EXPECT_EQ(BarVal, BazVal); 3284 }); 3285 } 3286 3287 TEST(TransferTest, StaticMemberRefVarDecl) { 3288 std::string Code = R"( 3289 struct A { 3290 static int &Foo; 3291 }; 3292 3293 void target(A a) { 3294 int Bar = a.Foo; 3295 int Baz = a.Foo; 3296 // [[p]] 3297 } 3298 )"; 3299 runDataflow( 3300 Code, 3301 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3302 ASTContext &ASTCtx) { 3303 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3304 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3305 3306 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3307 ASSERT_THAT(BarDecl, NotNull()); 3308 3309 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3310 ASSERT_THAT(BazDecl, NotNull()); 3311 3312 const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3313 const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl)); 3314 EXPECT_EQ(BarVal, BazVal); 3315 }); 3316 } 3317 3318 TEST(TransferTest, AssignMemberBeforeCopy) { 3319 std::string Code = R"( 3320 struct A { 3321 int Foo; 3322 }; 3323 3324 void target() { 3325 A A1; 3326 A A2; 3327 int Bar; 3328 A1.Foo = Bar; 3329 A2 = A1; 3330 // [[p]] 3331 } 3332 )"; 3333 runDataflow( 3334 Code, 3335 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3336 ASTContext &ASTCtx) { 3337 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3338 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3339 3340 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 3341 ASSERT_THAT(FooDecl, NotNull()); 3342 3343 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3344 ASSERT_THAT(BarDecl, NotNull()); 3345 3346 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1"); 3347 ASSERT_THAT(A1Decl, NotNull()); 3348 3349 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2"); 3350 ASSERT_THAT(A2Decl, NotNull()); 3351 3352 const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl)); 3353 3354 const auto *A2Val = cast<StructValue>(Env.getValue(*A2Decl)); 3355 EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal); 3356 }); 3357 } 3358 3359 TEST(TransferTest, BooleanEquality) { 3360 std::string Code = R"( 3361 void target(bool Bar) { 3362 bool Foo = true; 3363 if (Bar == Foo) { 3364 (void)0; 3365 /*[[p-then]]*/ 3366 } else { 3367 (void)0; 3368 /*[[p-else]]*/ 3369 } 3370 } 3371 )"; 3372 runDataflow( 3373 Code, 3374 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3375 ASTContext &ASTCtx) { 3376 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else")); 3377 const Environment &EnvThen = 3378 getEnvironmentAtAnnotation(Results, "p-then"); 3379 const Environment &EnvElse = 3380 getEnvironmentAtAnnotation(Results, "p-else"); 3381 3382 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3383 ASSERT_THAT(BarDecl, NotNull()); 3384 3385 auto &BarValThen = *cast<BoolValue>(EnvThen.getValue(*BarDecl)); 3386 EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen)); 3387 3388 auto &BarValElse = *cast<BoolValue>(EnvElse.getValue(*BarDecl)); 3389 EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse)); 3390 }); 3391 } 3392 3393 TEST(TransferTest, BooleanInequality) { 3394 std::string Code = R"( 3395 void target(bool Bar) { 3396 bool Foo = true; 3397 if (Bar != Foo) { 3398 (void)0; 3399 /*[[p-then]]*/ 3400 } else { 3401 (void)0; 3402 /*[[p-else]]*/ 3403 } 3404 } 3405 )"; 3406 runDataflow( 3407 Code, 3408 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3409 ASTContext &ASTCtx) { 3410 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else")); 3411 const Environment &EnvThen = 3412 getEnvironmentAtAnnotation(Results, "p-then"); 3413 const Environment &EnvElse = 3414 getEnvironmentAtAnnotation(Results, "p-else"); 3415 3416 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3417 ASSERT_THAT(BarDecl, NotNull()); 3418 3419 auto &BarValThen = *cast<BoolValue>(EnvThen.getValue(*BarDecl)); 3420 EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen)); 3421 3422 auto &BarValElse = *cast<BoolValue>(EnvElse.getValue(*BarDecl)); 3423 EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse)); 3424 }); 3425 } 3426 3427 TEST(TransferTest, CorrelatedBranches) { 3428 std::string Code = R"( 3429 void target(bool B, bool C) { 3430 if (B) { 3431 return; 3432 } 3433 (void)0; 3434 /*[[p0]]*/ 3435 if (C) { 3436 B = true; 3437 /*[[p1]]*/ 3438 } 3439 if (B) { 3440 (void)0; 3441 /*[[p2]]*/ 3442 } 3443 } 3444 )"; 3445 runDataflow( 3446 Code, 3447 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3448 ASTContext &ASTCtx) { 3449 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2")); 3450 3451 const ValueDecl *CDecl = findValueDecl(ASTCtx, "C"); 3452 ASSERT_THAT(CDecl, NotNull()); 3453 3454 { 3455 const Environment &Env = getEnvironmentAtAnnotation(Results, "p0"); 3456 const ValueDecl *BDecl = findValueDecl(ASTCtx, "B"); 3457 ASSERT_THAT(BDecl, NotNull()); 3458 auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl)); 3459 3460 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal))); 3461 } 3462 3463 { 3464 const Environment &Env = getEnvironmentAtAnnotation(Results, "p1"); 3465 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl)); 3466 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3467 } 3468 3469 { 3470 const Environment &Env = getEnvironmentAtAnnotation(Results, "p2"); 3471 auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl)); 3472 EXPECT_TRUE(Env.flowConditionImplies(CVal)); 3473 } 3474 }); 3475 } 3476 3477 TEST(TransferTest, LoopWithAssignmentConverges) { 3478 std::string Code = R"( 3479 bool foo(); 3480 3481 void target() { 3482 do { 3483 bool Bar = foo(); 3484 if (Bar) break; 3485 (void)Bar; 3486 /*[[p]]*/ 3487 } while (true); 3488 } 3489 )"; 3490 // The key property that we are verifying is implicit in `runDataflow` -- 3491 // namely, that the analysis succeeds, rather than hitting the maximum number 3492 // of iterations. 3493 runDataflow( 3494 Code, 3495 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3496 ASTContext &ASTCtx) { 3497 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3498 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3499 3500 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3501 ASSERT_THAT(BarDecl, NotNull()); 3502 3503 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl)); 3504 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3505 }); 3506 } 3507 3508 TEST(TransferTest, LoopWithStagedAssignments) { 3509 std::string Code = R"( 3510 bool foo(); 3511 3512 void target() { 3513 bool Bar = false; 3514 bool Err = false; 3515 while (foo()) { 3516 if (Bar) 3517 Err = true; 3518 Bar = true; 3519 /*[[p]]*/ 3520 } 3521 } 3522 )"; 3523 runDataflow( 3524 Code, 3525 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3526 ASTContext &ASTCtx) { 3527 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3528 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3529 3530 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3531 ASSERT_THAT(BarDecl, NotNull()); 3532 const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err"); 3533 ASSERT_THAT(ErrDecl, NotNull()); 3534 3535 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl)); 3536 auto &ErrVal = *cast<BoolValue>(Env.getValue(*ErrDecl)); 3537 EXPECT_TRUE(Env.flowConditionImplies(BarVal)); 3538 // An unsound analysis, for example only evaluating the loop once, can 3539 // conclude that `Err` is false. So, we test that this conclusion is not 3540 // reached. 3541 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(ErrVal))); 3542 }); 3543 } 3544 3545 TEST(TransferTest, LoopWithReferenceAssignmentConverges) { 3546 std::string Code = R"( 3547 bool &foo(); 3548 3549 void target() { 3550 do { 3551 bool& Bar = foo(); 3552 if (Bar) break; 3553 (void)Bar; 3554 /*[[p]]*/ 3555 } while (true); 3556 } 3557 )"; 3558 // The key property that we are verifying is that the analysis succeeds, 3559 // rather than hitting the maximum number of iterations. 3560 runDataflow( 3561 Code, 3562 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3563 ASTContext &ASTCtx) { 3564 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3565 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3566 3567 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 3568 ASSERT_THAT(BarDecl, NotNull()); 3569 3570 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl)); 3571 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 3572 }); 3573 } 3574 3575 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) { 3576 std::string Code = R"( 3577 struct Lookup { 3578 int x; 3579 }; 3580 3581 void target(Lookup val, bool b) { 3582 const Lookup* l = nullptr; 3583 while (b) { 3584 l = &val; 3585 /*[[p-inner]]*/ 3586 } 3587 (void)0; 3588 /*[[p-outer]]*/ 3589 } 3590 )"; 3591 // The key property that we are verifying is implicit in `runDataflow` -- 3592 // namely, that the analysis succeeds, rather than hitting the maximum number 3593 // of iterations. 3594 runDataflow( 3595 Code, 3596 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3597 ASTContext &ASTCtx) { 3598 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer")); 3599 const Environment &InnerEnv = 3600 getEnvironmentAtAnnotation(Results, "p-inner"); 3601 const Environment &OuterEnv = 3602 getEnvironmentAtAnnotation(Results, "p-outer"); 3603 3604 const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val"); 3605 ASSERT_THAT(ValDecl, NotNull()); 3606 3607 const ValueDecl *LDecl = findValueDecl(ASTCtx, "l"); 3608 ASSERT_THAT(LDecl, NotNull()); 3609 3610 // Inner. 3611 auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl)); 3612 ASSERT_THAT(LVal, NotNull()); 3613 3614 EXPECT_EQ(&LVal->getPointeeLoc(), 3615 InnerEnv.getStorageLocation(*ValDecl)); 3616 3617 // Outer. 3618 LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl)); 3619 ASSERT_THAT(LVal, NotNull()); 3620 3621 // The loop body may not have been executed, so we should not conclude 3622 // that `l` points to `val`. 3623 EXPECT_NE(&LVal->getPointeeLoc(), 3624 OuterEnv.getStorageLocation(*ValDecl)); 3625 }); 3626 } 3627 3628 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) { 3629 std::string Code = R"( 3630 union Union { 3631 int A; 3632 float B; 3633 }; 3634 3635 void foo() { 3636 Union A; 3637 Union B; 3638 A = B; 3639 } 3640 )"; 3641 // This is a crash regression test when calling the transfer function on a 3642 // `CXXThisExpr` that refers to a union. 3643 runDataflow( 3644 Code, 3645 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &, 3646 ASTContext &) {}, 3647 LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator="); 3648 } 3649 3650 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) { 3651 std::string Code = R"( 3652 struct A { 3653 int Foo; 3654 int Bar; 3655 }; 3656 3657 void target() { 3658 int Qux; 3659 A Baz; 3660 Baz.Foo = Qux; 3661 auto &FooRef = Baz.Foo; 3662 auto &BarRef = Baz.Bar; 3663 auto &[BoundFooRef, BoundBarRef] = Baz; 3664 // [[p]] 3665 } 3666 )"; 3667 runDataflow( 3668 Code, 3669 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3670 ASTContext &ASTCtx) { 3671 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3672 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3673 3674 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3675 ASSERT_THAT(FooRefDecl, NotNull()); 3676 3677 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3678 ASSERT_THAT(BarRefDecl, NotNull()); 3679 3680 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3681 ASSERT_THAT(QuxDecl, NotNull()); 3682 3683 const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); 3684 ASSERT_THAT(BoundFooRefDecl, NotNull()); 3685 3686 const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); 3687 ASSERT_THAT(BoundBarRefDecl, NotNull()); 3688 3689 const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl); 3690 ASSERT_THAT(FooRefLoc, NotNull()); 3691 3692 const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl); 3693 ASSERT_THAT(BarRefLoc, NotNull()); 3694 3695 const Value *QuxVal = Env.getValue(*QuxDecl); 3696 ASSERT_THAT(QuxVal, NotNull()); 3697 3698 const StorageLocation *BoundFooRefLoc = 3699 Env.getStorageLocation(*BoundFooRefDecl); 3700 EXPECT_EQ(BoundFooRefLoc, FooRefLoc); 3701 3702 const StorageLocation *BoundBarRefLoc = 3703 Env.getStorageLocation(*BoundBarRefDecl); 3704 EXPECT_EQ(BoundBarRefLoc, BarRefLoc); 3705 3706 EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal); 3707 }); 3708 } 3709 3710 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) { 3711 std::string Code = R"( 3712 struct A { 3713 int &Foo; 3714 int &Bar; 3715 }; 3716 3717 void target(A Baz) { 3718 int Qux; 3719 Baz.Foo = Qux; 3720 auto &FooRef = Baz.Foo; 3721 auto &BarRef = Baz.Bar; 3722 auto &[BoundFooRef, BoundBarRef] = Baz; 3723 // [[p]] 3724 } 3725 )"; 3726 runDataflow( 3727 Code, 3728 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3729 ASTContext &ASTCtx) { 3730 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3731 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3732 3733 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3734 ASSERT_THAT(FooRefDecl, NotNull()); 3735 3736 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3737 ASSERT_THAT(BarRefDecl, NotNull()); 3738 3739 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3740 ASSERT_THAT(QuxDecl, NotNull()); 3741 3742 const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef"); 3743 ASSERT_THAT(BoundFooRefDecl, NotNull()); 3744 3745 const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef"); 3746 ASSERT_THAT(BoundBarRefDecl, NotNull()); 3747 3748 const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl); 3749 ASSERT_THAT(FooRefLoc, NotNull()); 3750 3751 const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl); 3752 ASSERT_THAT(BarRefLoc, NotNull()); 3753 3754 const Value *QuxVal = Env.getValue(*QuxDecl); 3755 ASSERT_THAT(QuxVal, NotNull()); 3756 3757 const StorageLocation *BoundFooRefLoc = 3758 Env.getStorageLocation(*BoundFooRefDecl); 3759 EXPECT_EQ(BoundFooRefLoc, FooRefLoc); 3760 3761 const StorageLocation *BoundBarRefLoc = 3762 Env.getStorageLocation(*BoundBarRefDecl); 3763 EXPECT_EQ(BoundBarRefLoc, BarRefLoc); 3764 3765 EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal); 3766 }); 3767 } 3768 3769 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) { 3770 std::string Code = R"( 3771 struct A { 3772 int Foo; 3773 int Bar; 3774 }; 3775 3776 void target() { 3777 int Qux; 3778 A Baz; 3779 Baz.Foo = Qux; 3780 auto &FooRef = Baz.Foo; 3781 auto &BarRef = Baz.Bar; 3782 auto [BoundFoo, BoundBar] = Baz; 3783 // [[p]] 3784 } 3785 )"; 3786 runDataflow( 3787 Code, 3788 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3789 ASTContext &ASTCtx) { 3790 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 3791 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 3792 3793 const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef"); 3794 ASSERT_THAT(FooRefDecl, NotNull()); 3795 3796 const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef"); 3797 ASSERT_THAT(BarRefDecl, NotNull()); 3798 3799 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 3800 ASSERT_THAT(BoundFooDecl, NotNull()); 3801 3802 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 3803 ASSERT_THAT(BoundBarDecl, NotNull()); 3804 3805 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux"); 3806 ASSERT_THAT(QuxDecl, NotNull()); 3807 3808 const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl); 3809 ASSERT_THAT(FooRefLoc, NotNull()); 3810 3811 const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl); 3812 ASSERT_THAT(BarRefLoc, NotNull()); 3813 3814 const Value *QuxVal = Env.getValue(*QuxDecl); 3815 ASSERT_THAT(QuxVal, NotNull()); 3816 3817 const StorageLocation *BoundFooLoc = 3818 Env.getStorageLocation(*BoundFooDecl); 3819 EXPECT_NE(BoundFooLoc, FooRefLoc); 3820 3821 const StorageLocation *BoundBarLoc = 3822 Env.getStorageLocation(*BoundBarDecl); 3823 EXPECT_NE(BoundBarLoc, BarRefLoc); 3824 3825 EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal); 3826 }); 3827 } 3828 3829 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) { 3830 std::string Code = R"( 3831 namespace std { 3832 using size_t = int; 3833 template <class> struct tuple_size; 3834 template <std::size_t, class> struct tuple_element; 3835 template <class...> class tuple; 3836 3837 namespace { 3838 template <class T, T v> 3839 struct size_helper { static const T value = v; }; 3840 } // namespace 3841 3842 template <class... T> 3843 struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {}; 3844 3845 template <std::size_t I, class... T> 3846 struct tuple_element<I, tuple<T...>> { 3847 using type = __type_pack_element<I, T...>; 3848 }; 3849 3850 template <class...> class tuple {}; 3851 3852 template <std::size_t I, class... T> 3853 typename tuple_element<I, tuple<T...>>::type get(tuple<T...>); 3854 } // namespace std 3855 3856 std::tuple<bool, int> makeTuple(); 3857 3858 void target(bool B) { 3859 auto [BoundFoo, BoundBar] = makeTuple(); 3860 bool Baz; 3861 // Include if-then-else to test interaction of `BindingDecl` with join. 3862 if (B) { 3863 Baz = BoundFoo; 3864 (void)BoundBar; 3865 // [[p1]] 3866 } else { 3867 Baz = BoundFoo; 3868 } 3869 (void)0; 3870 // [[p2]] 3871 } 3872 )"; 3873 runDataflow( 3874 Code, 3875 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3876 ASTContext &ASTCtx) { 3877 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 3878 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 3879 3880 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 3881 ASSERT_THAT(BoundFooDecl, NotNull()); 3882 3883 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 3884 ASSERT_THAT(BoundBarDecl, NotNull()); 3885 3886 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3887 ASSERT_THAT(BazDecl, NotNull()); 3888 3889 // BindingDecls always map to references -- either lvalue or rvalue, so 3890 // we still need to skip here. 3891 const Value *BoundFooValue = Env1.getValue(*BoundFooDecl); 3892 ASSERT_THAT(BoundFooValue, NotNull()); 3893 EXPECT_TRUE(isa<BoolValue>(BoundFooValue)); 3894 3895 const Value *BoundBarValue = Env1.getValue(*BoundBarDecl); 3896 ASSERT_THAT(BoundBarValue, NotNull()); 3897 EXPECT_TRUE(isa<IntegerValue>(BoundBarValue)); 3898 3899 // Test that a `DeclRefExpr` to a `BindingDecl` works as expected. 3900 EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue); 3901 3902 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 3903 3904 // Test that `BoundFooDecl` retains the value we expect, after the join. 3905 BoundFooValue = Env2.getValue(*BoundFooDecl); 3906 EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue); 3907 }); 3908 } 3909 3910 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) { 3911 std::string Code = R"( 3912 namespace std { 3913 using size_t = int; 3914 template <class> struct tuple_size; 3915 template <std::size_t, class> struct tuple_element; 3916 template <class...> class tuple; 3917 3918 namespace { 3919 template <class T, T v> 3920 struct size_helper { static const T value = v; }; 3921 } // namespace 3922 3923 template <class... T> 3924 struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {}; 3925 3926 template <std::size_t I, class... T> 3927 struct tuple_element<I, tuple<T...>> { 3928 using type = __type_pack_element<I, T...>; 3929 }; 3930 3931 template <class...> class tuple {}; 3932 3933 template <std::size_t I, class... T> 3934 typename tuple_element<I, tuple<T...>>::type get(tuple<T...>); 3935 } // namespace std 3936 3937 std::tuple<bool, int> &getTuple(); 3938 3939 void target(bool B) { 3940 auto &[BoundFoo, BoundBar] = getTuple(); 3941 bool Baz; 3942 // Include if-then-else to test interaction of `BindingDecl` with join. 3943 if (B) { 3944 Baz = BoundFoo; 3945 (void)BoundBar; 3946 // [[p1]] 3947 } else { 3948 Baz = BoundFoo; 3949 } 3950 (void)0; 3951 // [[p2]] 3952 } 3953 )"; 3954 runDataflow( 3955 Code, 3956 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 3957 ASTContext &ASTCtx) { 3958 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2")); 3959 const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1"); 3960 3961 const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo"); 3962 ASSERT_THAT(BoundFooDecl, NotNull()); 3963 3964 const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar"); 3965 ASSERT_THAT(BoundBarDecl, NotNull()); 3966 3967 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 3968 ASSERT_THAT(BazDecl, NotNull()); 3969 3970 const Value *BoundFooValue = Env1.getValue(*BoundFooDecl); 3971 ASSERT_THAT(BoundFooValue, NotNull()); 3972 EXPECT_TRUE(isa<BoolValue>(BoundFooValue)); 3973 3974 const Value *BoundBarValue = Env1.getValue(*BoundBarDecl); 3975 ASSERT_THAT(BoundBarValue, NotNull()); 3976 EXPECT_TRUE(isa<IntegerValue>(BoundBarValue)); 3977 3978 // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type) 3979 // works as expected. We don't test aliasing properties of the 3980 // reference, because we don't model `std::get` and so have no way to 3981 // equate separate references into the tuple. 3982 EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue); 3983 3984 const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2"); 3985 3986 // Test that `BoundFooDecl` retains the value we expect, after the join. 3987 BoundFooValue = Env2.getValue(*BoundFooDecl); 3988 EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue); 3989 }); 3990 } 3991 3992 TEST(TransferTest, BinaryOperatorComma) { 3993 std::string Code = R"( 3994 void target(int Foo, int Bar) { 3995 int &Baz = (Foo, Bar); 3996 // [[p]] 3997 } 3998 )"; 3999 runDataflow( 4000 Code, 4001 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4002 ASTContext &ASTCtx) { 4003 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4004 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4005 4006 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4007 ASSERT_THAT(BarDecl, NotNull()); 4008 4009 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4010 ASSERT_THAT(BazDecl, NotNull()); 4011 4012 const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl); 4013 ASSERT_THAT(BarLoc, NotNull()); 4014 4015 const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl); 4016 EXPECT_EQ(BazLoc, BarLoc); 4017 }); 4018 } 4019 4020 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) { 4021 std::string Code = R"( 4022 void target(bool Foo) { 4023 if (Foo) { 4024 (void)0; 4025 // [[if_then]] 4026 } else { 4027 (void)0; 4028 // [[if_else]] 4029 } 4030 } 4031 )"; 4032 runDataflow( 4033 Code, 4034 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4035 ASTContext &ASTCtx) { 4036 ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else")); 4037 const Environment &ThenEnv = 4038 getEnvironmentAtAnnotation(Results, "if_then"); 4039 const Environment &ElseEnv = 4040 getEnvironmentAtAnnotation(Results, "if_else"); 4041 4042 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4043 ASSERT_THAT(FooDecl, NotNull()); 4044 4045 BoolValue &ThenFooVal = *cast<BoolValue>(ThenEnv.getValue(*FooDecl)); 4046 EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal)); 4047 4048 BoolValue &ElseFooVal = *cast<BoolValue>(ElseEnv.getValue(*FooDecl)); 4049 EXPECT_TRUE(ElseEnv.flowConditionImplies(ElseEnv.makeNot(ElseFooVal))); 4050 }); 4051 } 4052 4053 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) { 4054 std::string Code = R"( 4055 void target(bool Foo) { 4056 while (Foo) { 4057 (void)0; 4058 // [[loop_body]] 4059 } 4060 (void)0; 4061 // [[after_loop]] 4062 } 4063 )"; 4064 runDataflow( 4065 Code, 4066 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4067 ASTContext &ASTCtx) { 4068 ASSERT_THAT(Results.keys(), 4069 UnorderedElementsAre("loop_body", "after_loop")); 4070 const Environment &LoopBodyEnv = 4071 getEnvironmentAtAnnotation(Results, "loop_body"); 4072 const Environment &AfterLoopEnv = 4073 getEnvironmentAtAnnotation(Results, "after_loop"); 4074 4075 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4076 ASSERT_THAT(FooDecl, NotNull()); 4077 4078 BoolValue &LoopBodyFooVal = 4079 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl)); 4080 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4081 4082 BoolValue &AfterLoopFooVal = 4083 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl)); 4084 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4085 AfterLoopEnv.makeNot(AfterLoopFooVal))); 4086 }); 4087 } 4088 4089 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) { 4090 std::string Code = R"( 4091 void target(bool Foo) { 4092 bool Bar = true; 4093 do { 4094 (void)0; 4095 // [[loop_body]] 4096 Bar = false; 4097 } while (Foo); 4098 (void)0; 4099 // [[after_loop]] 4100 } 4101 )"; 4102 runDataflow( 4103 Code, 4104 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4105 ASTContext &ASTCtx) { 4106 ASSERT_THAT(Results.keys(), 4107 UnorderedElementsAre("loop_body", "after_loop")); 4108 const Environment &LoopBodyEnv = 4109 getEnvironmentAtAnnotation(Results, "loop_body"); 4110 const Environment &AfterLoopEnv = 4111 getEnvironmentAtAnnotation(Results, "after_loop"); 4112 4113 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4114 ASSERT_THAT(FooDecl, NotNull()); 4115 4116 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4117 ASSERT_THAT(BarDecl, NotNull()); 4118 4119 BoolValue &LoopBodyFooVal = 4120 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl)); 4121 BoolValue &LoopBodyBarVal = 4122 *cast<BoolValue>(LoopBodyEnv.getValue(*BarDecl)); 4123 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies( 4124 LoopBodyEnv.makeOr(LoopBodyBarVal, LoopBodyFooVal))); 4125 4126 BoolValue &AfterLoopFooVal = 4127 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl)); 4128 BoolValue &AfterLoopBarVal = 4129 *cast<BoolValue>(AfterLoopEnv.getValue(*BarDecl)); 4130 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4131 AfterLoopEnv.makeNot(AfterLoopFooVal))); 4132 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4133 AfterLoopEnv.makeNot(AfterLoopBarVal))); 4134 }); 4135 } 4136 4137 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) { 4138 std::string Code = R"( 4139 void target(bool Foo) { 4140 for (; Foo;) { 4141 (void)0; 4142 // [[loop_body]] 4143 } 4144 (void)0; 4145 // [[after_loop]] 4146 } 4147 )"; 4148 runDataflow( 4149 Code, 4150 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4151 ASTContext &ASTCtx) { 4152 ASSERT_THAT(Results.keys(), 4153 UnorderedElementsAre("loop_body", "after_loop")); 4154 const Environment &LoopBodyEnv = 4155 getEnvironmentAtAnnotation(Results, "loop_body"); 4156 const Environment &AfterLoopEnv = 4157 getEnvironmentAtAnnotation(Results, "after_loop"); 4158 4159 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4160 ASSERT_THAT(FooDecl, NotNull()); 4161 4162 BoolValue &LoopBodyFooVal = 4163 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl)); 4164 EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4165 4166 BoolValue &AfterLoopFooVal = 4167 *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl)); 4168 EXPECT_TRUE(AfterLoopEnv.flowConditionImplies( 4169 AfterLoopEnv.makeNot(AfterLoopFooVal))); 4170 }); 4171 } 4172 4173 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) { 4174 std::string Code = R"( 4175 void target(bool Foo) { 4176 for (;;) { 4177 (void)0; 4178 // [[loop_body]] 4179 } 4180 } 4181 )"; 4182 runDataflow( 4183 Code, 4184 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4185 ASTContext &ASTCtx) { 4186 ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body")); 4187 const Environment &LoopBodyEnv = 4188 getEnvironmentAtAnnotation(Results, "loop_body"); 4189 4190 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4191 ASSERT_THAT(FooDecl, NotNull()); 4192 4193 BoolValue &LoopBodyFooVal = 4194 *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl)); 4195 EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal)); 4196 }); 4197 } 4198 4199 TEST(TransferTest, ContextSensitiveOptionDisabled) { 4200 std::string Code = R"( 4201 bool GiveBool(); 4202 void SetBool(bool &Var) { Var = true; } 4203 4204 void target() { 4205 bool Foo = GiveBool(); 4206 SetBool(Foo); 4207 // [[p]] 4208 } 4209 )"; 4210 runDataflow( 4211 Code, 4212 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4213 ASTContext &ASTCtx) { 4214 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4215 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4216 4217 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4218 ASSERT_THAT(FooDecl, NotNull()); 4219 4220 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4221 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4222 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4223 }, 4224 {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}}); 4225 } 4226 4227 // This test is a regression test, based on a real crash. 4228 TEST(TransferTest, ContextSensitiveReturnReferenceFromNonReferenceLvalue) { 4229 // This code exercises an unusual code path. If we return an lvalue directly, 4230 // the code will catch that it's an l-value based on the `Value`'s kind. If we 4231 // pass through a dummy function, the framework won't populate a value at 4232 // all. In contrast, this code results in a (fresh) value, but it is not 4233 // `ReferenceValue`. This test verifies that we catch this case as well. 4234 std::string Code = R"( 4235 class S {}; 4236 S& target(bool b, S &s) { 4237 return b ? s : s; 4238 // [[p]] 4239 } 4240 )"; 4241 runDataflow( 4242 Code, 4243 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4244 ASTContext &ASTCtx) { 4245 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4246 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4247 4248 auto *Loc = Env.getReturnStorageLocation(); 4249 ASSERT_THAT(Loc, NotNull()); 4250 4251 EXPECT_THAT(Env.getValue(*Loc), IsNull()); 4252 }, 4253 {BuiltinOptions{ContextSensitiveOptions{}}}); 4254 } 4255 4256 TEST(TransferTest, ContextSensitiveDepthZero) { 4257 std::string Code = R"( 4258 bool GiveBool(); 4259 void SetBool(bool &Var) { Var = true; } 4260 4261 void target() { 4262 bool Foo = GiveBool(); 4263 SetBool(Foo); 4264 // [[p]] 4265 } 4266 )"; 4267 runDataflow( 4268 Code, 4269 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4270 ASTContext &ASTCtx) { 4271 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4272 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4273 4274 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4275 ASSERT_THAT(FooDecl, NotNull()); 4276 4277 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4278 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4279 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4280 }, 4281 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}}); 4282 } 4283 4284 TEST(TransferTest, ContextSensitiveSetTrue) { 4285 std::string Code = R"( 4286 bool GiveBool(); 4287 void SetBool(bool &Var) { Var = true; } 4288 4289 void target() { 4290 bool Foo = GiveBool(); 4291 SetBool(Foo); 4292 // [[p]] 4293 } 4294 )"; 4295 runDataflow( 4296 Code, 4297 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4298 ASTContext &ASTCtx) { 4299 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4300 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4301 4302 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4303 ASSERT_THAT(FooDecl, NotNull()); 4304 4305 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4306 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4307 }, 4308 {BuiltinOptions{ContextSensitiveOptions{}}}); 4309 } 4310 4311 TEST(TransferTest, ContextSensitiveSetFalse) { 4312 std::string Code = R"( 4313 bool GiveBool(); 4314 void SetBool(bool &Var) { Var = false; } 4315 4316 void target() { 4317 bool Foo = GiveBool(); 4318 SetBool(Foo); 4319 // [[p]] 4320 } 4321 )"; 4322 runDataflow( 4323 Code, 4324 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4325 ASTContext &ASTCtx) { 4326 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4327 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4328 4329 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4330 ASSERT_THAT(FooDecl, NotNull()); 4331 4332 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4333 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4334 }, 4335 {BuiltinOptions{ContextSensitiveOptions{}}}); 4336 } 4337 4338 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) { 4339 std::string Code = R"( 4340 bool GiveBool(); 4341 void SetBool(bool &Var, bool Val) { Var = Val; } 4342 4343 void target() { 4344 bool Foo = GiveBool(); 4345 bool Bar = GiveBool(); 4346 SetBool(Foo, true); 4347 SetBool(Bar, false); 4348 // [[p]] 4349 } 4350 )"; 4351 runDataflow( 4352 Code, 4353 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4354 ASTContext &ASTCtx) { 4355 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4356 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4357 4358 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4359 ASSERT_THAT(FooDecl, NotNull()); 4360 4361 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4362 ASSERT_THAT(BarDecl, NotNull()); 4363 4364 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4365 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4366 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4367 4368 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl)); 4369 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4370 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 4371 }, 4372 {BuiltinOptions{ContextSensitiveOptions{}}}); 4373 } 4374 4375 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) { 4376 std::string Code = R"( 4377 bool GiveBool(); 4378 void SetBool1(bool &Var) { Var = true; } 4379 void SetBool2(bool &Var) { SetBool1(Var); } 4380 4381 void target() { 4382 bool Foo = GiveBool(); 4383 SetBool2(Foo); 4384 // [[p]] 4385 } 4386 )"; 4387 runDataflow( 4388 Code, 4389 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4390 ASTContext &ASTCtx) { 4391 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4392 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4393 4394 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4395 ASSERT_THAT(FooDecl, NotNull()); 4396 4397 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4398 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4399 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4400 }, 4401 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}}); 4402 } 4403 4404 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) { 4405 std::string Code = R"( 4406 bool GiveBool(); 4407 void SetBool1(bool &Var) { Var = true; } 4408 void SetBool2(bool &Var) { SetBool1(Var); } 4409 4410 void target() { 4411 bool Foo = GiveBool(); 4412 SetBool2(Foo); 4413 // [[p]] 4414 } 4415 )"; 4416 runDataflow( 4417 Code, 4418 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4419 ASTContext &ASTCtx) { 4420 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4421 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4422 4423 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4424 ASSERT_THAT(FooDecl, NotNull()); 4425 4426 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4427 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4428 }, 4429 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}}); 4430 } 4431 4432 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) { 4433 std::string Code = R"( 4434 bool GiveBool(); 4435 void SetBool1(bool &Var) { Var = true; } 4436 void SetBool2(bool &Var) { SetBool1(Var); } 4437 void SetBool3(bool &Var) { SetBool2(Var); } 4438 4439 void target() { 4440 bool Foo = GiveBool(); 4441 SetBool3(Foo); 4442 // [[p]] 4443 } 4444 )"; 4445 runDataflow( 4446 Code, 4447 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4448 ASTContext &ASTCtx) { 4449 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4450 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4451 4452 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4453 ASSERT_THAT(FooDecl, NotNull()); 4454 4455 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4456 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4457 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4458 }, 4459 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}}); 4460 } 4461 4462 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) { 4463 std::string Code = R"( 4464 bool GiveBool(); 4465 void SetBool1(bool &Var) { Var = true; } 4466 void SetBool2(bool &Var) { SetBool1(Var); } 4467 void SetBool3(bool &Var) { SetBool2(Var); } 4468 4469 void target() { 4470 bool Foo = GiveBool(); 4471 SetBool3(Foo); 4472 // [[p]] 4473 } 4474 )"; 4475 runDataflow( 4476 Code, 4477 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4478 ASTContext &ASTCtx) { 4479 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4480 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4481 4482 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4483 ASSERT_THAT(FooDecl, NotNull()); 4484 4485 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4486 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4487 }, 4488 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}}); 4489 } 4490 4491 TEST(TransferTest, ContextSensitiveMutualRecursion) { 4492 std::string Code = R"( 4493 bool Pong(bool X, bool Y); 4494 4495 bool Ping(bool X, bool Y) { 4496 if (X) { 4497 return Y; 4498 } else { 4499 return Pong(!X, Y); 4500 } 4501 } 4502 4503 bool Pong(bool X, bool Y) { 4504 if (Y) { 4505 return X; 4506 } else { 4507 return Ping(X, !Y); 4508 } 4509 } 4510 4511 void target() { 4512 bool Foo = Ping(false, false); 4513 // [[p]] 4514 } 4515 )"; 4516 runDataflow( 4517 Code, 4518 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4519 ASTContext &ASTCtx) { 4520 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4521 // The analysis doesn't crash... 4522 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4523 4524 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4525 ASSERT_THAT(FooDecl, NotNull()); 4526 4527 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4528 // ... but it also can't prove anything here. 4529 EXPECT_FALSE(Env.flowConditionImplies(FooVal)); 4530 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4531 }, 4532 {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}}); 4533 } 4534 4535 TEST(TransferTest, ContextSensitiveSetMultipleLines) { 4536 std::string Code = R"( 4537 void SetBools(bool &Var1, bool &Var2) { 4538 Var1 = true; 4539 Var2 = false; 4540 } 4541 4542 void target() { 4543 bool Foo = false; 4544 bool Bar = true; 4545 SetBools(Foo, Bar); 4546 // [[p]] 4547 } 4548 )"; 4549 runDataflow( 4550 Code, 4551 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4552 ASTContext &ASTCtx) { 4553 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4554 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4555 4556 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4557 ASSERT_THAT(FooDecl, NotNull()); 4558 4559 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4560 ASSERT_THAT(BarDecl, NotNull()); 4561 4562 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4563 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4564 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4565 4566 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl)); 4567 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4568 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 4569 }, 4570 {BuiltinOptions{ContextSensitiveOptions{}}}); 4571 } 4572 4573 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) { 4574 std::string Code = R"( 4575 void IfCond(bool Cond, bool &Then, bool &Else) { 4576 if (Cond) { 4577 Then = true; 4578 } else { 4579 Else = true; 4580 } 4581 } 4582 4583 void target() { 4584 bool Foo = false; 4585 bool Bar = false; 4586 bool Baz = false; 4587 IfCond(Foo, Bar, Baz); 4588 // [[p]] 4589 } 4590 )"; 4591 runDataflow( 4592 Code, 4593 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4594 ASTContext &ASTCtx) { 4595 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4596 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4597 4598 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar"); 4599 ASSERT_THAT(BarDecl, NotNull()); 4600 4601 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4602 ASSERT_THAT(BazDecl, NotNull()); 4603 4604 auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl)); 4605 EXPECT_FALSE(Env.flowConditionImplies(BarVal)); 4606 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal))); 4607 4608 auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl)); 4609 EXPECT_TRUE(Env.flowConditionImplies(BazVal)); 4610 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(BazVal))); 4611 }, 4612 {BuiltinOptions{ContextSensitiveOptions{}}}); 4613 } 4614 4615 TEST(TransferTest, ContextSensitiveReturnVoid) { 4616 std::string Code = R"( 4617 void Noop() { return; } 4618 4619 void target() { 4620 Noop(); 4621 // [[p]] 4622 } 4623 )"; 4624 runDataflow( 4625 Code, 4626 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4627 ASTContext &ASTCtx) { 4628 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4629 // This just tests that the analysis doesn't crash. 4630 }, 4631 {BuiltinOptions{ContextSensitiveOptions{}}}); 4632 } 4633 4634 TEST(TransferTest, ContextSensitiveReturnTrue) { 4635 std::string Code = R"( 4636 bool GiveBool() { return true; } 4637 4638 void target() { 4639 bool Foo = GiveBool(); 4640 // [[p]] 4641 } 4642 )"; 4643 runDataflow( 4644 Code, 4645 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4646 ASTContext &ASTCtx) { 4647 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4648 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4649 4650 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4651 ASSERT_THAT(FooDecl, NotNull()); 4652 4653 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4654 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4655 }, 4656 {BuiltinOptions{ContextSensitiveOptions{}}}); 4657 } 4658 4659 TEST(TransferTest, ContextSensitiveReturnFalse) { 4660 std::string Code = R"( 4661 bool GiveBool() { return false; } 4662 4663 void target() { 4664 bool Foo = GiveBool(); 4665 // [[p]] 4666 } 4667 )"; 4668 runDataflow( 4669 Code, 4670 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4671 ASTContext &ASTCtx) { 4672 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4673 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4674 4675 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4676 ASSERT_THAT(FooDecl, NotNull()); 4677 4678 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4679 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal))); 4680 }, 4681 {BuiltinOptions{ContextSensitiveOptions{}}}); 4682 } 4683 4684 TEST(TransferTest, ContextSensitiveReturnArg) { 4685 std::string Code = R"( 4686 bool GiveBool(); 4687 bool GiveBack(bool Arg) { return Arg; } 4688 4689 void target() { 4690 bool Foo = GiveBool(); 4691 bool Bar = GiveBack(Foo); 4692 bool Baz = Foo == Bar; 4693 // [[p]] 4694 } 4695 )"; 4696 runDataflow( 4697 Code, 4698 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4699 ASTContext &ASTCtx) { 4700 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4701 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4702 4703 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); 4704 ASSERT_THAT(BazDecl, NotNull()); 4705 4706 auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl)); 4707 EXPECT_TRUE(Env.flowConditionImplies(BazVal)); 4708 }, 4709 {BuiltinOptions{ContextSensitiveOptions{}}}); 4710 } 4711 4712 TEST(TransferTest, ContextSensitiveReturnInt) { 4713 std::string Code = R"( 4714 int identity(int x) { return x; } 4715 4716 void target() { 4717 int y = identity(42); 4718 // [[p]] 4719 } 4720 )"; 4721 runDataflow( 4722 Code, 4723 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4724 ASTContext &ASTCtx) { 4725 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4726 // This just tests that the analysis doesn't crash. 4727 }, 4728 {BuiltinOptions{ContextSensitiveOptions{}}}); 4729 } 4730 4731 TEST(TransferTest, ContextSensitiveMethodLiteral) { 4732 std::string Code = R"( 4733 class MyClass { 4734 public: 4735 bool giveBool() { return true; } 4736 }; 4737 4738 void target() { 4739 MyClass MyObj; 4740 bool Foo = MyObj.giveBool(); 4741 // [[p]] 4742 } 4743 )"; 4744 runDataflow( 4745 Code, 4746 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4747 ASTContext &ASTCtx) { 4748 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4749 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4750 4751 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4752 ASSERT_THAT(FooDecl, NotNull()); 4753 4754 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4755 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4756 }, 4757 {BuiltinOptions{ContextSensitiveOptions{}}}); 4758 } 4759 4760 TEST(TransferTest, ContextSensitiveMethodGetter) { 4761 std::string Code = R"( 4762 class MyClass { 4763 public: 4764 bool getField() { return Field; } 4765 4766 bool Field; 4767 }; 4768 4769 void target() { 4770 MyClass MyObj; 4771 MyObj.Field = true; 4772 bool Foo = MyObj.getField(); 4773 // [[p]] 4774 } 4775 )"; 4776 runDataflow( 4777 Code, 4778 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4779 ASTContext &ASTCtx) { 4780 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4781 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4782 4783 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4784 ASSERT_THAT(FooDecl, NotNull()); 4785 4786 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4787 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4788 }, 4789 {BuiltinOptions{ContextSensitiveOptions{}}}); 4790 } 4791 4792 TEST(TransferTest, ContextSensitiveMethodSetter) { 4793 std::string Code = R"( 4794 class MyClass { 4795 public: 4796 void setField(bool Val) { Field = Val; } 4797 4798 bool Field; 4799 }; 4800 4801 void target() { 4802 MyClass MyObj; 4803 MyObj.setField(true); 4804 bool Foo = MyObj.Field; 4805 // [[p]] 4806 } 4807 )"; 4808 runDataflow( 4809 Code, 4810 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4811 ASTContext &ASTCtx) { 4812 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4813 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4814 4815 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4816 ASSERT_THAT(FooDecl, NotNull()); 4817 4818 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4819 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4820 }, 4821 {BuiltinOptions{ContextSensitiveOptions{}}}); 4822 } 4823 4824 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) { 4825 std::string Code = R"( 4826 class MyClass { 4827 public: 4828 bool getField() { return Field; } 4829 void setField(bool Val) { Field = Val; } 4830 4831 private: 4832 bool Field; 4833 }; 4834 4835 void target() { 4836 MyClass MyObj; 4837 MyObj.setField(true); 4838 bool Foo = MyObj.getField(); 4839 // [[p]] 4840 } 4841 )"; 4842 runDataflow( 4843 Code, 4844 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4845 ASTContext &ASTCtx) { 4846 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4847 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4848 4849 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4850 ASSERT_THAT(FooDecl, NotNull()); 4851 4852 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4853 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4854 }, 4855 {BuiltinOptions{ContextSensitiveOptions{}}}); 4856 } 4857 4858 4859 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) { 4860 std::string Code = R"( 4861 class MyClass { 4862 public: 4863 void Inner() { MyField = true; } 4864 void Outer() { Inner(); } 4865 4866 bool MyField; 4867 }; 4868 4869 void target() { 4870 MyClass MyObj; 4871 MyObj.Outer(); 4872 bool Foo = MyObj.MyField; 4873 // [[p]] 4874 } 4875 )"; 4876 runDataflow( 4877 Code, 4878 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4879 ASTContext &ASTCtx) { 4880 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4881 ; 4882 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4883 4884 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4885 ASSERT_THAT(FooDecl, NotNull()); 4886 4887 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4888 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4889 }, 4890 {BuiltinOptions{ContextSensitiveOptions{}}}); 4891 } 4892 4893 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) { 4894 std::string Code = R"( 4895 class MyClass { 4896 public: 4897 bool Inner() { return MyField; } 4898 bool Outer() { return Inner(); } 4899 4900 bool MyField; 4901 }; 4902 4903 void target() { 4904 MyClass MyObj; 4905 MyObj.MyField = true; 4906 bool Foo = MyObj.Outer(); 4907 // [[p]] 4908 } 4909 )"; 4910 runDataflow( 4911 Code, 4912 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4913 ASTContext &ASTCtx) { 4914 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4915 ; 4916 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4917 4918 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4919 ASSERT_THAT(FooDecl, NotNull()); 4920 4921 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4922 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4923 }, 4924 {BuiltinOptions{ContextSensitiveOptions{}}}); 4925 } 4926 4927 TEST(TransferTest, ContextSensitiveConstructorBody) { 4928 std::string Code = R"( 4929 class MyClass { 4930 public: 4931 MyClass() { MyField = true; } 4932 4933 bool MyField; 4934 }; 4935 4936 void target() { 4937 MyClass MyObj; 4938 bool Foo = MyObj.MyField; 4939 // [[p]] 4940 } 4941 )"; 4942 runDataflow( 4943 Code, 4944 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4945 ASTContext &ASTCtx) { 4946 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4947 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4948 4949 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4950 ASSERT_THAT(FooDecl, NotNull()); 4951 4952 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4953 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4954 }, 4955 {BuiltinOptions{ContextSensitiveOptions{}}}); 4956 } 4957 4958 TEST(TransferTest, ContextSensitiveConstructorInitializer) { 4959 std::string Code = R"( 4960 class MyClass { 4961 public: 4962 MyClass() : MyField(true) {} 4963 4964 bool MyField; 4965 }; 4966 4967 void target() { 4968 MyClass MyObj; 4969 bool Foo = MyObj.MyField; 4970 // [[p]] 4971 } 4972 )"; 4973 runDataflow( 4974 Code, 4975 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 4976 ASTContext &ASTCtx) { 4977 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 4978 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 4979 4980 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 4981 ASSERT_THAT(FooDecl, NotNull()); 4982 4983 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 4984 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 4985 }, 4986 {BuiltinOptions{ContextSensitiveOptions{}}}); 4987 } 4988 4989 TEST(TransferTest, ContextSensitiveConstructorDefault) { 4990 std::string Code = R"( 4991 class MyClass { 4992 public: 4993 MyClass() = default; 4994 4995 bool MyField = true; 4996 }; 4997 4998 void target() { 4999 MyClass MyObj; 5000 bool Foo = MyObj.MyField; 5001 // [[p]] 5002 } 5003 )"; 5004 runDataflow( 5005 Code, 5006 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5007 ASTContext &ASTCtx) { 5008 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5009 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5010 5011 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo"); 5012 ASSERT_THAT(FooDecl, NotNull()); 5013 5014 auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl)); 5015 EXPECT_TRUE(Env.flowConditionImplies(FooVal)); 5016 }, 5017 {BuiltinOptions{ContextSensitiveOptions{}}}); 5018 } 5019 5020 TEST(TransferTest, UnnamedBitfieldInitializer) { 5021 std::string Code = R"( 5022 struct B {}; 5023 struct A { 5024 unsigned a; 5025 unsigned : 4; 5026 unsigned c; 5027 B b; 5028 }; 5029 void target() { 5030 A a = {}; 5031 A test = a; 5032 (void)test.c; 5033 } 5034 )"; 5035 runDataflow( 5036 Code, 5037 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5038 ASTContext &ASTCtx) { 5039 // This doesn't need a body because this test was crashing the framework 5040 // before handling correctly Unnamed bitfields in `InitListExpr`. 5041 }); 5042 } 5043 5044 // Repro for a crash that used to occur when we call a `noreturn` function 5045 // within one of the operands of a `&&` or `||` operator. 5046 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) { 5047 std::string Code = R"( 5048 __attribute__((noreturn)) int doesnt_return(); 5049 bool some_condition(); 5050 void target(bool b1, bool b2) { 5051 // Neither of these should crash. In addition, if we don't terminate the 5052 // program, we know that the operators need to trigger the short-circuit 5053 // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr` 5054 // will be true. 5055 bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0; 5056 bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0; 5057 5058 // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the 5059 // entire expression unreachable. So we know that in both of the following 5060 // cases, if `target()` terminates, the `else` branch was taken. 5061 bool NoreturnOnLhsMakesAndUnreachable = false; 5062 if (some_condition()) 5063 doesnt_return() > 0 && some_condition(); 5064 else 5065 NoreturnOnLhsMakesAndUnreachable = true; 5066 5067 bool NoreturnOnLhsMakesOrUnreachable = false; 5068 if (some_condition()) 5069 doesnt_return() > 0 || some_condition(); 5070 else 5071 NoreturnOnLhsMakesOrUnreachable = true; 5072 5073 // [[p]] 5074 } 5075 )"; 5076 runDataflow( 5077 Code, 5078 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5079 ASTContext &ASTCtx) { 5080 ASSERT_THAT(Results.keys(), UnorderedElementsAre("p")); 5081 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5082 5083 // Check that [[p]] is reachable with a non-false flow condition. 5084 EXPECT_FALSE(Env.flowConditionImplies(Env.getBoolLiteralValue(false))); 5085 5086 auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1"); 5087 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(B1))); 5088 5089 auto &NoreturnOnRhsOfAnd = 5090 getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd"); 5091 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(NoreturnOnRhsOfAnd))); 5092 5093 auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2"); 5094 EXPECT_TRUE(Env.flowConditionImplies(B2)); 5095 5096 auto &NoreturnOnRhsOfOr = 5097 getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr"); 5098 EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnRhsOfOr)); 5099 5100 auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>( 5101 ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable"); 5102 EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesAndUnreachable)); 5103 5104 auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>( 5105 ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable"); 5106 EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesOrUnreachable)); 5107 }); 5108 } 5109 5110 TEST(TransferTest, NewExpressions) { 5111 std::string Code = R"( 5112 void target() { 5113 int *p = new int(42); 5114 // [[after_new]] 5115 } 5116 )"; 5117 runDataflow( 5118 Code, 5119 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5120 ASTContext &ASTCtx) { 5121 const Environment &Env = 5122 getEnvironmentAtAnnotation(Results, "after_new"); 5123 5124 auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p"); 5125 5126 EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull()); 5127 }); 5128 } 5129 5130 TEST(TransferTest, NewExpressions_Structs) { 5131 std::string Code = R"( 5132 struct Inner { 5133 int InnerField; 5134 }; 5135 5136 struct Outer { 5137 Inner OuterField; 5138 }; 5139 5140 void target() { 5141 Outer *p = new Outer; 5142 // Access the fields to make sure the analysis actually generates children 5143 // for them in the `AggregateStorageLoc` and `StructValue`. 5144 p->OuterField.InnerField; 5145 // [[after_new]] 5146 } 5147 )"; 5148 runDataflow( 5149 Code, 5150 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5151 ASTContext &ASTCtx) { 5152 const Environment &Env = 5153 getEnvironmentAtAnnotation(Results, "after_new"); 5154 5155 const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField"); 5156 const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField"); 5157 5158 auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p"); 5159 5160 auto &OuterLoc = cast<AggregateStorageLocation>(P.getPointeeLoc()); 5161 auto &OuterFieldLoc = 5162 cast<AggregateStorageLocation>(OuterLoc.getChild(*OuterField)); 5163 auto &InnerFieldLoc = OuterFieldLoc.getChild(*InnerField); 5164 5165 // Values for the struct and all fields exist after the new. 5166 EXPECT_THAT(Env.getValue(OuterLoc), NotNull()); 5167 EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull()); 5168 EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull()); 5169 }); 5170 } 5171 5172 TEST(TransferTest, FunctionToPointerDecayHasValue) { 5173 std::string Code = R"( 5174 struct A { static void static_member_func(); }; 5175 void target() { 5176 // To check that we're treating function-to-pointer decay correctly, 5177 // create two pointers, then verify they refer to the same storage 5178 // location. 5179 // We need to do the test this way because even if an initializer (in this 5180 // case, the function-to-pointer decay) does not create a value, we still 5181 // create a value for the variable. 5182 void (*non_member_p1)() = target; 5183 void (*non_member_p2)() = target; 5184 5185 // Do the same thing but for a static member function. 5186 void (*member_p1)() = A::static_member_func; 5187 void (*member_p2)() = A::static_member_func; 5188 // [[p]] 5189 } 5190 )"; 5191 runDataflow( 5192 Code, 5193 [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results, 5194 ASTContext &ASTCtx) { 5195 const Environment &Env = getEnvironmentAtAnnotation(Results, "p"); 5196 5197 auto &NonMemberP1 = 5198 getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1"); 5199 auto &NonMemberP2 = 5200 getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2"); 5201 EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc()); 5202 5203 auto &MemberP1 = 5204 getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1"); 5205 auto &MemberP2 = 5206 getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2"); 5207 EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc()); 5208 }); 5209 } 5210 5211 } // namespace 5212