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