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