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