xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision fcd020d561f28a2b33b6cc12a5a0164a6d5e4172)
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/RecordOps.h"
17 #include "clang/Analysis/FlowSensitive/StorageLocation.h"
18 #include "clang/Analysis/FlowSensitive/Value.h"
19 #include "clang/Basic/LangStandard.h"
20 #include "clang/Testing/TestAST.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/StringRef.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 clang {
31 namespace dataflow {
32 namespace {
33 AST_MATCHER(FunctionDecl, isTemplated) { return Node.isTemplated(); }
34 } // namespace
35 } // namespace dataflow
36 } // namespace clang
37 
38 namespace {
39 
40 using namespace clang;
41 using namespace dataflow;
42 using namespace test;
43 using ::testing::Eq;
44 using ::testing::IsNull;
45 using ::testing::Ne;
46 using ::testing::NotNull;
47 using ::testing::UnorderedElementsAre;
48 
49 // Declares a minimal coroutine library.
50 constexpr llvm::StringRef CoroutineLibrary = R"cc(
51 struct promise;
52 struct task;
53 
54 namespace std {
55 template <class, class...>
56 struct coroutine_traits {};
57 template <>
58 struct coroutine_traits<task> {
59     using promise_type = promise;
60 };
61 
62 template <class Promise = void>
63 struct coroutine_handle {
64     static constexpr coroutine_handle from_address(void *addr) { return {}; }
65 };
66 }  // namespace std
67 
68 struct awaitable {
69     bool await_ready() const noexcept;
70     void await_suspend(std::coroutine_handle<promise>) const noexcept;
71     void await_resume() const noexcept;
72 };
73 struct task {};
74 struct promise {
75     task get_return_object();
76     awaitable initial_suspend();
77     awaitable final_suspend() noexcept;
78     void unhandled_exception();
79     void return_void();
80 };
81 )cc";
82 
83 void runDataflow(
84     llvm::StringRef Code,
85     std::function<
86         void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
87              ASTContext &)>
88         VerifyResults,
89     DataflowAnalysisOptions Options,
90     LangStandard::Kind Std = LangStandard::lang_cxx17,
91     llvm::StringRef TargetFun = "target") {
92   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code, VerifyResults, Options,
93                                                   Std, TargetFun),
94                     llvm::Succeeded());
95 }
96 
97 void runDataflow(
98     llvm::StringRef Code,
99     std::function<
100         void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
101              ASTContext &)>
102         VerifyResults,
103     LangStandard::Kind Std = LangStandard::lang_cxx17,
104     bool ApplyBuiltinTransfer = true, llvm::StringRef TargetFun = "target") {
105   runDataflow(Code, std::move(VerifyResults),
106               {ApplyBuiltinTransfer ? BuiltinOptions{}
107                                     : std::optional<BuiltinOptions>()},
108               Std, TargetFun);
109 }
110 
111 void runDataflowOnLambda(
112     llvm::StringRef Code,
113     std::function<
114         void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
115              ASTContext &)>
116         VerifyResults,
117     DataflowAnalysisOptions Options,
118     LangStandard::Kind Std = LangStandard::lang_cxx17) {
119   ASSERT_THAT_ERROR(
120       checkDataflowWithNoopAnalysis(
121           Code,
122           ast_matchers::hasDeclContext(
123               ast_matchers::cxxRecordDecl(ast_matchers::isLambda())),
124           VerifyResults, Options, Std),
125       llvm::Succeeded());
126 }
127 
128 void runDataflowOnLambda(
129     llvm::StringRef Code,
130     std::function<
131         void(const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
132              ASTContext &)>
133         VerifyResults,
134     LangStandard::Kind Std = LangStandard::lang_cxx17,
135     bool ApplyBuiltinTransfer = true) {
136   runDataflowOnLambda(Code, std::move(VerifyResults),
137                       {ApplyBuiltinTransfer ? BuiltinOptions{}
138                                             : std::optional<BuiltinOptions>()},
139                       Std);
140 }
141 
142 const Formula &getFormula(const ValueDecl &D, const Environment &Env) {
143   return cast<BoolValue>(Env.getValue(D))->formula();
144 }
145 
146 TEST(TransferTest, CNotSupported) {
147   TestInputs Inputs("void target() {}");
148   Inputs.Language = TestLanguage::Lang_C89;
149   clang::TestAST AST(Inputs);
150   const auto *Target =
151       cast<FunctionDecl>(test::findValueDecl(AST.context(), "target"));
152   ASSERT_THAT_ERROR(AdornedCFG::build(*Target).takeError(),
153                     llvm::FailedWithMessage("Can only analyze C++"));
154 }
155 
156 TEST(TransferTest, ObjectiveCNotSupported) {
157   TestInputs Inputs("void target() {}");
158   Inputs.Language = TestLanguage::Lang_OBJC;
159   clang::TestAST AST(Inputs);
160   const auto *Target =
161       cast<FunctionDecl>(test::findValueDecl(AST.context(), "target"));
162   ASSERT_THAT_ERROR(AdornedCFG::build(*Target).takeError(),
163                     llvm::FailedWithMessage("Can only analyze C++"));
164 }
165 
166 TEST(TransferTest, ObjectiveCXXNotSupported) {
167   TestInputs Inputs("void target() {}");
168   Inputs.Language = TestLanguage::Lang_OBJCXX;
169   clang::TestAST AST(Inputs);
170   const auto *Target =
171       cast<FunctionDecl>(test::findValueDecl(AST.context(), "target"));
172   ASSERT_THAT_ERROR(AdornedCFG::build(*Target).takeError(),
173                     llvm::FailedWithMessage("Can only analyze C++"));
174 }
175 
176 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
177   std::string Code = R"(
178     void target() {
179       int Foo;
180       // [[p]]
181     }
182   )";
183   runDataflow(
184       Code,
185       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
186          ASTContext &ASTCtx) {
187         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
188         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
189 
190         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
191         ASSERT_THAT(FooDecl, NotNull());
192 
193         EXPECT_EQ(Env.getStorageLocation(*FooDecl), nullptr);
194       },
195       LangStandard::lang_cxx17,
196       /*ApplyBuiltinTransfer=*/false);
197 }
198 
199 TEST(TransferTest, BoolVarDecl) {
200   std::string Code = R"(
201     void target() {
202       bool Foo;
203       // [[p]]
204     }
205   )";
206   runDataflow(
207       Code,
208       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
209          ASTContext &ASTCtx) {
210         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
211         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
212 
213         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
214         ASSERT_THAT(FooDecl, NotNull());
215 
216         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
217         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
218 
219         const Value *FooVal = Env.getValue(*FooLoc);
220         EXPECT_TRUE(isa_and_nonnull<BoolValue>(FooVal));
221       });
222 }
223 
224 TEST(TransferTest, IntVarDecl) {
225   std::string Code = R"(
226     void target() {
227       int Foo;
228       // [[p]]
229     }
230   )";
231   runDataflow(
232       Code,
233       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
234          ASTContext &ASTCtx) {
235         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
236         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
237 
238         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
239         ASSERT_THAT(FooDecl, NotNull());
240 
241         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
242         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
243 
244         const Value *FooVal = Env.getValue(*FooLoc);
245         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
246       });
247 }
248 
249 TEST(TransferTest, StructIncomplete) {
250   std::string Code = R"(
251     struct A;
252 
253     void target() {
254       A* Foo;
255       // [[p]]
256     }
257   )";
258   runDataflow(
259       Code,
260       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
261          ASTContext &ASTCtx) {
262         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
263         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
264 
265         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
266         ASSERT_THAT(FooDecl, NotNull());
267         auto *FooValue = dyn_cast_or_null<PointerValue>(Env.getValue(*FooDecl));
268         ASSERT_THAT(FooValue, NotNull());
269 
270         EXPECT_TRUE(isa<RecordStorageLocation>(FooValue->getPointeeLoc()));
271       });
272 }
273 
274 // As a memory optimization, we prevent modeling fields nested below a certain
275 // level (currently, depth 3). This test verifies this lack of modeling. We also
276 // include a regression test for the case that the unmodeled field is a
277 // reference to a struct; previously, we crashed when accessing such a field.
278 TEST(TransferTest, StructFieldUnmodeled) {
279   std::string Code = R"(
280     struct S { int X; };
281     S GlobalS;
282     struct A { S &Unmodeled = GlobalS; };
283     struct B { A F3; };
284     struct C { B F2; };
285     struct D { C F1; };
286 
287     void target() {
288       D Bar;
289       A &Foo = Bar.F1.F2.F3;
290       int Zab = Foo.Unmodeled.X;
291       // [[p]]
292     }
293   )";
294   runDataflow(
295       Code,
296       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
297          ASTContext &ASTCtx) {
298         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
299         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
300 
301         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
302         ASSERT_THAT(FooDecl, NotNull());
303         QualType FooReferentType = FooDecl->getType()->getPointeeType();
304         ASSERT_TRUE(FooReferentType->isStructureType());
305         auto FooFields = FooReferentType->getAsRecordDecl()->fields();
306 
307         FieldDecl *UnmodeledDecl = nullptr;
308         for (FieldDecl *Field : FooFields) {
309           if (Field->getNameAsString() == "Unmodeled") {
310             UnmodeledDecl = Field;
311           } else {
312             FAIL() << "Unexpected field: " << Field->getNameAsString();
313           }
314         }
315         ASSERT_THAT(UnmodeledDecl, NotNull());
316 
317         const auto *FooLoc =
318             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
319         const auto &UnmodeledLoc =
320             *cast<RecordStorageLocation>(FooLoc->getChild(*UnmodeledDecl));
321         StorageLocation &UnmodeledXLoc = getFieldLoc(UnmodeledLoc, "X", ASTCtx);
322         EXPECT_EQ(Env.getValue(UnmodeledXLoc), nullptr);
323 
324         const ValueDecl *ZabDecl = findValueDecl(ASTCtx, "Zab");
325         ASSERT_THAT(ZabDecl, NotNull());
326         EXPECT_THAT(Env.getValue(*ZabDecl), NotNull());
327       });
328 }
329 
330 TEST(TransferTest, StructVarDecl) {
331   std::string Code = R"(
332     struct A {
333       int Bar;
334     };
335 
336     void target() {
337       A Foo;
338       (void)Foo.Bar;
339       // [[p]]
340     }
341   )";
342   runDataflow(
343       Code,
344       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
345          ASTContext &ASTCtx) {
346         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
347         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
348 
349         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
350         ASSERT_THAT(FooDecl, NotNull());
351 
352         ASSERT_TRUE(FooDecl->getType()->isStructureType());
353         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
354 
355         FieldDecl *BarDecl = nullptr;
356         for (FieldDecl *Field : FooFields) {
357           if (Field->getNameAsString() == "Bar") {
358             BarDecl = Field;
359           } else {
360             FAIL() << "Unexpected field: " << Field->getNameAsString();
361           }
362         }
363         ASSERT_THAT(BarDecl, NotNull());
364 
365         const auto *FooLoc =
366             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
367         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
368       });
369 }
370 
371 TEST(TransferTest, StructVarDeclWithInit) {
372   std::string Code = R"(
373     struct A {
374       int Bar;
375     };
376 
377     A Gen();
378 
379     void target() {
380       A Foo = Gen();
381       (void)Foo.Bar;
382       // [[p]]
383     }
384   )";
385   runDataflow(
386       Code,
387       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
388          ASTContext &ASTCtx) {
389         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
390         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
391 
392         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
393         ASSERT_THAT(FooDecl, NotNull());
394 
395         ASSERT_TRUE(FooDecl->getType()->isStructureType());
396         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
397 
398         FieldDecl *BarDecl = nullptr;
399         for (FieldDecl *Field : FooFields) {
400           if (Field->getNameAsString() == "Bar") {
401             BarDecl = Field;
402           } else {
403             FAIL() << "Unexpected field: " << Field->getNameAsString();
404           }
405         }
406         ASSERT_THAT(BarDecl, NotNull());
407 
408         const auto *FooLoc =
409             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
410         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
411       });
412 }
413 
414 TEST(TransferTest, StructArrayVarDecl) {
415   std::string Code = R"(
416     struct A {};
417 
418     void target() {
419       A Array[2];
420       // [[p]]
421     }
422   )";
423   runDataflow(
424       Code,
425       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
426          ASTContext &ASTCtx) {
427         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
428 
429         const ValueDecl *ArrayDecl = findValueDecl(ASTCtx, "Array");
430 
431         // We currently don't create values for arrays.
432         ASSERT_THAT(Env.getValue(*ArrayDecl), IsNull());
433       });
434 }
435 
436 TEST(TransferTest, ClassVarDecl) {
437   std::string Code = R"(
438     class A {
439      public:
440       int Bar;
441     };
442 
443     void target() {
444       A Foo;
445       (void)Foo.Bar;
446       // [[p]]
447     }
448   )";
449   runDataflow(
450       Code,
451       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
452          ASTContext &ASTCtx) {
453         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
454         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
455 
456         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
457         ASSERT_THAT(FooDecl, NotNull());
458 
459         ASSERT_TRUE(FooDecl->getType()->isClassType());
460         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
461 
462         FieldDecl *BarDecl = nullptr;
463         for (FieldDecl *Field : FooFields) {
464           if (Field->getNameAsString() == "Bar") {
465             BarDecl = Field;
466           } else {
467             FAIL() << "Unexpected field: " << Field->getNameAsString();
468           }
469         }
470         ASSERT_THAT(BarDecl, NotNull());
471 
472         const auto *FooLoc =
473             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
474         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
475       });
476 }
477 
478 TEST(TransferTest, ReferenceVarDecl) {
479   std::string Code = R"(
480     struct A {};
481 
482     A &getA();
483 
484     void target() {
485       A &Foo = getA();
486       // [[p]]
487     }
488   )";
489   runDataflow(
490       Code,
491       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
492          ASTContext &ASTCtx) {
493         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
494         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
495 
496         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
497         ASSERT_THAT(FooDecl, NotNull());
498 
499         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
500         ASSERT_TRUE(isa_and_nonnull<RecordStorageLocation>(FooLoc));
501       });
502 }
503 
504 TEST(TransferTest, SelfReferentialReferenceVarDecl) {
505   std::string Code = R"(
506     struct A;
507 
508     struct B {};
509 
510     struct C {
511       A &FooRef;
512       A *FooPtr;
513       B &BazRef;
514       B *BazPtr;
515     };
516 
517     struct A {
518       C &Bar;
519     };
520 
521     A &getA();
522 
523     void target() {
524       A &Foo = getA();
525       (void)Foo.Bar.FooRef;
526       (void)Foo.Bar.FooPtr;
527       (void)Foo.Bar.BazRef;
528       (void)Foo.Bar.BazPtr;
529       // [[p]]
530     }
531   )";
532   runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>>
533                            &Results,
534                        ASTContext &ASTCtx) {
535     ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
536     const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
537 
538     const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
539     ASSERT_THAT(FooDecl, NotNull());
540 
541     ASSERT_TRUE(FooDecl->getType()->isReferenceType());
542     ASSERT_TRUE(FooDecl->getType().getNonReferenceType()->isStructureType());
543     const auto FooFields =
544         FooDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields();
545 
546     FieldDecl *BarDecl = nullptr;
547     for (FieldDecl *Field : FooFields) {
548       if (Field->getNameAsString() == "Bar") {
549         BarDecl = Field;
550       } else {
551         FAIL() << "Unexpected field: " << Field->getNameAsString();
552       }
553     }
554     ASSERT_THAT(BarDecl, NotNull());
555 
556     ASSERT_TRUE(BarDecl->getType()->isReferenceType());
557     ASSERT_TRUE(BarDecl->getType().getNonReferenceType()->isStructureType());
558     const auto BarFields =
559         BarDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields();
560 
561     FieldDecl *FooRefDecl = nullptr;
562     FieldDecl *FooPtrDecl = nullptr;
563     FieldDecl *BazRefDecl = nullptr;
564     FieldDecl *BazPtrDecl = nullptr;
565     for (FieldDecl *Field : BarFields) {
566       if (Field->getNameAsString() == "FooRef") {
567         FooRefDecl = Field;
568       } else if (Field->getNameAsString() == "FooPtr") {
569         FooPtrDecl = Field;
570       } else if (Field->getNameAsString() == "BazRef") {
571         BazRefDecl = Field;
572       } else if (Field->getNameAsString() == "BazPtr") {
573         BazPtrDecl = Field;
574       } else {
575         FAIL() << "Unexpected field: " << Field->getNameAsString();
576       }
577     }
578     ASSERT_THAT(FooRefDecl, NotNull());
579     ASSERT_THAT(FooPtrDecl, NotNull());
580     ASSERT_THAT(BazRefDecl, NotNull());
581     ASSERT_THAT(BazPtrDecl, NotNull());
582 
583     const auto &FooLoc =
584         *cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
585 
586     const auto &BarLoc =
587         *cast<RecordStorageLocation>(FooLoc.getChild(*BarDecl));
588 
589     const auto &FooReferentLoc =
590         *cast<RecordStorageLocation>(BarLoc.getChild(*FooRefDecl));
591     EXPECT_EQ(Env.getValue(*cast<RecordStorageLocation>(
592                                 FooReferentLoc.getChild(*BarDecl))
593                                 ->getChild(*FooPtrDecl)),
594               nullptr);
595 
596     const auto &FooPtrVal =
597         *cast<PointerValue>(getFieldValue(&BarLoc, *FooPtrDecl, Env));
598     const auto &FooPtrPointeeLoc =
599         cast<RecordStorageLocation>(FooPtrVal.getPointeeLoc());
600     EXPECT_EQ(Env.getValue(*cast<RecordStorageLocation>(
601                                 FooPtrPointeeLoc.getChild(*BarDecl))
602                                 ->getChild(*FooPtrDecl)),
603               nullptr);
604 
605     EXPECT_TRUE(isa<PointerValue>(getFieldValue(&BarLoc, *BazPtrDecl, Env)));
606   });
607 }
608 
609 TEST(TransferTest, PointerVarDecl) {
610   std::string Code = R"(
611     struct A {};
612 
613     A *getA();
614 
615     void target() {
616       A *Foo = getA();
617       // [[p]]
618     }
619   )";
620   runDataflow(
621       Code,
622       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
623          ASTContext &ASTCtx) {
624         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
625         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
626 
627         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
628         ASSERT_THAT(FooDecl, NotNull());
629 
630         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
631         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
632 
633         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
634         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
635         EXPECT_TRUE(isa<RecordStorageLocation>(&FooPointeeLoc));
636       });
637 }
638 
639 TEST(TransferTest, SelfReferentialPointerVarDecl) {
640   std::string Code = R"(
641     struct A;
642 
643     struct B {};
644 
645     struct C {
646       A &FooRef;
647       A *FooPtr;
648       B &BazRef;
649       B *BazPtr;
650     };
651 
652     struct A {
653       C *Bar;
654     };
655 
656     A *getA();
657 
658     void target() {
659       A *Foo = getA();
660       (void)Foo->Bar->FooRef;
661       (void)Foo->Bar->FooPtr;
662       (void)Foo->Bar->BazRef;
663       (void)Foo->Bar->BazPtr;
664       // [[p]]
665     }
666   )";
667   runDataflow(
668       Code,
669       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
670          ASTContext &ASTCtx) {
671         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
672         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
673 
674         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
675         ASSERT_THAT(FooDecl, NotNull());
676 
677         ASSERT_TRUE(FooDecl->getType()->isPointerType());
678         ASSERT_TRUE(FooDecl->getType()
679                         ->getAs<PointerType>()
680                         ->getPointeeType()
681                         ->isStructureType());
682         const auto FooFields = FooDecl->getType()
683                                    ->getAs<PointerType>()
684                                    ->getPointeeType()
685                                    ->getAsRecordDecl()
686                                    ->fields();
687 
688         FieldDecl *BarDecl = nullptr;
689         for (FieldDecl *Field : FooFields) {
690           if (Field->getNameAsString() == "Bar") {
691             BarDecl = Field;
692           } else {
693             FAIL() << "Unexpected field: " << Field->getNameAsString();
694           }
695         }
696         ASSERT_THAT(BarDecl, NotNull());
697 
698         ASSERT_TRUE(BarDecl->getType()->isPointerType());
699         ASSERT_TRUE(BarDecl->getType()
700                         ->getAs<PointerType>()
701                         ->getPointeeType()
702                         ->isStructureType());
703         const auto BarFields = BarDecl->getType()
704                                    ->getAs<PointerType>()
705                                    ->getPointeeType()
706                                    ->getAsRecordDecl()
707                                    ->fields();
708 
709         FieldDecl *FooRefDecl = nullptr;
710         FieldDecl *FooPtrDecl = nullptr;
711         FieldDecl *BazRefDecl = nullptr;
712         FieldDecl *BazPtrDecl = nullptr;
713         for (FieldDecl *Field : BarFields) {
714           if (Field->getNameAsString() == "FooRef") {
715             FooRefDecl = Field;
716           } else if (Field->getNameAsString() == "FooPtr") {
717             FooPtrDecl = Field;
718           } else if (Field->getNameAsString() == "BazRef") {
719             BazRefDecl = Field;
720           } else if (Field->getNameAsString() == "BazPtr") {
721             BazPtrDecl = Field;
722           } else {
723             FAIL() << "Unexpected field: " << Field->getNameAsString();
724           }
725         }
726         ASSERT_THAT(FooRefDecl, NotNull());
727         ASSERT_THAT(FooPtrDecl, NotNull());
728         ASSERT_THAT(BazRefDecl, NotNull());
729         ASSERT_THAT(BazPtrDecl, NotNull());
730 
731         const auto &FooLoc =
732             *cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
733         const auto &FooVal = *cast<PointerValue>(Env.getValue(FooLoc));
734         const auto &FooPointeeLoc =
735             cast<RecordStorageLocation>(FooVal.getPointeeLoc());
736 
737         const auto &BarVal =
738             *cast<PointerValue>(getFieldValue(&FooPointeeLoc, *BarDecl, Env));
739         const auto &BarPointeeLoc =
740             cast<RecordStorageLocation>(BarVal.getPointeeLoc());
741 
742         const auto &FooPtrVal = *cast<PointerValue>(
743             getFieldValue(&BarPointeeLoc, *FooPtrDecl, Env));
744         const auto &FooPtrPointeeLoc =
745             cast<RecordStorageLocation>(FooPtrVal.getPointeeLoc());
746         EXPECT_EQ(Env.getValue(*FooPtrPointeeLoc.getChild(*BarDecl)), nullptr);
747 
748         EXPECT_TRUE(
749             isa<PointerValue>(getFieldValue(&BarPointeeLoc, *BazPtrDecl, Env)));
750       });
751 }
752 
753 TEST(TransferTest, DirectlySelfReferentialReference) {
754   std::string Code = R"(
755     struct target {
756       target() {
757         (void)0;
758         // [[p]]
759       }
760       target &self = *this;
761     };
762   )";
763   runDataflow(
764       Code,
765       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
766          ASTContext &ASTCtx) {
767         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
768         const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "self");
769 
770         auto *ThisLoc = Env.getThisPointeeStorageLocation();
771         ASSERT_EQ(ThisLoc->getChild(*SelfDecl), ThisLoc);
772       });
773 }
774 
775 TEST(TransferTest, MultipleVarsDecl) {
776   std::string Code = R"(
777     void target() {
778       int Foo, Bar;
779       (void)0;
780       // [[p]]
781     }
782   )";
783   runDataflow(
784       Code,
785       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
786          ASTContext &ASTCtx) {
787         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
788         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
789 
790         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
791         ASSERT_THAT(FooDecl, NotNull());
792 
793         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
794         ASSERT_THAT(BarDecl, NotNull());
795 
796         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
797         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
798 
799         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
800         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
801 
802         const Value *FooVal = Env.getValue(*FooLoc);
803         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
804 
805         const Value *BarVal = Env.getValue(*BarLoc);
806         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
807       });
808 }
809 
810 TEST(TransferTest, JoinVarDecl) {
811   std::string Code = R"(
812     void target(bool B) {
813       int Foo;
814       // [[p1]]
815       if (B) {
816         int Bar;
817         // [[p2]]
818       } else {
819         int Baz;
820         // [[p3]]
821       }
822       (void)0;
823       // [[p4]]
824     }
825   )";
826   runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>>
827                            &Results,
828                        ASTContext &ASTCtx) {
829     ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2", "p3", "p4"));
830 
831     const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
832     ASSERT_THAT(FooDecl, NotNull());
833 
834     const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
835     ASSERT_THAT(BarDecl, NotNull());
836 
837     const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
838     ASSERT_THAT(BazDecl, NotNull());
839 
840     const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
841 
842     const StorageLocation *FooLoc = Env1.getStorageLocation(*FooDecl);
843     EXPECT_THAT(FooLoc, NotNull());
844     EXPECT_THAT(Env1.getStorageLocation(*BarDecl), IsNull());
845     EXPECT_THAT(Env1.getStorageLocation(*BazDecl), IsNull());
846 
847     const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
848     EXPECT_EQ(Env2.getStorageLocation(*FooDecl), FooLoc);
849     EXPECT_THAT(Env2.getStorageLocation(*BarDecl), NotNull());
850     EXPECT_THAT(Env2.getStorageLocation(*BazDecl), IsNull());
851 
852     const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
853     EXPECT_EQ(Env3.getStorageLocation(*FooDecl), FooLoc);
854     EXPECT_THAT(Env3.getStorageLocation(*BarDecl), IsNull());
855     EXPECT_THAT(Env3.getStorageLocation(*BazDecl), NotNull());
856 
857     const Environment &Env4 = getEnvironmentAtAnnotation(Results, "p4");
858     EXPECT_EQ(Env4.getStorageLocation(*FooDecl), FooLoc);
859     EXPECT_THAT(Env4.getStorageLocation(*BarDecl), IsNull());
860     EXPECT_THAT(Env4.getStorageLocation(*BazDecl), IsNull());
861   });
862 }
863 
864 TEST(TransferTest, BinaryOperatorAssign) {
865   std::string Code = R"(
866     void target() {
867       int Foo;
868       int Bar;
869       (Bar) = (Foo);
870       // [[p]]
871     }
872   )";
873   runDataflow(
874       Code,
875       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
876          ASTContext &ASTCtx) {
877         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
878         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
879 
880         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
881         ASSERT_THAT(FooDecl, NotNull());
882 
883         const Value *FooVal = Env.getValue(*FooDecl);
884         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
885 
886         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
887         ASSERT_THAT(BarDecl, NotNull());
888 
889         EXPECT_EQ(Env.getValue(*BarDecl), FooVal);
890       });
891 }
892 
893 TEST(TransferTest, BinaryOperatorAssignIntegerLiteral) {
894   std::string Code = R"(
895     void target() {
896       int Foo = 1;
897       // [[before]]
898       Foo = 2;
899       // [[after]]
900     }
901   )";
902   runDataflow(
903       Code,
904       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
905          ASTContext &ASTCtx) {
906         const Environment &Before =
907             getEnvironmentAtAnnotation(Results, "before");
908         const Environment &After = getEnvironmentAtAnnotation(Results, "after");
909 
910         const auto &ValBefore =
911             getValueForDecl<IntegerValue>(ASTCtx, Before, "Foo");
912         const auto &ValAfter =
913             getValueForDecl<IntegerValue>(ASTCtx, After, "Foo");
914         EXPECT_NE(&ValBefore, &ValAfter);
915       });
916 }
917 
918 TEST(TransferTest, VarDeclInitAssign) {
919   std::string Code = R"(
920     void target() {
921       int Foo;
922       int Bar = Foo;
923       // [[p]]
924     }
925   )";
926   runDataflow(
927       Code,
928       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
929          ASTContext &ASTCtx) {
930         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
931         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
932 
933         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
934         ASSERT_THAT(FooDecl, NotNull());
935 
936         const Value *FooVal = Env.getValue(*FooDecl);
937         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
938 
939         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
940         ASSERT_THAT(BarDecl, NotNull());
941 
942         EXPECT_EQ(Env.getValue(*BarDecl), FooVal);
943       });
944 }
945 
946 TEST(TransferTest, VarDeclInitAssignChained) {
947   std::string Code = R"(
948     void target() {
949       int Foo;
950       int Bar;
951       int Baz = (Bar = Foo);
952       // [[p]]
953     }
954   )";
955   runDataflow(
956       Code,
957       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
958          ASTContext &ASTCtx) {
959         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
960         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
961 
962         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
963         ASSERT_THAT(FooDecl, NotNull());
964 
965         const Value *FooVal = Env.getValue(*FooDecl);
966         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
967 
968         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
969         ASSERT_THAT(BarDecl, NotNull());
970 
971         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
972         ASSERT_THAT(BazDecl, NotNull());
973 
974         EXPECT_EQ(Env.getValue(*BarDecl), FooVal);
975         EXPECT_EQ(Env.getValue(*BazDecl), FooVal);
976       });
977 }
978 
979 TEST(TransferTest, VarDeclInitAssignPtrDeref) {
980   std::string Code = R"(
981     void target() {
982       int Foo;
983       int *Bar;
984       *(Bar) = Foo;
985       int Baz = *(Bar);
986       // [[p]]
987     }
988   )";
989   runDataflow(
990       Code,
991       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
992          ASTContext &ASTCtx) {
993         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
994         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
995 
996         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
997         ASSERT_THAT(FooDecl, NotNull());
998 
999         const Value *FooVal = Env.getValue(*FooDecl);
1000         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
1001 
1002         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1003         ASSERT_THAT(BarDecl, NotNull());
1004 
1005         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
1006         EXPECT_EQ(Env.getValue(BarVal->getPointeeLoc()), FooVal);
1007 
1008         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1009         ASSERT_THAT(BazDecl, NotNull());
1010 
1011         EXPECT_EQ(Env.getValue(*BazDecl), FooVal);
1012       });
1013 }
1014 
1015 TEST(TransferTest, AssignToAndFromReference) {
1016   std::string Code = R"(
1017     void target() {
1018       int Foo;
1019       int Bar;
1020       int &Baz = Foo;
1021       // [[p1]]
1022       Baz = Bar;
1023       int Qux = Baz;
1024       int &Quux = Baz;
1025       // [[p2]]
1026     }
1027   )";
1028   runDataflow(
1029       Code,
1030       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1031          ASTContext &ASTCtx) {
1032         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
1033         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
1034         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
1035 
1036         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1037         ASSERT_THAT(FooDecl, NotNull());
1038 
1039         const Value *FooVal = Env1.getValue(*FooDecl);
1040         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
1041 
1042         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1043         ASSERT_THAT(BarDecl, NotNull());
1044 
1045         const Value *BarVal = Env1.getValue(*BarDecl);
1046         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1047 
1048         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1049         ASSERT_THAT(BazDecl, NotNull());
1050 
1051         EXPECT_EQ(Env1.getValue(*BazDecl), FooVal);
1052 
1053         EXPECT_EQ(Env2.getValue(*BazDecl), BarVal);
1054         EXPECT_EQ(Env2.getValue(*FooDecl), BarVal);
1055 
1056         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1057         ASSERT_THAT(QuxDecl, NotNull());
1058         EXPECT_EQ(Env2.getValue(*QuxDecl), BarVal);
1059 
1060         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1061         ASSERT_THAT(QuuxDecl, NotNull());
1062         EXPECT_EQ(Env2.getValue(*QuuxDecl), BarVal);
1063       });
1064 }
1065 
1066 TEST(TransferTest, MultipleParamDecls) {
1067   std::string Code = R"(
1068     void target(int Foo, int Bar) {
1069       (void)0;
1070       // [[p]]
1071     }
1072   )";
1073   runDataflow(
1074       Code,
1075       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1076          ASTContext &ASTCtx) {
1077         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1078         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1079 
1080         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1081         ASSERT_THAT(FooDecl, NotNull());
1082 
1083         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
1084         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1085 
1086         const Value *FooVal = Env.getValue(*FooLoc);
1087         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
1088 
1089         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1090         ASSERT_THAT(BarDecl, NotNull());
1091 
1092         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
1093         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1094 
1095         const Value *BarVal = Env.getValue(*BarLoc);
1096         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1097       });
1098 }
1099 
1100 TEST(TransferTest, StructParamDecl) {
1101   std::string Code = R"(
1102     struct A {
1103       int Bar;
1104     };
1105 
1106     void target(A Foo) {
1107       (void)Foo.Bar;
1108       // [[p]]
1109     }
1110   )";
1111   runDataflow(
1112       Code,
1113       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1114          ASTContext &ASTCtx) {
1115         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1116         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1117 
1118         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1119         ASSERT_THAT(FooDecl, NotNull());
1120 
1121         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1122         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1123 
1124         FieldDecl *BarDecl = nullptr;
1125         for (FieldDecl *Field : FooFields) {
1126           if (Field->getNameAsString() == "Bar") {
1127             BarDecl = Field;
1128           } else {
1129             FAIL() << "Unexpected field: " << Field->getNameAsString();
1130           }
1131         }
1132         ASSERT_THAT(BarDecl, NotNull());
1133 
1134         const auto *FooLoc =
1135             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1136         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
1137       });
1138 }
1139 
1140 TEST(TransferTest, ReferenceParamDecl) {
1141   std::string Code = R"(
1142     struct A {};
1143 
1144     void target(A &Foo) {
1145       (void)0;
1146       // [[p]]
1147     }
1148   )";
1149   runDataflow(
1150       Code,
1151       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1152          ASTContext &ASTCtx) {
1153         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1154         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1155 
1156         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1157         ASSERT_THAT(FooDecl, NotNull());
1158 
1159         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
1160         ASSERT_TRUE(isa_and_nonnull<RecordStorageLocation>(FooLoc));
1161       });
1162 }
1163 
1164 TEST(TransferTest, PointerParamDecl) {
1165   std::string Code = R"(
1166     struct A {};
1167 
1168     void target(A *Foo) {
1169       (void)0;
1170       // [[p]]
1171     }
1172   )";
1173   runDataflow(
1174       Code,
1175       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1176          ASTContext &ASTCtx) {
1177         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1178         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1179 
1180         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1181         ASSERT_THAT(FooDecl, NotNull());
1182 
1183         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
1184         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1185 
1186         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
1187         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
1188         EXPECT_TRUE(isa<RecordStorageLocation>(&FooPointeeLoc));
1189       });
1190 }
1191 
1192 TEST(TransferTest, StructMember) {
1193   std::string Code = R"(
1194     struct A {
1195       int Bar;
1196     };
1197 
1198     void target(A Foo) {
1199       int Baz = Foo.Bar;
1200       // [[p]]
1201     }
1202   )";
1203   runDataflow(
1204       Code,
1205       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1206          ASTContext &ASTCtx) {
1207         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1208         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1209 
1210         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1211         ASSERT_THAT(FooDecl, NotNull());
1212 
1213         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1214         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1215 
1216         FieldDecl *BarDecl = nullptr;
1217         for (FieldDecl *Field : FooFields) {
1218           if (Field->getNameAsString() == "Bar") {
1219             BarDecl = Field;
1220           } else {
1221             FAIL() << "Unexpected field: " << Field->getNameAsString();
1222           }
1223         }
1224         ASSERT_THAT(BarDecl, NotNull());
1225 
1226         const auto *FooLoc =
1227             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1228         const auto *BarVal =
1229             cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env));
1230 
1231         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1232         ASSERT_THAT(BazDecl, NotNull());
1233 
1234         EXPECT_EQ(Env.getValue(*BazDecl), BarVal);
1235       });
1236 }
1237 
1238 TEST(TransferTest, StructMemberEnum) {
1239   std::string Code = R"(
1240     struct A {
1241       int Bar;
1242       enum E { ONE, TWO };
1243     };
1244 
1245     void target(A Foo) {
1246       A::E Baz = Foo.ONE;
1247       // [[p]]
1248     }
1249   )";
1250   // Minimal expectations -- we're just testing that it doesn't crash, since
1251   // enums aren't interpreted.
1252   runDataflow(
1253       Code,
1254       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1255          ASTContext &ASTCtx) {
1256         EXPECT_THAT(Results.keys(), UnorderedElementsAre("p"));
1257       });
1258 }
1259 
1260 TEST(TransferTest, DerivedBaseMemberClass) {
1261   std::string Code = R"(
1262     class A {
1263       int ADefault;
1264     protected:
1265       int AProtected;
1266     private:
1267       int APrivate;
1268     public:
1269       int APublic;
1270 
1271     private:
1272       friend void target();
1273     };
1274 
1275     class B : public A {
1276       int BDefault;
1277     protected:
1278       int BProtected;
1279     private:
1280       int BPrivate;
1281 
1282     private:
1283       friend void target();
1284     };
1285 
1286     void target() {
1287       B Foo;
1288       (void)Foo.ADefault;
1289       (void)Foo.AProtected;
1290       (void)Foo.APrivate;
1291       (void)Foo.APublic;
1292       (void)Foo.BDefault;
1293       (void)Foo.BProtected;
1294       (void)Foo.BPrivate;
1295       // [[p]]
1296     }
1297   )";
1298   runDataflow(
1299       Code,
1300       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1301          ASTContext &ASTCtx) {
1302         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1303         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1304 
1305         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1306         ASSERT_THAT(FooDecl, NotNull());
1307         ASSERT_TRUE(FooDecl->getType()->isRecordType());
1308 
1309         // Derived-class fields.
1310         const FieldDecl *BDefaultDecl = nullptr;
1311         const FieldDecl *BProtectedDecl = nullptr;
1312         const FieldDecl *BPrivateDecl = nullptr;
1313         for (const FieldDecl *Field :
1314              FooDecl->getType()->getAsRecordDecl()->fields()) {
1315           if (Field->getNameAsString() == "BDefault") {
1316             BDefaultDecl = Field;
1317           } else if (Field->getNameAsString() == "BProtected") {
1318             BProtectedDecl = Field;
1319           } else if (Field->getNameAsString() == "BPrivate") {
1320             BPrivateDecl = Field;
1321           } else {
1322             FAIL() << "Unexpected field: " << Field->getNameAsString();
1323           }
1324         }
1325         ASSERT_THAT(BDefaultDecl, NotNull());
1326         ASSERT_THAT(BProtectedDecl, NotNull());
1327         ASSERT_THAT(BPrivateDecl, NotNull());
1328 
1329         // Base-class fields.
1330         const FieldDecl *ADefaultDecl = nullptr;
1331         const FieldDecl *APrivateDecl = nullptr;
1332         const FieldDecl *AProtectedDecl = nullptr;
1333         const FieldDecl *APublicDecl = nullptr;
1334         for (const clang::CXXBaseSpecifier &Base :
1335              FooDecl->getType()->getAsCXXRecordDecl()->bases()) {
1336           QualType BaseType = Base.getType();
1337           ASSERT_TRUE(BaseType->isRecordType());
1338           for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) {
1339             if (Field->getNameAsString() == "ADefault") {
1340               ADefaultDecl = Field;
1341             } else if (Field->getNameAsString() == "AProtected") {
1342               AProtectedDecl = Field;
1343             } else if (Field->getNameAsString() == "APrivate") {
1344               APrivateDecl = Field;
1345             } else if (Field->getNameAsString() == "APublic") {
1346               APublicDecl = Field;
1347             } else {
1348               FAIL() << "Unexpected field: " << Field->getNameAsString();
1349             }
1350           }
1351         }
1352         ASSERT_THAT(ADefaultDecl, NotNull());
1353         ASSERT_THAT(AProtectedDecl, NotNull());
1354         ASSERT_THAT(APrivateDecl, NotNull());
1355         ASSERT_THAT(APublicDecl, NotNull());
1356 
1357         ASSERT_TRUE(
1358             isa<RecordStorageLocation>(Env.getStorageLocation(*FooDecl)));
1359       });
1360 }
1361 
1362 static void derivedBaseMemberExpectations(
1363     const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1364     ASTContext &ASTCtx) {
1365   ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1366   const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1367 
1368   const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1369   ASSERT_THAT(FooDecl, NotNull());
1370 
1371   ASSERT_TRUE(FooDecl->getType()->isRecordType());
1372   const FieldDecl *BarDecl = nullptr;
1373   for (const clang::CXXBaseSpecifier &Base :
1374        FooDecl->getType()->getAsCXXRecordDecl()->bases()) {
1375     QualType BaseType = Base.getType();
1376     ASSERT_TRUE(BaseType->isStructureType());
1377 
1378     for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) {
1379       if (Field->getNameAsString() == "Bar") {
1380         BarDecl = Field;
1381       } else {
1382         FAIL() << "Unexpected field: " << Field->getNameAsString();
1383       }
1384     }
1385   }
1386   ASSERT_THAT(BarDecl, NotNull());
1387 
1388   const auto &FooLoc =
1389       *cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1390   EXPECT_NE(Env.getValue(*FooLoc.getChild(*BarDecl)), nullptr);
1391 }
1392 
1393 TEST(TransferTest, DerivedBaseMemberStructDefault) {
1394   std::string Code = R"(
1395     struct A {
1396       int Bar;
1397     };
1398     struct B : public A {
1399     };
1400 
1401     void target() {
1402       B Foo;
1403       (void)Foo.Bar;
1404       // [[p]]
1405     }
1406   )";
1407   runDataflow(Code, derivedBaseMemberExpectations);
1408 }
1409 
1410 TEST(TransferTest, DerivedBaseMemberPrivateFriend) {
1411   // Include an access to `Foo.Bar` to verify the analysis doesn't crash on that
1412   // access.
1413   std::string Code = R"(
1414     struct A {
1415     private:
1416       friend void target();
1417       int Bar;
1418     };
1419     struct B : public A {
1420     };
1421 
1422     void target() {
1423       B Foo;
1424       (void)Foo.Bar;
1425       // [[p]]
1426     }
1427   )";
1428   runDataflow(Code, derivedBaseMemberExpectations);
1429 }
1430 
1431 TEST(TransferTest, ClassMember) {
1432   std::string Code = R"(
1433     class A {
1434     public:
1435       int Bar;
1436     };
1437 
1438     void target(A Foo) {
1439       int Baz = Foo.Bar;
1440       // [[p]]
1441     }
1442   )";
1443   runDataflow(
1444       Code,
1445       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1446          ASTContext &ASTCtx) {
1447         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1448         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1449 
1450         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1451         ASSERT_THAT(FooDecl, NotNull());
1452 
1453         ASSERT_TRUE(FooDecl->getType()->isClassType());
1454         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1455 
1456         FieldDecl *BarDecl = nullptr;
1457         for (FieldDecl *Field : FooFields) {
1458           if (Field->getNameAsString() == "Bar") {
1459             BarDecl = Field;
1460           } else {
1461             FAIL() << "Unexpected field: " << Field->getNameAsString();
1462           }
1463         }
1464         ASSERT_THAT(BarDecl, NotNull());
1465 
1466         const auto *FooLoc =
1467             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1468         const auto *BarVal =
1469             cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env));
1470 
1471         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1472         ASSERT_THAT(BazDecl, NotNull());
1473 
1474         EXPECT_EQ(Env.getValue(*BazDecl), BarVal);
1475       });
1476 }
1477 
1478 TEST(TransferTest, BaseClassInitializer) {
1479   using ast_matchers::cxxConstructorDecl;
1480   using ast_matchers::hasName;
1481   using ast_matchers::ofClass;
1482 
1483   std::string Code = R"(
1484     class A {
1485     public:
1486       A(int I) : Bar(I) {}
1487       int Bar;
1488     };
1489 
1490     class B : public A {
1491     public:
1492       B(int I) : A(I) {
1493         (void)0;
1494         // [[p]]
1495       }
1496     };
1497   )";
1498   ASSERT_THAT_ERROR(
1499       checkDataflow<NoopAnalysis>(
1500           AnalysisInputs<NoopAnalysis>(
1501               Code, cxxConstructorDecl(ofClass(hasName("B"))),
1502               [](ASTContext &C, Environment &) { return NoopAnalysis(C); })
1503               .withASTBuildArgs(
1504                   {"-fsyntax-only", "-fno-delayed-template-parsing",
1505                    "-std=" + std::string(LangStandard::getLangStandardForKind(
1506                                              LangStandard::lang_cxx17)
1507                                              .getName())}),
1508           /*VerifyResults=*/
1509           [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1510              const AnalysisOutputs &) {
1511             // Regression test to verify that base-class initializers do not
1512             // trigger an assertion. If we add support for such initializers in
1513             // the future, we can expand this test to check more specific
1514             // properties.
1515             EXPECT_THAT(Results.keys(), UnorderedElementsAre("p"));
1516           }),
1517       llvm::Succeeded());
1518 }
1519 
1520 TEST(TransferTest, FieldsDontHaveValuesInConstructor) {
1521   // In a constructor, unlike in regular member functions, we don't want fields
1522   // to be pre-initialized with values, because doing so is the job of the
1523   // constructor.
1524   std::string Code = R"(
1525     struct target {
1526       target() {
1527         0;
1528         // [[p]]
1529         // Mention the field so it is modeled;
1530         Val;
1531       }
1532 
1533       int Val;
1534     };
1535  )";
1536   runDataflow(
1537       Code,
1538       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1539          ASTContext &ASTCtx) {
1540         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1541         EXPECT_EQ(getFieldValue(Env.getThisPointeeStorageLocation(), "Val",
1542                                 ASTCtx, Env),
1543                   nullptr);
1544       });
1545 }
1546 
1547 TEST(TransferTest, FieldsDontHaveValuesInConstructorWithBaseClass) {
1548   // See above, but for a class with a base class.
1549   std::string Code = R"(
1550     struct Base {
1551         int BaseVal;
1552     };
1553 
1554     struct target  : public Base {
1555       target() {
1556         0;
1557         // [[p]]
1558         // Mention the fields so they are modeled.
1559         BaseVal;
1560         Val;
1561       }
1562 
1563       int Val;
1564     };
1565  )";
1566   runDataflow(
1567       Code,
1568       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1569          ASTContext &ASTCtx) {
1570         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1571         // The field of the base class should already have been initialized with
1572         // a value by the base constructor.
1573         EXPECT_NE(getFieldValue(Env.getThisPointeeStorageLocation(), "BaseVal",
1574                                 ASTCtx, Env),
1575                   nullptr);
1576         EXPECT_EQ(getFieldValue(Env.getThisPointeeStorageLocation(), "Val",
1577                                 ASTCtx, Env),
1578                   nullptr);
1579       });
1580 }
1581 
1582 TEST(TransferTest, StructModeledFieldsWithAccessor) {
1583   std::string Code = R"(
1584     class S {
1585       int *Ptr;
1586       int *PtrNonConst;
1587       int Int;
1588       int IntWithInc;
1589       int IntNotAccessed;
1590       int IntRef;
1591     public:
1592       int *getPtr() const { return Ptr; }
1593       int *getPtrNonConst() { return PtrNonConst; }
1594       int getInt(int i) const { return Int; }
1595       int getWithInc(int i) { IntWithInc += i; return IntWithInc; }
1596       int getIntNotAccessed() const { return IntNotAccessed; }
1597       int getIntNoDefinition() const;
1598       int &getIntRef() { return IntRef; }
1599       void returnVoid() const { return; }
1600     };
1601 
1602     void target() {
1603       S s;
1604       int *p1 = s.getPtr();
1605       int *p2 = s.getPtrNonConst();
1606       int i1 = s.getInt(1);
1607       int i2 = s.getWithInc(1);
1608       int i3 = s.getIntNoDefinition();
1609       int &iref = s.getIntRef();
1610 
1611       // Regression test: Don't crash on an indirect call (which doesn't have
1612       // an associated `CXXMethodDecl`).
1613       auto ptr_to_member_fn = &S::getPtr;
1614       p1 = (s.*ptr_to_member_fn)();
1615 
1616       // Regression test: Don't crash on a return statement without a value.
1617       s.returnVoid();
1618       // [[p]]
1619     }
1620   )";
1621   runDataflow(
1622       Code,
1623       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1624          ASTContext &ASTCtx) {
1625         const Environment &Env =
1626               getEnvironmentAtAnnotation(Results, "p");
1627         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
1628         std::vector<const ValueDecl*> Fields;
1629         for (auto [Field, _] : SLoc.children())
1630           Fields.push_back(Field);
1631         // Only the fields that have simple accessor methods (that have a
1632         // single statement body that returns the member variable) should be
1633         // modeled.
1634         ASSERT_THAT(Fields, UnorderedElementsAre(
1635             findValueDecl(ASTCtx, "Ptr"), findValueDecl(ASTCtx, "PtrNonConst"),
1636             findValueDecl(ASTCtx, "Int"), findValueDecl(ASTCtx, "IntRef")));
1637       });
1638 }
1639 
1640 TEST(TransferTest, StructModeledFieldsWithComplicatedInheritance) {
1641   std::string Code = R"(
1642     struct Base1 {
1643       int base1_1;
1644       int base1_2;
1645     };
1646     struct Intermediate : Base1 {
1647       int intermediate_1;
1648       int intermediate_2;
1649     };
1650     struct Base2 {
1651       int base2_1;
1652       int base2_2;
1653     };
1654     struct MostDerived : public Intermediate, Base2 {
1655       int most_derived_1;
1656       int most_derived_2;
1657     };
1658 
1659     void target() {
1660       MostDerived MD;
1661       MD.base1_2 = 1;
1662       MD.intermediate_2 = 1;
1663       MD.base2_2 = 1;
1664       MD.most_derived_2 = 1;
1665       // [[p]]
1666     }
1667   )";
1668   runDataflow(
1669       Code,
1670       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1671          ASTContext &ASTCtx) {
1672         const Environment &Env =
1673               getEnvironmentAtAnnotation(Results, "p");
1674 
1675         // Only the accessed fields should exist in the model.
1676         auto &MDLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MD");
1677         std::vector<const ValueDecl*> Fields;
1678         for (auto [Field, _] : MDLoc.children())
1679           Fields.push_back(Field);
1680         ASSERT_THAT(Fields, UnorderedElementsAre(
1681             findValueDecl(ASTCtx, "base1_2"),
1682             findValueDecl(ASTCtx, "intermediate_2"),
1683             findValueDecl(ASTCtx, "base2_2"),
1684             findValueDecl(ASTCtx, "most_derived_2")));
1685       });
1686 }
1687 
1688 TEST(TransferTest, StructInitializerListWithComplicatedInheritance) {
1689   std::string Code = R"(
1690     struct Base1 {
1691       int base1;
1692     };
1693     struct Intermediate : Base1 {
1694       int intermediate;
1695     };
1696     struct Base2 {
1697       int base2;
1698     };
1699     struct MostDerived : public Intermediate, Base2 {
1700       int most_derived;
1701     };
1702 
1703     void target() {
1704       MostDerived MD = {};
1705       // [[p]]
1706     }
1707   )";
1708   runDataflow(
1709       Code,
1710       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1711          ASTContext &ASTCtx) {
1712         const Environment &Env =
1713               getEnvironmentAtAnnotation(Results, "p");
1714 
1715         // When a struct is initialized with a initializer list, all the
1716         // fields are considered "accessed", and therefore do exist.
1717         auto &MD = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MD");
1718         ASSERT_THAT(cast<IntegerValue>(
1719             getFieldValue(&MD, *findValueDecl(ASTCtx, "base1"), Env)),
1720             NotNull());
1721         ASSERT_THAT(cast<IntegerValue>(
1722             getFieldValue(&MD, *findValueDecl(ASTCtx, "intermediate"), Env)),
1723             NotNull());
1724         ASSERT_THAT(cast<IntegerValue>(
1725             getFieldValue(&MD, *findValueDecl(ASTCtx, "base2"), Env)),
1726             NotNull());
1727         ASSERT_THAT(cast<IntegerValue>(
1728             getFieldValue(&MD, *findValueDecl(ASTCtx, "most_derived"), Env)),
1729             NotNull());
1730       });
1731 }
1732 
1733 TEST(TransferTest, ReferenceMember) {
1734   std::string Code = R"(
1735     struct A {
1736       int &Bar;
1737     };
1738 
1739     void target(A Foo) {
1740       int Baz = Foo.Bar;
1741       // [[p]]
1742     }
1743   )";
1744   runDataflow(
1745       Code,
1746       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1747          ASTContext &ASTCtx) {
1748         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1749         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1750 
1751         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1752         ASSERT_THAT(FooDecl, NotNull());
1753 
1754         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1755         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1756 
1757         FieldDecl *BarDecl = nullptr;
1758         for (FieldDecl *Field : FooFields) {
1759           if (Field->getNameAsString() == "Bar") {
1760             BarDecl = Field;
1761           } else {
1762             FAIL() << "Unexpected field: " << Field->getNameAsString();
1763           }
1764         }
1765         ASSERT_THAT(BarDecl, NotNull());
1766 
1767         const auto *FooLoc =
1768             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1769         const auto *BarReferentVal =
1770             cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env));
1771 
1772         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1773         ASSERT_THAT(BazDecl, NotNull());
1774 
1775         EXPECT_EQ(Env.getValue(*BazDecl), BarReferentVal);
1776       });
1777 }
1778 
1779 TEST(TransferTest, StructThisMember) {
1780   std::string Code = R"(
1781     struct A {
1782       int Bar;
1783 
1784       struct B {
1785         int Baz;
1786       };
1787 
1788       B Qux;
1789 
1790       void target() {
1791         int Foo = Bar;
1792         int Quux = Qux.Baz;
1793         // [[p]]
1794       }
1795     };
1796   )";
1797   runDataflow(
1798       Code,
1799       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1800          ASTContext &ASTCtx) {
1801         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1802         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1803 
1804         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1805         ASSERT_THAT(ThisLoc, NotNull());
1806 
1807         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1808         ASSERT_THAT(BarDecl, NotNull());
1809 
1810         const auto *BarLoc =
1811             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1812         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1813 
1814         const Value *BarVal = Env.getValue(*BarLoc);
1815         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1816 
1817         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1818         ASSERT_THAT(FooDecl, NotNull());
1819         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1820 
1821         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1822         ASSERT_THAT(QuxDecl, NotNull());
1823 
1824         ASSERT_TRUE(QuxDecl->getType()->isStructureType());
1825         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1826 
1827         FieldDecl *BazDecl = nullptr;
1828         for (FieldDecl *Field : QuxFields) {
1829           if (Field->getNameAsString() == "Baz") {
1830             BazDecl = Field;
1831           } else {
1832             FAIL() << "Unexpected field: " << Field->getNameAsString();
1833           }
1834         }
1835         ASSERT_THAT(BazDecl, NotNull());
1836 
1837         const auto *QuxLoc =
1838             cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl));
1839 
1840         const auto *BazVal =
1841             cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env));
1842 
1843         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1844         ASSERT_THAT(QuuxDecl, NotNull());
1845         EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal);
1846       });
1847 }
1848 
1849 TEST(TransferTest, ClassThisMember) {
1850   std::string Code = R"(
1851     class A {
1852       int Bar;
1853 
1854       class B {
1855       public:
1856         int Baz;
1857       };
1858 
1859       B Qux;
1860 
1861       void target() {
1862         int Foo = Bar;
1863         int Quux = Qux.Baz;
1864         // [[p]]
1865       }
1866     };
1867   )";
1868   runDataflow(
1869       Code,
1870       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1871          ASTContext &ASTCtx) {
1872         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1873         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1874 
1875         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1876 
1877         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1878         ASSERT_THAT(BarDecl, NotNull());
1879 
1880         const auto *BarLoc =
1881             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1882         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1883 
1884         const Value *BarVal = Env.getValue(*BarLoc);
1885         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1886 
1887         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1888         ASSERT_THAT(FooDecl, NotNull());
1889         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1890 
1891         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1892         ASSERT_THAT(QuxDecl, NotNull());
1893 
1894         ASSERT_TRUE(QuxDecl->getType()->isClassType());
1895         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1896 
1897         FieldDecl *BazDecl = nullptr;
1898         for (FieldDecl *Field : QuxFields) {
1899           if (Field->getNameAsString() == "Baz") {
1900             BazDecl = Field;
1901           } else {
1902             FAIL() << "Unexpected field: " << Field->getNameAsString();
1903           }
1904         }
1905         ASSERT_THAT(BazDecl, NotNull());
1906 
1907         const auto *QuxLoc =
1908             cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl));
1909 
1910         const auto *BazVal =
1911             cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env));
1912 
1913         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1914         ASSERT_THAT(QuuxDecl, NotNull());
1915         EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal);
1916       });
1917 }
1918 
1919 TEST(TransferTest, UnionThisMember) {
1920   std::string Code = R"(
1921     union A {
1922       int Foo;
1923       int Bar;
1924 
1925       void target() {
1926         A a;
1927         // Mention the fields to ensure they're included in the analysis.
1928         (void)a.Foo;
1929         (void)a.Bar;
1930         // [[p]]
1931       }
1932     };
1933   )";
1934   runDataflow(
1935       Code,
1936       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1937          ASTContext &ASTCtx) {
1938         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1939         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1940 
1941         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1942         ASSERT_THAT(ThisLoc, NotNull());
1943 
1944         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1945         ASSERT_THAT(FooDecl, NotNull());
1946 
1947         const auto *FooLoc =
1948             cast<ScalarStorageLocation>(ThisLoc->getChild(*FooDecl));
1949         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1950 
1951         const Value *FooVal = Env.getValue(*FooLoc);
1952         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
1953 
1954         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1955         ASSERT_THAT(BarDecl, NotNull());
1956 
1957         const auto *BarLoc =
1958             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1959         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1960 
1961         const Value *BarVal = Env.getValue(*BarLoc);
1962         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1963       });
1964 }
1965 
1966 TEST(TransferTest, StructThisInLambda) {
1967   std::string ThisCaptureCode = R"(
1968     struct A {
1969       void frob() {
1970         [this]() {
1971           int Foo = Bar;
1972           // [[p1]]
1973         }();
1974       }
1975 
1976       int Bar;
1977     };
1978   )";
1979   runDataflow(
1980       ThisCaptureCode,
1981       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1982          ASTContext &ASTCtx) {
1983         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1"));
1984         const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
1985 
1986         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1987         ASSERT_THAT(ThisLoc, NotNull());
1988 
1989         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1990         ASSERT_THAT(BarDecl, NotNull());
1991 
1992         const auto *BarLoc =
1993             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1994         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1995 
1996         const Value *BarVal = Env.getValue(*BarLoc);
1997         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1998 
1999         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2000         ASSERT_THAT(FooDecl, NotNull());
2001         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
2002       },
2003       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
2004 
2005   std::string RefCaptureDefaultCode = R"(
2006     struct A {
2007       void frob() {
2008         [&]() {
2009           int Foo = Bar;
2010           // [[p2]]
2011         }();
2012       }
2013 
2014       int Bar;
2015     };
2016   )";
2017   runDataflow(
2018       RefCaptureDefaultCode,
2019       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2020          ASTContext &ASTCtx) {
2021         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p2"));
2022         const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
2023 
2024         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2025         ASSERT_THAT(ThisLoc, NotNull());
2026 
2027         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2028         ASSERT_THAT(BarDecl, NotNull());
2029 
2030         const auto *BarLoc =
2031             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
2032         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2033 
2034         const Value *BarVal = Env.getValue(*BarLoc);
2035         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
2036 
2037         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2038         ASSERT_THAT(FooDecl, NotNull());
2039         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
2040       },
2041       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
2042 
2043   std::string FreeFunctionLambdaCode = R"(
2044     void foo() {
2045       int Bar;
2046       [&]() {
2047         int Foo = Bar;
2048         // [[p3]]
2049       }();
2050     }
2051   )";
2052   runDataflow(
2053       FreeFunctionLambdaCode,
2054       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2055          ASTContext &ASTCtx) {
2056         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p3"));
2057         const Environment &Env = getEnvironmentAtAnnotation(Results, "p3");
2058 
2059         EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull());
2060       },
2061       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
2062 }
2063 
2064 TEST(TransferTest, ConstructorInitializer) {
2065   std::string Code = R"(
2066     struct target {
2067       int Bar;
2068 
2069       target(int Foo) : Bar(Foo) {
2070         int Qux = Bar;
2071         // [[p]]
2072       }
2073     };
2074   )";
2075   runDataflow(
2076       Code,
2077       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2078          ASTContext &ASTCtx) {
2079         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2080         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2081 
2082         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2083         ASSERT_THAT(ThisLoc, NotNull());
2084 
2085         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2086         ASSERT_THAT(FooDecl, NotNull());
2087 
2088         const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl));
2089 
2090         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2091         ASSERT_THAT(QuxDecl, NotNull());
2092         EXPECT_EQ(Env.getValue(*QuxDecl), FooVal);
2093       });
2094 }
2095 
2096 TEST(TransferTest, DefaultInitializer) {
2097   std::string Code = R"(
2098     struct target {
2099       int Bar;
2100       int Baz = Bar;
2101 
2102       target(int Foo) : Bar(Foo) {
2103         int Qux = Baz;
2104         // [[p]]
2105       }
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 auto *ThisLoc = Env.getThisPointeeStorageLocation();
2116         ASSERT_THAT(ThisLoc, NotNull());
2117 
2118         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2119         ASSERT_THAT(FooDecl, NotNull());
2120 
2121         const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl));
2122 
2123         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2124         ASSERT_THAT(QuxDecl, NotNull());
2125         EXPECT_EQ(Env.getValue(*QuxDecl), FooVal);
2126       });
2127 }
2128 
2129 TEST(TransferTest, DefaultInitializerReference) {
2130   std::string Code = R"(
2131     struct target {
2132       int &Bar;
2133       int &Baz = Bar;
2134 
2135       target(int &Foo) : Bar(Foo) {
2136         int &Qux = Baz;
2137         // [[p]]
2138       }
2139     };
2140   )";
2141   runDataflow(
2142       Code,
2143       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2144          ASTContext &ASTCtx) {
2145         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2146         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2147 
2148         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
2149         ASSERT_THAT(ThisLoc, NotNull());
2150 
2151         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2152         ASSERT_THAT(FooDecl, NotNull());
2153 
2154         const auto *FooLoc = Env.getStorageLocation(*FooDecl);
2155 
2156         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2157         ASSERT_THAT(QuxDecl, NotNull());
2158 
2159         const auto *QuxLoc = Env.getStorageLocation(*QuxDecl);
2160         EXPECT_EQ(QuxLoc, FooLoc);
2161       });
2162 }
2163 
2164 TEST(TransferTest, TemporaryObject) {
2165   std::string Code = R"(
2166     struct A {
2167       int Bar;
2168     };
2169 
2170     void target() {
2171       A Foo = A();
2172       (void)Foo.Bar;
2173       // [[p]]
2174     }
2175   )";
2176   runDataflow(
2177       Code,
2178       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2179          ASTContext &ASTCtx) {
2180         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2181         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2182 
2183         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2184         ASSERT_THAT(FooDecl, NotNull());
2185 
2186         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2187         ASSERT_THAT(BarDecl, NotNull());
2188 
2189         const auto *FooLoc =
2190             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2191         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
2192       });
2193 }
2194 
2195 TEST(TransferTest, ElidableConstructor) {
2196   // This test is effectively the same as TransferTest.TemporaryObject, but
2197   // the code is compiled as C++14.
2198   std::string Code = R"(
2199     struct A {
2200       int Bar;
2201     };
2202 
2203     void target() {
2204       A Foo = A();
2205       (void)Foo.Bar;
2206       // [[p]]
2207     }
2208   )";
2209   runDataflow(
2210       Code,
2211       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2212          ASTContext &ASTCtx) {
2213         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2214         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2215 
2216         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2217         ASSERT_THAT(FooDecl, NotNull());
2218 
2219         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2220         ASSERT_THAT(BarDecl, NotNull());
2221 
2222         const auto *FooLoc =
2223             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2224         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
2225       },
2226       LangStandard::lang_cxx14);
2227 }
2228 
2229 TEST(TransferTest, AssignmentOperator) {
2230   std::string Code = R"(
2231     struct A {
2232       int Baz;
2233     };
2234 
2235     void target() {
2236       A Foo = { 1 };
2237       A Bar = { 2 };
2238       // [[p1]]
2239       A &Rval = (Foo = Bar);
2240       // [[p2]]
2241       Foo.Baz = 3;
2242       // [[p3]]
2243     }
2244   )";
2245   runDataflow(
2246       Code,
2247       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2248          ASTContext &ASTCtx) {
2249         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2250         ASSERT_THAT(FooDecl, NotNull());
2251 
2252         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2253         ASSERT_THAT(BarDecl, NotNull());
2254 
2255         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2256         ASSERT_THAT(BazDecl, NotNull());
2257 
2258         // Before copy assignment.
2259         {
2260           const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2261 
2262           const auto *FooLoc1 =
2263               cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
2264           const auto *BarLoc1 =
2265               cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
2266           EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
2267 
2268           const auto *FooBazVal1 =
2269               cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1));
2270           const auto *BarBazVal1 =
2271               cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1));
2272           EXPECT_NE(FooBazVal1, BarBazVal1);
2273         }
2274 
2275         // After copy assignment.
2276         {
2277           const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
2278 
2279           const auto *FooLoc2 =
2280               cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
2281           const auto *BarLoc2 =
2282               cast<RecordStorageLocation>(Env2.getStorageLocation(*BarDecl));
2283 
2284           EXPECT_TRUE(recordsEqual(*FooLoc2, *BarLoc2, Env2));
2285           EXPECT_EQ(&getLocForDecl(ASTCtx, Env2, "Rval"), FooLoc2);
2286 
2287           const auto *FooBazVal2 =
2288               cast<IntegerValue>(getFieldValue(FooLoc2, *BazDecl, Env2));
2289           const auto *BarBazVal2 =
2290               cast<IntegerValue>(getFieldValue(BarLoc2, *BazDecl, Env2));
2291           EXPECT_EQ(FooBazVal2, BarBazVal2);
2292         }
2293 
2294         // After value update.
2295         {
2296           const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
2297 
2298           const auto *FooLoc3 =
2299               cast<RecordStorageLocation>(Env3.getStorageLocation(*FooDecl));
2300           const auto *BarLoc3 =
2301               cast<RecordStorageLocation>(Env3.getStorageLocation(*BarDecl));
2302           EXPECT_FALSE(recordsEqual(*FooLoc3, *BarLoc3, Env3));
2303 
2304           const auto *FooBazVal3 =
2305               cast<IntegerValue>(getFieldValue(FooLoc3, *BazDecl, Env3));
2306           const auto *BarBazVal3 =
2307               cast<IntegerValue>(getFieldValue(BarLoc3, *BazDecl, Env3));
2308           EXPECT_NE(FooBazVal3, BarBazVal3);
2309         }
2310       });
2311 }
2312 
2313 // It's legal for the assignment operator to take its source parameter by value.
2314 // Check that we handle this correctly. (This is a repro -- we used to
2315 // assert-fail on this.)
2316 TEST(TransferTest, AssignmentOperator_ArgByValue) {
2317   std::string Code = R"(
2318     struct A {
2319       int Baz;
2320       A &operator=(A);
2321     };
2322 
2323     void target() {
2324       A Foo = { 1 };
2325       A Bar = { 2 };
2326       Foo = Bar;
2327       // [[p]]
2328     }
2329   )";
2330   runDataflow(
2331       Code,
2332       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2333          ASTContext &ASTCtx) {
2334         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2335         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2336 
2337         const auto &FooLoc =
2338             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo");
2339         const auto &BarLoc =
2340             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar");
2341 
2342         const auto *FooBazVal =
2343             cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env));
2344         const auto *BarBazVal =
2345             cast<IntegerValue>(getFieldValue(&BarLoc, *BazDecl, Env));
2346         EXPECT_EQ(FooBazVal, BarBazVal);
2347       });
2348 }
2349 
2350 TEST(TransferTest, AssignmentOperatorFromBase) {
2351   std::string Code = R"(
2352     struct Base {
2353       int base;
2354     };
2355     struct Derived : public Base {
2356       using Base::operator=;
2357       int derived;
2358     };
2359     void target(Base B, Derived D) {
2360       D.base = 1;
2361       D.derived = 1;
2362       // [[before]]
2363       D = B;
2364       // [[after]]
2365     }
2366   )";
2367   runDataflow(
2368       Code,
2369       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2370          ASTContext &ASTCtx) {
2371         const Environment &EnvBefore =
2372             getEnvironmentAtAnnotation(Results, "before");
2373         const Environment &EnvAfter =
2374             getEnvironmentAtAnnotation(Results, "after");
2375 
2376         auto &BLoc =
2377             getLocForDecl<RecordStorageLocation>(ASTCtx, EnvBefore, "B");
2378         auto &DLoc =
2379             getLocForDecl<RecordStorageLocation>(ASTCtx, EnvBefore, "D");
2380 
2381         EXPECT_NE(getFieldValue(&BLoc, "base", ASTCtx, EnvBefore),
2382                   getFieldValue(&DLoc, "base", ASTCtx, EnvBefore));
2383         EXPECT_EQ(getFieldValue(&BLoc, "base", ASTCtx, EnvAfter),
2384                   getFieldValue(&DLoc, "base", ASTCtx, EnvAfter));
2385 
2386         EXPECT_EQ(getFieldValue(&DLoc, "derived", ASTCtx, EnvBefore),
2387                   getFieldValue(&DLoc, "derived", ASTCtx, EnvAfter));
2388       });
2389 }
2390 
2391 TEST(TransferTest, AssignmentOperatorFromCallResult) {
2392   std::string Code = R"(
2393     struct A {};
2394     A ReturnA();
2395 
2396     void target() {
2397       A MyA;
2398       MyA = ReturnA();
2399     }
2400   )";
2401   runDataflow(
2402       Code,
2403       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2404          ASTContext &ASTCtx) {
2405         // As of this writing, we don't produce a `Value` for the call
2406         // `ReturnA()`. The only condition we're testing for is that the
2407         // analysis should not crash in this case.
2408       });
2409 }
2410 
2411 TEST(TransferTest, AssignmentOperatorWithInitAndInheritance) {
2412   // This is a crash repro.
2413   std::string Code = R"(
2414     struct B { int Foo; };
2415     struct S : public B {};
2416     void target() {
2417       S S1 = { 1 };
2418       S S2;
2419       S S3;
2420       S1 = S2;  // Only Dst has InitListExpr.
2421       S3 = S1;  // Only Src has InitListExpr.
2422       // [[p]]
2423     }
2424   )";
2425   runDataflow(
2426       Code,
2427       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2428          ASTContext &ASTCtx) {});
2429 }
2430 
2431 TEST(TransferTest, AssignmentOperatorReturnsVoid) {
2432   // This is a crash repro.
2433   std::string Code = R"(
2434     struct S {
2435       void operator=(S&& other);
2436     };
2437     void target() {
2438       S s;
2439       s = S();
2440       // [[p]]
2441     }
2442   )";
2443   runDataflow(
2444       Code,
2445       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2446          ASTContext &ASTCtx) {});
2447 }
2448 
2449 TEST(TransferTest, AssignmentOperatorReturnsByValue) {
2450   // This is a crash repro.
2451   std::string Code = R"(
2452     struct S {
2453       S operator=(const S&);
2454       int i;
2455     };
2456     void target() {
2457       S S1 = { 1 };
2458       S S2 = { 2 };
2459       S S3 = { 3 };
2460       // [[before]]
2461       // Test that the returned value is modeled by assigning to another value.
2462       S1 = (S2 = S3);
2463       (void)0;
2464       // [[after]]
2465     }
2466   )";
2467   runDataflow(
2468       Code,
2469       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2470          ASTContext &ASTCtx) {
2471         const ValueDecl *S1Decl = findValueDecl(ASTCtx, "S1");
2472         const ValueDecl *S2Decl = findValueDecl(ASTCtx, "S2");
2473         const ValueDecl *S3Decl = findValueDecl(ASTCtx, "S3");
2474 
2475         const Environment &EnvBefore =
2476             getEnvironmentAtAnnotation(Results, "before");
2477 
2478         EXPECT_FALSE(recordsEqual(
2479             *EnvBefore.get<RecordStorageLocation>(*S1Decl),
2480             *EnvBefore.get<RecordStorageLocation>(*S2Decl), EnvBefore));
2481         EXPECT_FALSE(recordsEqual(
2482             *EnvBefore.get<RecordStorageLocation>(*S2Decl),
2483             *EnvBefore.get<RecordStorageLocation>(*S3Decl), EnvBefore));
2484 
2485         const Environment &EnvAfter =
2486             getEnvironmentAtAnnotation(Results, "after");
2487 
2488         EXPECT_TRUE(recordsEqual(*EnvAfter.get<RecordStorageLocation>(*S1Decl),
2489                                  *EnvAfter.get<RecordStorageLocation>(*S2Decl),
2490                                  EnvAfter));
2491         EXPECT_TRUE(recordsEqual(*EnvAfter.get<RecordStorageLocation>(*S2Decl),
2492                                  *EnvAfter.get<RecordStorageLocation>(*S3Decl),
2493                                  EnvAfter));
2494       });
2495 }
2496 
2497 TEST(TransferTest, AssignmentOperatorReturnsDifferentTypeByRef) {
2498   // This is a crash repro.
2499   std::string Code = R"(
2500     struct DifferentType {};
2501     struct S {
2502       DifferentType& operator=(const S&);
2503     };
2504     void target() {
2505       S s;
2506       s = S();
2507       // [[p]]
2508     }
2509   )";
2510   runDataflow(
2511       Code,
2512       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2513          ASTContext &ASTCtx) {});
2514 }
2515 
2516 TEST(TransferTest, AssignmentOperatorReturnsDifferentTypeByValue) {
2517   // This is a crash repro.
2518   std::string Code = R"(
2519     struct DifferentType {};
2520     struct S {
2521       DifferentType operator=(const S&);
2522     };
2523     void target() {
2524       S s;
2525       s = S();
2526       // [[p]]
2527     }
2528   )";
2529   runDataflow(
2530       Code,
2531       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2532          ASTContext &ASTCtx) {});
2533 }
2534 
2535 TEST(TransferTest, InitListExprAsXValue) {
2536   // This is a crash repro.
2537   std::string Code = R"(
2538     void target() {
2539       bool&& Foo{false};
2540       // [[p]]
2541     }
2542   )";
2543   runDataflow(
2544       Code,
2545       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2546          ASTContext &ASTCtx) {
2547         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2548         const auto &FooVal = getValueForDecl<BoolValue>(ASTCtx, Env, "Foo");
2549         ASSERT_TRUE(FooVal.formula().isLiteral(false));
2550       });
2551 }
2552 
2553 TEST(TransferTest, ArrayInitListExprOneRecordElement) {
2554   // This is a crash repro.
2555   std::string Code = R"cc(
2556     struct S {};
2557 
2558     void target() { S foo[] = {S()}; }
2559   )cc";
2560   runDataflow(
2561       Code,
2562       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2563          ASTContext &ASTCtx) {
2564         // Just verify that it doesn't crash.
2565       });
2566 }
2567 
2568 TEST(TransferTest, InitListExprAsUnion) {
2569   // This is a crash repro.
2570   std::string Code = R"cc(
2571     class target {
2572       union {
2573         int *a;
2574         bool *b;
2575       } F;
2576 
2577      public:
2578       constexpr target() : F{nullptr} {
2579         int *null = nullptr;
2580         F.b;  // Make sure we reference 'b' so it is modeled.
2581         // [[p]]
2582       }
2583     };
2584   )cc";
2585   runDataflow(
2586       Code,
2587       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2588          ASTContext &ASTCtx) {
2589         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2590 
2591         auto &FLoc = getFieldLoc<RecordStorageLocation>(
2592             *Env.getThisPointeeStorageLocation(), "F", ASTCtx);
2593         auto *AVal = cast<PointerValue>(getFieldValue(&FLoc, "a", ASTCtx, Env));
2594         EXPECT_EQ(AVal, &getValueForDecl<PointerValue>(ASTCtx, Env, "null"));
2595         EXPECT_EQ(getFieldValue(&FLoc, "b", ASTCtx, Env), nullptr);
2596       });
2597 }
2598 
2599 TEST(TransferTest, EmptyInitListExprForUnion) {
2600   // This is a crash repro.
2601   std::string Code = R"cc(
2602     class target {
2603       union {
2604         int *a;
2605         bool *b;
2606       } F;
2607 
2608      public:
2609       // Empty initializer list means that `F` is aggregate-initialized.
2610       // For a union, this has the effect that the first member of the union
2611       // is copy-initialized from an empty initializer list; in this specific
2612       // case, this has the effect of initializing `a` with null.
2613       constexpr target() : F{} {
2614         int *null = nullptr;
2615         F.b;  // Make sure we reference 'b' so it is modeled.
2616         // [[p]]
2617       }
2618     };
2619   )cc";
2620   runDataflow(
2621       Code,
2622       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2623          ASTContext &ASTCtx) {
2624         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2625 
2626         auto &FLoc = getFieldLoc<RecordStorageLocation>(
2627             *Env.getThisPointeeStorageLocation(), "F", ASTCtx);
2628         auto *AVal = cast<PointerValue>(getFieldValue(&FLoc, "a", ASTCtx, Env));
2629         EXPECT_EQ(AVal, &getValueForDecl<PointerValue>(ASTCtx, Env, "null"));
2630         EXPECT_EQ(getFieldValue(&FLoc, "b", ASTCtx, Env), nullptr);
2631       });
2632 }
2633 
2634 TEST(TransferTest, EmptyInitListExprForStruct) {
2635   std::string Code = R"cc(
2636     class target {
2637       struct {
2638         int *a;
2639         bool *b;
2640       } F;
2641 
2642      public:
2643       constexpr target() : F{} {
2644         int *NullIntPtr = nullptr;
2645         bool *NullBoolPtr = nullptr;
2646         // [[p]]
2647       }
2648     };
2649   )cc";
2650   runDataflow(
2651       Code,
2652       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2653          ASTContext &ASTCtx) {
2654         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2655 
2656         auto &FLoc = getFieldLoc<RecordStorageLocation>(
2657             *Env.getThisPointeeStorageLocation(), "F", ASTCtx);
2658         auto *AVal = cast<PointerValue>(getFieldValue(&FLoc, "a", ASTCtx, Env));
2659         EXPECT_EQ(AVal,
2660                   &getValueForDecl<PointerValue>(ASTCtx, Env, "NullIntPtr"));
2661         auto *BVal = cast<PointerValue>(getFieldValue(&FLoc, "b", ASTCtx, Env));
2662         EXPECT_EQ(BVal,
2663                   &getValueForDecl<PointerValue>(ASTCtx, Env, "NullBoolPtr"));
2664       });
2665 }
2666 
2667 TEST(TransferTest, CopyConstructor) {
2668   std::string Code = R"(
2669     struct A {
2670       int Baz;
2671     };
2672 
2673     void target() {
2674       A Foo = { 1 };
2675       A Bar = Foo;
2676       // [[after_copy]]
2677       Foo.Baz = 2;
2678       // [[after_update]]
2679     }
2680   )";
2681   runDataflow(
2682       Code,
2683       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2684          ASTContext &ASTCtx) {
2685         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2686         ASSERT_THAT(FooDecl, NotNull());
2687 
2688         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2689         ASSERT_THAT(BarDecl, NotNull());
2690 
2691         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2692         ASSERT_THAT(BazDecl, NotNull());
2693 
2694         // after_copy
2695         {
2696           const Environment &Env =
2697               getEnvironmentAtAnnotation(Results, "after_copy");
2698 
2699           const auto *FooLoc =
2700               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2701           const auto *BarLoc =
2702               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2703 
2704           // The records compare equal.
2705           EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2706 
2707           // In particular, the value of `Baz` in both records is the same.
2708           const auto *FooBazVal =
2709               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2710           const auto *BarBazVal =
2711               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2712           EXPECT_EQ(FooBazVal, BarBazVal);
2713         }
2714 
2715         // after_update
2716         {
2717           const Environment &Env =
2718               getEnvironmentAtAnnotation(Results, "after_update");
2719 
2720           const auto *FooLoc =
2721               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2722           const auto *BarLoc =
2723               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2724 
2725           EXPECT_FALSE(recordsEqual(*FooLoc, *BarLoc, Env));
2726 
2727           const auto *FooBazVal =
2728               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2729           const auto *BarBazVal =
2730               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2731           EXPECT_NE(FooBazVal, BarBazVal);
2732         }
2733       });
2734 }
2735 
2736 TEST(TransferTest, CopyConstructorWithDefaultArgument) {
2737   std::string Code = R"(
2738     struct A {
2739       int Baz;
2740       A() = default;
2741       A(const A& a, bool def = true) { Baz = a.Baz; }
2742     };
2743 
2744     void target() {
2745       A Foo;
2746       (void)Foo.Baz;
2747       A Bar = Foo;
2748       // [[p]]
2749     }
2750   )";
2751   runDataflow(
2752       Code,
2753       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2754          ASTContext &ASTCtx) {
2755         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2756         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2757 
2758         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2759         ASSERT_THAT(FooDecl, NotNull());
2760 
2761         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2762         ASSERT_THAT(BarDecl, NotNull());
2763 
2764         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2765         ASSERT_THAT(BazDecl, NotNull());
2766 
2767         const auto *FooLoc =
2768             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2769         const auto *BarLoc =
2770             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2771         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2772 
2773         const auto *FooBazVal =
2774             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2775         const auto *BarBazVal =
2776             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2777         EXPECT_EQ(FooBazVal, BarBazVal);
2778       });
2779 }
2780 
2781 TEST(TransferTest, CopyConstructorWithParens) {
2782   std::string Code = R"(
2783     struct A {
2784       int Baz;
2785     };
2786 
2787     void target() {
2788       A Foo;
2789       (void)Foo.Baz;
2790       A Bar((A(Foo)));
2791       // [[p]]
2792     }
2793   )";
2794   runDataflow(
2795       Code,
2796       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2797          ASTContext &ASTCtx) {
2798         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2799         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2800 
2801         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2802         ASSERT_THAT(FooDecl, NotNull());
2803 
2804         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2805         ASSERT_THAT(BarDecl, NotNull());
2806 
2807         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2808         ASSERT_THAT(BazDecl, NotNull());
2809 
2810         const auto *FooLoc =
2811             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2812         const auto *BarLoc =
2813             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2814         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2815 
2816         const auto *FooBazVal =
2817             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2818         const auto *BarBazVal =
2819             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2820         EXPECT_EQ(FooBazVal, BarBazVal);
2821       });
2822 }
2823 
2824 TEST(TransferTest, CopyConstructorWithInitializerListAsSyntacticSugar) {
2825   std::string Code = R"(
2826   struct A {
2827     int Baz;
2828   };
2829   void target() {
2830     A Foo = {3};
2831     (void)Foo.Baz;
2832     A Bar = {A(Foo)};
2833     // [[p]]
2834   }
2835   )";
2836   runDataflow(
2837       Code,
2838       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2839          ASTContext &ASTCtx) {
2840         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2841 
2842         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2843 
2844         const auto &FooLoc =
2845             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo");
2846         const auto &BarLoc =
2847             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar");
2848 
2849         const auto *FooBazVal =
2850             cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env));
2851         const auto *BarBazVal =
2852             cast<IntegerValue>(getFieldValue(&BarLoc, *BazDecl, Env));
2853         EXPECT_EQ(FooBazVal, BarBazVal);
2854       });
2855 }
2856 
2857 TEST(TransferTest, CopyConstructorArgIsRefReturnedByFunction) {
2858   // This is a crash repro.
2859   std::string Code = R"(
2860     struct S {};
2861     const S &returnsSRef();
2862     void target() {
2863       S s(returnsSRef());
2864     }
2865   )";
2866   runDataflow(
2867       Code,
2868       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2869          ASTContext &ASTCtx) {});
2870 }
2871 
2872 TEST(TransferTest, MoveConstructor) {
2873   std::string Code = R"(
2874     namespace std {
2875 
2876     template <typename T> struct remove_reference      { using type = T; };
2877     template <typename T> struct remove_reference<T&>  { using type = T; };
2878     template <typename T> struct remove_reference<T&&> { using type = T; };
2879 
2880     template <typename T>
2881     using remove_reference_t = typename remove_reference<T>::type;
2882 
2883     template <typename T>
2884     std::remove_reference_t<T>&& move(T&& x);
2885 
2886     } // namespace std
2887 
2888     struct A {
2889       int Baz;
2890     };
2891 
2892     void target() {
2893       A Foo;
2894       A Bar;
2895       (void)Foo.Baz;
2896       // [[p1]]
2897       Foo = std::move(Bar);
2898       // [[p2]]
2899     }
2900   )";
2901   runDataflow(
2902       Code,
2903       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2904          ASTContext &ASTCtx) {
2905         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
2906         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2907         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
2908 
2909         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2910         ASSERT_THAT(FooDecl, NotNull());
2911 
2912         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2913         ASSERT_THAT(BarDecl, NotNull());
2914 
2915         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2916         ASSERT_THAT(BazDecl, NotNull());
2917 
2918         const auto *FooLoc1 =
2919             cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
2920         const auto *BarLoc1 =
2921             cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
2922 
2923         EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
2924 
2925         const auto *FooBazVal1 =
2926             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1));
2927         const auto *BarBazVal1 =
2928             cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1));
2929         EXPECT_NE(FooBazVal1, BarBazVal1);
2930 
2931         const auto *FooLoc2 =
2932             cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
2933         EXPECT_TRUE(recordsEqual(*FooLoc2, Env2, *BarLoc1, Env1));
2934 
2935         const auto *FooBazVal2 =
2936             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env2));
2937         EXPECT_EQ(FooBazVal2, BarBazVal1);
2938       });
2939 }
2940 
2941 TEST(TransferTest, BindTemporary) {
2942   std::string Code = R"(
2943     struct A {
2944       virtual ~A() = default;
2945 
2946       int Baz;
2947     };
2948 
2949     void target(A Foo) {
2950       int Bar = A(Foo).Baz;
2951       // [[p]]
2952     }
2953   )";
2954   runDataflow(
2955       Code,
2956       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2957          ASTContext &ASTCtx) {
2958         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2959         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2960 
2961         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2962         ASSERT_THAT(FooDecl, NotNull());
2963 
2964         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2965         ASSERT_THAT(BarDecl, NotNull());
2966 
2967         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2968         ASSERT_THAT(BazDecl, NotNull());
2969 
2970         const auto &FooLoc =
2971             *cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2972         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
2973         EXPECT_EQ(BarVal, getFieldValue(&FooLoc, *BazDecl, Env));
2974       });
2975 }
2976 
2977 TEST(TransferTest, ResultObjectLocation) {
2978   std::string Code = R"(
2979     struct A {
2980       virtual ~A() = default;
2981     };
2982 
2983     void target() {
2984       0, A();
2985       (void)0; // [[p]]
2986     }
2987   )";
2988   using ast_matchers::binaryOperator;
2989   using ast_matchers::cxxBindTemporaryExpr;
2990   using ast_matchers::cxxTemporaryObjectExpr;
2991   using ast_matchers::exprWithCleanups;
2992   using ast_matchers::has;
2993   using ast_matchers::hasOperatorName;
2994   using ast_matchers::hasRHS;
2995   using ast_matchers::match;
2996   using ast_matchers::selectFirst;
2997   using ast_matchers::traverse;
2998   runDataflow(
2999       Code,
3000       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3001          ASTContext &ASTCtx) {
3002         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3003 
3004         // The expression `0, A()` in the code above produces the following
3005         // structure, consisting of four prvalues of record type.
3006         // `Env.getResultObjectLocation()` should return the same location for
3007         // all of these.
3008         auto MatchResult = match(
3009             traverse(TK_AsIs,
3010                      exprWithCleanups(
3011                          has(binaryOperator(
3012                                  hasOperatorName(","),
3013                                  hasRHS(cxxBindTemporaryExpr(
3014                                             has(cxxTemporaryObjectExpr().bind(
3015                                                 "toe")))
3016                                             .bind("bte")))
3017                                  .bind("comma")))
3018                          .bind("ewc")),
3019             ASTCtx);
3020         auto *TOE = selectFirst<CXXTemporaryObjectExpr>("toe", MatchResult);
3021         ASSERT_NE(TOE, nullptr);
3022         auto *Comma = selectFirst<BinaryOperator>("comma", MatchResult);
3023         ASSERT_NE(Comma, nullptr);
3024         auto *EWC = selectFirst<ExprWithCleanups>("ewc", MatchResult);
3025         ASSERT_NE(EWC, nullptr);
3026         auto *BTE = selectFirst<CXXBindTemporaryExpr>("bte", MatchResult);
3027         ASSERT_NE(BTE, nullptr);
3028 
3029         RecordStorageLocation &Loc = Env.getResultObjectLocation(*TOE);
3030         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*Comma));
3031         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*EWC));
3032         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*BTE));
3033       });
3034 }
3035 
3036 TEST(TransferTest, ResultObjectLocationForDefaultArgExpr) {
3037   std::string Code = R"(
3038     struct Inner {};
3039     struct Outer {
3040         Inner I = {};
3041     };
3042 
3043     void funcWithDefaultArg(Outer O = {});
3044     void target() {
3045       funcWithDefaultArg();
3046       // [[p]]
3047     }
3048   )";
3049 
3050   using ast_matchers::cxxDefaultArgExpr;
3051   using ast_matchers::match;
3052   using ast_matchers::selectFirst;
3053   runDataflow(
3054       Code,
3055       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3056          ASTContext &ASTCtx) {
3057         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3058 
3059         auto *DefaultArg = selectFirst<CXXDefaultArgExpr>(
3060             "default_arg",
3061             match(cxxDefaultArgExpr().bind("default_arg"), ASTCtx));
3062         ASSERT_NE(DefaultArg, nullptr);
3063 
3064         // The values for default arguments aren't modeled; we merely verify
3065         // that we can get a result object location for a default arg.
3066         Env.getResultObjectLocation(*DefaultArg);
3067       });
3068 }
3069 
3070 TEST(TransferTest, ResultObjectLocationForDefaultInitExpr) {
3071   std::string Code = R"(
3072     struct S {};
3073     struct target {
3074       target () {
3075         (void)0;
3076         // [[p]]
3077       }
3078       S s = {};
3079     };
3080   )";
3081 
3082   using ast_matchers::cxxCtorInitializer;
3083   using ast_matchers::match;
3084   using ast_matchers::selectFirst;
3085   runDataflow(
3086       Code,
3087       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3088          ASTContext &ASTCtx) {
3089         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3090 
3091         const ValueDecl *SField = findValueDecl(ASTCtx, "s");
3092 
3093         auto *CtorInit = selectFirst<CXXCtorInitializer>(
3094             "ctor_initializer",
3095             match(cxxCtorInitializer().bind("ctor_initializer"), ASTCtx));
3096         ASSERT_NE(CtorInit, nullptr);
3097 
3098         auto *DefaultInit = cast<CXXDefaultInitExpr>(CtorInit->getInit());
3099 
3100         RecordStorageLocation &Loc = Env.getResultObjectLocation(*DefaultInit);
3101 
3102         EXPECT_EQ(&Loc, Env.getThisPointeeStorageLocation()->getChild(*SField));
3103       });
3104 }
3105 
3106 // This test ensures that CXXOperatorCallExpr returning prvalues are correctly
3107 // handled by the transfer functions, especially that `getResultObjectLocation`
3108 // correctly returns a storage location for those.
3109 TEST(TransferTest, ResultObjectLocationForCXXOperatorCallExpr) {
3110   std::string Code = R"(
3111     struct A {
3112       A operator+(int);
3113     };
3114 
3115     void target() {
3116       A a;
3117       a + 3;
3118       (void)0; // [[p]]
3119     }
3120   )";
3121   using ast_matchers::cxxOperatorCallExpr;
3122   using ast_matchers::match;
3123   using ast_matchers::selectFirst;
3124   using ast_matchers::traverse;
3125   runDataflow(
3126       Code,
3127       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3128          ASTContext &ASTCtx) {
3129         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3130 
3131         auto *CallExpr = selectFirst<CXXOperatorCallExpr>(
3132             "call_expr",
3133             match(cxxOperatorCallExpr().bind("call_expr"), ASTCtx));
3134 
3135         EXPECT_NE(&Env.getResultObjectLocation(*CallExpr), nullptr);
3136       });
3137 }
3138 
3139 TEST(TransferTest, ResultObjectLocationForInitListExpr) {
3140   std::string Code = R"cc(
3141     struct Inner {};
3142 
3143     struct Outer { Inner I; };
3144 
3145     void target() {
3146       Outer O = { Inner() };
3147       // [[p]]
3148     }
3149   )cc";
3150   using ast_matchers::asString;
3151   using ast_matchers::cxxConstructExpr;
3152   using ast_matchers::hasType;
3153   using ast_matchers::match;
3154   using ast_matchers::selectFirst;
3155   using ast_matchers::traverse;
3156   runDataflow(
3157       Code,
3158       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3159          ASTContext &ASTCtx) {
3160         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3161 
3162         auto *Construct = selectFirst<CXXConstructExpr>(
3163             "construct",
3164             match(
3165                 cxxConstructExpr(hasType(asString("Inner"))).bind("construct"),
3166                 ASTCtx));
3167 
3168         EXPECT_EQ(
3169             &Env.getResultObjectLocation(*Construct),
3170             &getFieldLoc(getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "O"),
3171                          "I", ASTCtx));
3172       });
3173 }
3174 
3175 TEST(TransferTest, ResultObjectLocationForParenInitListExpr) {
3176   std::string Code = R"cc(
3177     struct Inner {};
3178 
3179     struct Outer { Inner I; };
3180 
3181     void target() {
3182       Outer O((Inner()));
3183       // [[p]]
3184     }
3185   )cc";
3186   using ast_matchers::asString;
3187   using ast_matchers::cxxConstructExpr;
3188   using ast_matchers::hasType;
3189   using ast_matchers::match;
3190   using ast_matchers::selectFirst;
3191   using ast_matchers::traverse;
3192   runDataflow(
3193       Code,
3194       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3195          ASTContext &ASTCtx) {
3196         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3197 
3198         auto *Construct = selectFirst<CXXConstructExpr>(
3199             "construct",
3200             match(
3201                 cxxConstructExpr(hasType(asString("Inner"))).bind("construct"),
3202                 ASTCtx));
3203 
3204         EXPECT_EQ(
3205             &Env.getResultObjectLocation(*Construct),
3206             &getFieldLoc(getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "O"),
3207                          "I", ASTCtx));
3208       },
3209       LangStandard::lang_cxx20);
3210 }
3211 
3212 // Check that the `std::strong_ordering` object returned by builtin `<=>` has a
3213 // correctly modeled result object location.
3214 TEST(TransferTest, ResultObjectLocationForBuiltinSpaceshipOperator) {
3215   std::string Code = R"(
3216     namespace std {
3217       // This is the minimal definition required to get
3218       // `Sema::CheckComparisonCategoryType()` to accept this fake.
3219       struct strong_ordering {
3220         enum class ordering { less, equal, greater };
3221         ordering o;
3222         static const strong_ordering less;
3223         static const strong_ordering equivalent;
3224         static const strong_ordering equal;
3225         static const strong_ordering greater;
3226       };
3227 
3228       inline constexpr strong_ordering strong_ordering::less =
3229         { strong_ordering::ordering::less };
3230       inline constexpr strong_ordering strong_ordering::equal =
3231         { strong_ordering::ordering::equal };
3232       inline constexpr strong_ordering strong_ordering::equivalent =
3233         { strong_ordering::ordering::equal };
3234       inline constexpr strong_ordering strong_ordering::greater =
3235         { strong_ordering::ordering::greater };
3236     }
3237     void target(int i, int j) {
3238       auto ordering = i <=> j;
3239       // [[p]]
3240     }
3241   )";
3242   using ast_matchers::binaryOperator;
3243   using ast_matchers::hasOperatorName;
3244   using ast_matchers::match;
3245   using ast_matchers::selectFirst;
3246   using ast_matchers::traverse;
3247   runDataflow(
3248       Code,
3249       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3250          ASTContext &ASTCtx) {
3251         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3252 
3253         auto *Spaceship = selectFirst<BinaryOperator>(
3254             "op",
3255             match(binaryOperator(hasOperatorName("<=>")).bind("op"), ASTCtx));
3256 
3257         EXPECT_EQ(
3258             &Env.getResultObjectLocation(*Spaceship),
3259             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "ordering"));
3260       },
3261       LangStandard::lang_cxx20);
3262 }
3263 
3264 TEST(TransferTest, ResultObjectLocationForStdInitializerListExpr) {
3265   std::string Code = R"(
3266     namespace std {
3267     template <typename T>
3268     struct initializer_list {};
3269     } // namespace std
3270 
3271     void target() {
3272       std::initializer_list<int> list = {1};
3273       // [[p]]
3274     }
3275   )";
3276 
3277   using ast_matchers::cxxStdInitializerListExpr;
3278   using ast_matchers::match;
3279   using ast_matchers::selectFirst;
3280   runDataflow(
3281       Code,
3282       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3283          ASTContext &ASTCtx) {
3284         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3285 
3286         auto *StdInitList = selectFirst<CXXStdInitializerListExpr>(
3287             "std_init_list",
3288             match(cxxStdInitializerListExpr().bind("std_init_list"), ASTCtx));
3289         ASSERT_NE(StdInitList, nullptr);
3290 
3291         EXPECT_EQ(&Env.getResultObjectLocation(*StdInitList),
3292                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "list"));
3293       });
3294 }
3295 
3296 TEST(TransferTest, ResultObjectLocationForStmtExpr) {
3297   std::string Code = R"(
3298     struct S {};
3299     void target() {
3300       S s = ({ S(); });
3301       // [[p]]
3302     }
3303   )";
3304   using ast_matchers::cxxConstructExpr;
3305   using ast_matchers::match;
3306   using ast_matchers::selectFirst;
3307   using ast_matchers::traverse;
3308   runDataflow(
3309       Code,
3310       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3311          ASTContext &ASTCtx) {
3312         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3313 
3314         auto *Construct = selectFirst<CXXConstructExpr>(
3315             "construct", match(cxxConstructExpr().bind("construct"), ASTCtx));
3316 
3317         EXPECT_EQ(&Env.getResultObjectLocation(*Construct),
3318                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s"));
3319       });
3320 }
3321 
3322 TEST(TransferTest, ResultObjectLocationForBuiltinBitCastExpr) {
3323   std::string Code = R"(
3324     struct S { int i; };
3325     void target(int i) {
3326       S s = __builtin_bit_cast(S, i);
3327       // [[p]]
3328     }
3329   )";
3330   using ast_matchers::explicitCastExpr;
3331   using ast_matchers::match;
3332   using ast_matchers::selectFirst;
3333   using ast_matchers::traverse;
3334   runDataflow(
3335       Code,
3336       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3337          ASTContext &ASTCtx) {
3338         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3339 
3340         auto *BuiltinBitCast = selectFirst<BuiltinBitCastExpr>(
3341             "cast", match(explicitCastExpr().bind("cast"), ASTCtx));
3342 
3343         EXPECT_EQ(&Env.getResultObjectLocation(*BuiltinBitCast),
3344                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s"));
3345       });
3346 }
3347 
3348 TEST(TransferTest, ResultObjectLocationPropagatesThroughConditionalOperator) {
3349   std::string Code = R"(
3350     struct A {
3351       A(int);
3352     };
3353 
3354     void target(bool b) {
3355       A a = b ? A(0) : A(1);
3356       (void)0; // [[p]]
3357     }
3358   )";
3359   using ast_matchers::cxxConstructExpr;
3360   using ast_matchers::equals;
3361   using ast_matchers::hasArgument;
3362   using ast_matchers::integerLiteral;
3363   using ast_matchers::match;
3364   using ast_matchers::selectFirst;
3365   using ast_matchers::traverse;
3366   runDataflow(
3367       Code,
3368       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3369          ASTContext &ASTCtx) {
3370         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3371 
3372         auto *ConstructExpr0 = selectFirst<CXXConstructExpr>(
3373             "construct",
3374             match(cxxConstructExpr(hasArgument(0, integerLiteral(equals(0))))
3375                       .bind("construct"),
3376                   ASTCtx));
3377         auto *ConstructExpr1 = selectFirst<CXXConstructExpr>(
3378             "construct",
3379             match(cxxConstructExpr(hasArgument(0, integerLiteral(equals(1))))
3380                       .bind("construct"),
3381                   ASTCtx));
3382 
3383         auto &ALoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "a");
3384         EXPECT_EQ(&Env.getResultObjectLocation(*ConstructExpr0), &ALoc);
3385         EXPECT_EQ(&Env.getResultObjectLocation(*ConstructExpr1), &ALoc);
3386       });
3387 }
3388 
3389 TEST(TransferTest, ResultObjectLocationDontVisitNestedRecordDecl) {
3390   // This is a crash repro.
3391   // We used to crash because when propagating result objects, we would visit
3392   // nested record and function declarations, but we don't model fields used
3393   // only in these.
3394   std::string Code = R"(
3395     struct S1 {};
3396     struct S2 { S1 s1; };
3397     void target() {
3398       struct Nested {
3399         void f() {
3400           S2 s2 = { S1() };
3401         }
3402       };
3403     }
3404   )";
3405   runDataflow(
3406       Code,
3407       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3408          ASTContext &ASTCtx) {});
3409 }
3410 
3411 TEST(TransferTest, ResultObjectLocationDontVisitUnevaluatedContexts) {
3412   // This is a crash repro.
3413   // We used to crash because when propagating result objects, we would visit
3414   // unevaluated contexts, but we don't model fields used only in these.
3415 
3416   auto testFunction = [](llvm::StringRef Code, llvm::StringRef TargetFun) {
3417     runDataflow(
3418         Code,
3419         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3420            ASTContext &ASTCtx) {},
3421         LangStandard::lang_gnucxx17,
3422         /* ApplyBuiltinTransfer= */ true, TargetFun);
3423   };
3424 
3425   std::string Code = R"cc(
3426     // Definitions needed for `typeid`.
3427     namespace std {
3428       class type_info {};
3429       class bad_typeid {};
3430     }  // namespace std
3431 
3432     struct S1 {};
3433     struct S2 { S1 s1; };
3434 
3435     // We test each type of unevaluated context from a different target
3436     // function. Some types of unevaluated contexts may actually cause the
3437     // field `s1` to be modeled, and we don't want this to "pollute" the tests
3438     // for the other unevaluated contexts.
3439     void decltypeTarget() {
3440         decltype(S2{}) Dummy;
3441     }
3442     void typeofTarget() {
3443         typeof(S2{}) Dummy;
3444     }
3445     void typeidTarget() {
3446 #if __has_feature(cxx_rtti)
3447         typeid(S2{});
3448 #endif
3449     }
3450     void sizeofTarget() {
3451         sizeof(S2{});
3452     }
3453     void noexceptTarget() {
3454         noexcept(S2{});
3455     }
3456   )cc";
3457 
3458   testFunction(Code, "decltypeTarget");
3459   testFunction(Code, "typeofTarget");
3460   testFunction(Code, "typeidTarget");
3461   testFunction(Code, "sizeofTarget");
3462   testFunction(Code, "noexceptTarget");
3463 }
3464 
3465 TEST(TransferTest, StaticCast) {
3466   std::string Code = R"(
3467     void target(int Foo) {
3468       int Bar = static_cast<int>(Foo);
3469       // [[p]]
3470     }
3471   )";
3472   runDataflow(
3473       Code,
3474       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3475          ASTContext &ASTCtx) {
3476         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3477         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3478 
3479         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3480         ASSERT_THAT(FooDecl, NotNull());
3481 
3482         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3483         ASSERT_THAT(BarDecl, NotNull());
3484 
3485         const auto *FooVal = Env.getValue(*FooDecl);
3486         const auto *BarVal = Env.getValue(*BarDecl);
3487         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3488         EXPECT_TRUE(isa<IntegerValue>(BarVal));
3489         EXPECT_EQ(FooVal, BarVal);
3490       });
3491 }
3492 
3493 TEST(TransferTest, IntegralCast) {
3494   std::string Code = R"(
3495     void target(int Foo) {
3496       long Bar = Foo;
3497       // [[p]]
3498     }
3499   )";
3500   runDataflow(
3501       Code,
3502       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3503          ASTContext &ASTCtx) {
3504         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3505 
3506         const auto &FooVal = getValueForDecl<IntegerValue>(ASTCtx, Env, "Foo");
3507         const auto &BarVal = getValueForDecl<IntegerValue>(ASTCtx, Env, "Bar");
3508         EXPECT_EQ(&FooVal, &BarVal);
3509       });
3510 }
3511 
3512 TEST(TransferTest, IntegraltoBooleanCast) {
3513   std::string Code = R"(
3514     void target(int Foo) {
3515       bool Bar = Foo;
3516       // [[p]]
3517     }
3518   )";
3519   runDataflow(
3520       Code,
3521       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3522          ASTContext &ASTCtx) {
3523         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3524 
3525         const auto &FooVal = getValueForDecl(ASTCtx, Env, "Foo");
3526         const auto &BarVal = getValueForDecl(ASTCtx, Env, "Bar");
3527         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3528         EXPECT_TRUE(isa<BoolValue>(BarVal));
3529       });
3530 }
3531 
3532 TEST(TransferTest, IntegralToBooleanCastFromBool) {
3533   std::string Code = R"(
3534     void target(bool Foo) {
3535       int Zab = Foo;
3536       bool Bar = Zab;
3537       // [[p]]
3538     }
3539   )";
3540   runDataflow(
3541       Code,
3542       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3543          ASTContext &ASTCtx) {
3544         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3545 
3546         const auto &FooVal = getValueForDecl<BoolValue>(ASTCtx, Env, "Foo");
3547         const auto &BarVal = getValueForDecl<BoolValue>(ASTCtx, Env, "Bar");
3548         EXPECT_EQ(&FooVal, &BarVal);
3549       });
3550 }
3551 
3552 TEST(TransferTest, WidenBoolValueInIntegerVariable) {
3553   // This is a crash repro.
3554   // This test sets up a case where we perform widening on an integer variable
3555   // that contains a `BoolValue` for the previous iteration and an
3556   // `IntegerValue` for the current iteration. We used to crash on this because
3557   // `widenDistinctValues()` assumed that if the previous iteration had a
3558   // `BoolValue`, the current iteration would too.
3559   // FIXME: The real fix here is to make sure we never store `BoolValue`s in
3560   // integer variables; see also the comment in `widenDistinctValues()`.
3561   std::string Code = R"cc(
3562     struct S {
3563       int i;
3564       S *next;
3565     };
3566     void target(S *s) {
3567       for (; s; s = s->next)
3568         s->i = false;
3569     }
3570   )cc";
3571   runDataflow(Code,
3572               [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
3573                  ASTContext &) {});
3574 }
3575 
3576 TEST(TransferTest, NullToPointerCast) {
3577   std::string Code = R"(
3578     using my_nullptr_t = decltype(nullptr);
3579     struct Baz {};
3580     void target() {
3581       int *FooX = nullptr;
3582       int *FooY = nullptr;
3583       bool **Bar = nullptr;
3584       Baz *Baz = nullptr;
3585       my_nullptr_t Null = 0;
3586       // [[p]]
3587     }
3588   )";
3589   runDataflow(
3590       Code,
3591       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3592          ASTContext &ASTCtx) {
3593         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3594         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3595 
3596         const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
3597         ASSERT_THAT(FooXDecl, NotNull());
3598 
3599         const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
3600         ASSERT_THAT(FooYDecl, NotNull());
3601 
3602         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3603         ASSERT_THAT(BarDecl, NotNull());
3604 
3605         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3606         ASSERT_THAT(BazDecl, NotNull());
3607 
3608         const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
3609         ASSERT_THAT(NullDecl, NotNull());
3610 
3611         const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl));
3612         const auto *FooYVal = cast<PointerValue>(Env.getValue(*FooYDecl));
3613         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3614         const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl));
3615         const auto *NullVal = cast<PointerValue>(Env.getValue(*NullDecl));
3616 
3617         EXPECT_EQ(FooXVal, FooYVal);
3618         EXPECT_NE(FooXVal, BarVal);
3619         EXPECT_NE(FooXVal, BazVal);
3620         EXPECT_NE(BarVal, BazVal);
3621 
3622         const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
3623         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
3624         EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
3625 
3626         const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
3627         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
3628         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
3629 
3630         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
3631         EXPECT_TRUE(isa<RecordStorageLocation>(BazPointeeLoc));
3632         EXPECT_EQ(BazVal, &Env.fork().getOrCreateNullPointerValue(
3633                               BazPointeeLoc.getType()));
3634 
3635         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
3636         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
3637         EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
3638       });
3639 }
3640 
3641 TEST(TransferTest, PointerToMemberVariable) {
3642   std::string Code = R"(
3643     struct S {
3644       int i;
3645     };
3646     void target() {
3647       int S::*MemberPointer = &S::i;
3648       // [[p]]
3649     }
3650   )";
3651   runDataflow(
3652       Code,
3653       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3654          ASTContext &ASTCtx) {
3655         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3656 
3657         const ValueDecl *MemberPointerDecl =
3658             findValueDecl(ASTCtx, "MemberPointer");
3659         ASSERT_THAT(MemberPointerDecl, NotNull());
3660         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3661       });
3662 }
3663 
3664 TEST(TransferTest, PointerToMemberFunction) {
3665   std::string Code = R"(
3666     struct S {
3667       void Method();
3668     };
3669     void target() {
3670       void (S::*MemberPointer)() = &S::Method;
3671       // [[p]]
3672     }
3673   )";
3674   runDataflow(
3675       Code,
3676       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3677          ASTContext &ASTCtx) {
3678         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3679 
3680         const ValueDecl *MemberPointerDecl =
3681             findValueDecl(ASTCtx, "MemberPointer");
3682         ASSERT_THAT(MemberPointerDecl, NotNull());
3683         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3684       });
3685 }
3686 
3687 TEST(TransferTest, NullToMemberPointerCast) {
3688   std::string Code = R"(
3689     struct Foo {};
3690     void target() {
3691       int Foo::*MemberPointer = nullptr;
3692       // [[p]]
3693     }
3694   )";
3695   runDataflow(
3696       Code,
3697       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3698          ASTContext &ASTCtx) {
3699         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3700         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3701 
3702         const ValueDecl *MemberPointerDecl =
3703             findValueDecl(ASTCtx, "MemberPointer");
3704         ASSERT_THAT(MemberPointerDecl, NotNull());
3705         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3706       });
3707 }
3708 
3709 TEST(TransferTest, AddrOfValue) {
3710   std::string Code = R"(
3711     void target() {
3712       int Foo;
3713       int *Bar = &Foo;
3714       // [[p]]
3715     }
3716   )";
3717   runDataflow(
3718       Code,
3719       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3720          ASTContext &ASTCtx) {
3721         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3722         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3723 
3724         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3725         ASSERT_THAT(FooDecl, NotNull());
3726 
3727         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3728         ASSERT_THAT(BarDecl, NotNull());
3729 
3730         const auto *FooLoc =
3731             cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
3732         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3733         EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
3734       });
3735 }
3736 
3737 TEST(TransferTest, AddrOfReference) {
3738   std::string Code = R"(
3739     void target(int *Foo) {
3740       int *Bar = &(*Foo);
3741       // [[p]]
3742     }
3743   )";
3744   runDataflow(
3745       Code,
3746       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3747          ASTContext &ASTCtx) {
3748         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3749         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3750 
3751         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3752         ASSERT_THAT(FooDecl, NotNull());
3753 
3754         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3755         ASSERT_THAT(BarDecl, NotNull());
3756 
3757         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl));
3758         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3759         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
3760       });
3761 }
3762 
3763 TEST(TransferTest, CannotAnalyzeFunctionTemplate) {
3764   std::string Code = R"(
3765     template <typename T>
3766     void target() {}
3767   )";
3768   ASSERT_THAT_ERROR(
3769       checkDataflowWithNoopAnalysis(Code),
3770       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3771 }
3772 
3773 TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) {
3774   std::string Code = R"(
3775     template <typename T>
3776     struct A {
3777       void target() {}
3778     };
3779   )";
3780   ASSERT_THAT_ERROR(
3781       checkDataflowWithNoopAnalysis(Code),
3782       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3783 }
3784 
3785 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
3786   std::string Code = R"(
3787     struct A {
3788       int i;
3789     };
3790 
3791     void target(A Foo, A Bar, bool Cond) {
3792       A Baz = Cond ?  A(Foo) : A(Bar);
3793       // Make sure A::i is modeled.
3794       Baz.i;
3795       /*[[p]]*/
3796     }
3797   )";
3798   runDataflow(
3799       Code,
3800       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3801          ASTContext &ASTCtx) {
3802         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3803 
3804         auto *FooIVal = cast<IntegerValue>(getFieldValue(
3805             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo"), "i",
3806             ASTCtx, Env));
3807         auto *BarIVal = cast<IntegerValue>(getFieldValue(
3808             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar"), "i",
3809             ASTCtx, Env));
3810         auto *BazIVal = cast<IntegerValue>(getFieldValue(
3811             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Baz"), "i",
3812             ASTCtx, Env));
3813 
3814         EXPECT_NE(BazIVal, FooIVal);
3815         EXPECT_NE(BazIVal, BarIVal);
3816       });
3817 }
3818 
3819 TEST(TransferTest, VarDeclInDoWhile) {
3820   std::string Code = R"(
3821     void target(int *Foo) {
3822       do {
3823         int Bar = *Foo;
3824         // [[in_loop]]
3825       } while (false);
3826       (void)0;
3827       // [[after_loop]]
3828     }
3829   )";
3830   runDataflow(
3831       Code,
3832       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3833          ASTContext &ASTCtx) {
3834         const Environment &EnvInLoop =
3835             getEnvironmentAtAnnotation(Results, "in_loop");
3836         const Environment &EnvAfterLoop =
3837             getEnvironmentAtAnnotation(Results, "after_loop");
3838 
3839         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3840         ASSERT_THAT(FooDecl, NotNull());
3841 
3842         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3843         ASSERT_THAT(BarDecl, NotNull());
3844 
3845         const auto *FooVal =
3846             cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl));
3847         const auto *FooPointeeVal =
3848             cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc()));
3849 
3850         const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl));
3851         EXPECT_EQ(BarVal, FooPointeeVal);
3852 
3853         ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), IsNull());
3854       });
3855 }
3856 
3857 TEST(TransferTest, UnreachableAfterWhileTrue) {
3858   std::string Code = R"(
3859     void target() {
3860       while (true) {}
3861       (void)0;
3862       /*[[p]]*/
3863     }
3864   )";
3865   runDataflow(
3866       Code,
3867       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3868          ASTContext &ASTCtx) {
3869         // The node after the while-true is pruned because it is trivially
3870         // known to be unreachable.
3871         ASSERT_TRUE(Results.empty());
3872       });
3873 }
3874 
3875 TEST(TransferTest, AggregateInitialization) {
3876   std::string BracesCode = R"(
3877     struct A {
3878       int Foo;
3879     };
3880 
3881     struct B {
3882       int Bar;
3883       A Baz;
3884       int Qux;
3885     };
3886 
3887     void target(int BarArg, int FooArg, int QuxArg) {
3888       B Quux{BarArg, {FooArg}, QuxArg};
3889       B OtherB;
3890       /*[[p]]*/
3891     }
3892   )";
3893   std::string BraceElisionCode = R"(
3894     struct A {
3895       int Foo;
3896     };
3897 
3898     struct B {
3899       int Bar;
3900       A Baz;
3901       int Qux;
3902     };
3903 
3904     void target(int BarArg, int FooArg, int QuxArg) {
3905       B Quux = {BarArg, FooArg, QuxArg};
3906       B OtherB;
3907       /*[[p]]*/
3908     }
3909   )";
3910   for (const std::string &Code : {BracesCode, BraceElisionCode}) {
3911     runDataflow(
3912         Code,
3913         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3914            ASTContext &ASTCtx) {
3915           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3916           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3917 
3918           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3919           ASSERT_THAT(FooDecl, NotNull());
3920 
3921           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3922           ASSERT_THAT(BarDecl, NotNull());
3923 
3924           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3925           ASSERT_THAT(BazDecl, NotNull());
3926 
3927           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3928           ASSERT_THAT(QuxDecl, NotNull());
3929 
3930           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
3931           ASSERT_THAT(FooArgDecl, NotNull());
3932 
3933           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
3934           ASSERT_THAT(BarArgDecl, NotNull());
3935 
3936           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
3937           ASSERT_THAT(QuxArgDecl, NotNull());
3938 
3939           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
3940           ASSERT_THAT(QuuxDecl, NotNull());
3941 
3942           const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl));
3943           const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl));
3944           const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl));
3945 
3946           const auto &QuuxLoc =
3947               *cast<RecordStorageLocation>(Env.getStorageLocation(*QuuxDecl));
3948           const auto &BazLoc =
3949               *cast<RecordStorageLocation>(QuuxLoc.getChild(*BazDecl));
3950 
3951           EXPECT_EQ(getFieldValue(&QuuxLoc, *BarDecl, Env), BarArgVal);
3952           EXPECT_EQ(getFieldValue(&BazLoc, *FooDecl, Env), FooArgVal);
3953           EXPECT_EQ(getFieldValue(&QuuxLoc, *QuxDecl, Env), QuxArgVal);
3954 
3955           // Check that fields initialized in an initializer list are always
3956           // modeled in other instances of the same type.
3957           const auto &OtherBLoc =
3958               getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "OtherB");
3959           EXPECT_THAT(OtherBLoc.getChild(*BarDecl), NotNull());
3960           EXPECT_THAT(OtherBLoc.getChild(*BazDecl), NotNull());
3961           EXPECT_THAT(OtherBLoc.getChild(*QuxDecl), NotNull());
3962         });
3963   }
3964 }
3965 
3966 TEST(TransferTest, AggregateInitializationReferenceField) {
3967   std::string Code = R"(
3968     struct S {
3969       int &RefField;
3970     };
3971 
3972     void target(int i) {
3973       S s = { i };
3974       /*[[p]]*/
3975     }
3976   )";
3977   runDataflow(
3978       Code,
3979       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3980          ASTContext &ASTCtx) {
3981         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3982 
3983         const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField");
3984 
3985         auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i");
3986         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3987 
3988         EXPECT_EQ(SLoc.getChild(*RefFieldDecl), &ILoc);
3989       });
3990 }
3991 
3992 TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) {
3993   std::string Code = R"(
3994     struct S {
3995       int i1;
3996       int i2;
3997     };
3998 
3999     void target(int i) {
4000       S s = { i };
4001       /*[[p]]*/
4002     }
4003   )";
4004   runDataflow(
4005       Code,
4006       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4007          ASTContext &ASTCtx) {
4008         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4009 
4010         const ValueDecl *I1FieldDecl = findValueDecl(ASTCtx, "i1");
4011         const ValueDecl *I2FieldDecl = findValueDecl(ASTCtx, "i2");
4012 
4013         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
4014 
4015         auto &IValue = getValueForDecl<IntegerValue>(ASTCtx, Env, "i");
4016         auto &I1Value =
4017             *cast<IntegerValue>(getFieldValue(&SLoc, *I1FieldDecl, Env));
4018         EXPECT_EQ(&I1Value, &IValue);
4019         auto &I2Value =
4020             *cast<IntegerValue>(getFieldValue(&SLoc, *I2FieldDecl, Env));
4021         EXPECT_NE(&I2Value, &IValue);
4022       });
4023 }
4024 
4025 TEST(TransferTest, AggregateInitializationFunctionPointer) {
4026   // This is a repro for an assertion failure.
4027   // nullptr takes on the type of a const function pointer, but its type was
4028   // asserted to be equal to the *unqualified* type of Field, which no longer
4029   // included the const.
4030   std::string Code = R"(
4031     struct S {
4032       void (*const Field)();
4033     };
4034 
4035     void target() {
4036       S s{nullptr};
4037     }
4038   )";
4039   runDataflow(
4040       Code,
4041       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4042          ASTContext &ASTCtx) {});
4043 }
4044 
4045 TEST(TransferTest, AssignToUnionMember) {
4046   std::string Code = R"(
4047     union A {
4048       int Foo;
4049     };
4050 
4051     void target(int Bar) {
4052       A Baz;
4053       Baz.Foo = Bar;
4054       // [[p]]
4055     }
4056   )";
4057   runDataflow(
4058       Code,
4059       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4060          ASTContext &ASTCtx) {
4061         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4062         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4063 
4064         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4065         ASSERT_THAT(BazDecl, NotNull());
4066         ASSERT_TRUE(BazDecl->getType()->isUnionType());
4067 
4068         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
4069         FieldDecl *FooDecl = nullptr;
4070         for (FieldDecl *Field : BazFields) {
4071           if (Field->getNameAsString() == "Foo") {
4072             FooDecl = Field;
4073           } else {
4074             FAIL() << "Unexpected field: " << Field->getNameAsString();
4075           }
4076         }
4077         ASSERT_THAT(FooDecl, NotNull());
4078 
4079         const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>(
4080             Env.getStorageLocation(*BazDecl));
4081         ASSERT_THAT(BazLoc, NotNull());
4082 
4083         const auto *FooVal =
4084             cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env));
4085 
4086         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4087         ASSERT_THAT(BarDecl, NotNull());
4088         const auto *BarLoc = Env.getStorageLocation(*BarDecl);
4089         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
4090 
4091         EXPECT_EQ(Env.getValue(*BarLoc), FooVal);
4092       });
4093 }
4094 
4095 TEST(TransferTest, AssignFromBoolLiteral) {
4096   std::string Code = R"(
4097     void target() {
4098       bool Foo = true;
4099       bool Bar = false;
4100       // [[p]]
4101     }
4102   )";
4103   runDataflow(
4104       Code,
4105       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4106          ASTContext &ASTCtx) {
4107         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4108         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4109 
4110         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4111         ASSERT_THAT(FooDecl, NotNull());
4112 
4113         const auto *FooVal =
4114             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4115         ASSERT_THAT(FooVal, NotNull());
4116 
4117         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4118         ASSERT_THAT(BarDecl, NotNull());
4119 
4120         const auto *BarVal =
4121             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4122         ASSERT_THAT(BarVal, NotNull());
4123 
4124         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
4125         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
4126       });
4127 }
4128 
4129 TEST(TransferTest, AssignFromCompositeBoolExpression) {
4130   {
4131     std::string Code = R"(
4132     void target(bool Foo, bool Bar, bool Qux) {
4133       bool Baz = (Foo) && (Bar || Qux);
4134       // [[p]]
4135     }
4136   )";
4137     runDataflow(
4138         Code,
4139         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4140            ASTContext &ASTCtx) {
4141           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4142           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4143 
4144           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4145           ASSERT_THAT(FooDecl, NotNull());
4146 
4147           const auto *FooVal =
4148               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4149           ASSERT_THAT(FooVal, NotNull());
4150 
4151           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4152           ASSERT_THAT(BarDecl, NotNull());
4153 
4154           const auto *BarVal =
4155               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4156           ASSERT_THAT(BarVal, NotNull());
4157 
4158           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4159           ASSERT_THAT(QuxDecl, NotNull());
4160 
4161           const auto *QuxVal =
4162               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
4163           ASSERT_THAT(QuxVal, NotNull());
4164 
4165           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4166           ASSERT_THAT(BazDecl, NotNull());
4167 
4168           const auto *BazVal =
4169               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
4170           ASSERT_THAT(BazVal, NotNull());
4171           auto &A = Env.arena();
4172           EXPECT_EQ(&BazVal->formula(),
4173                     &A.makeAnd(FooVal->formula(),
4174                                A.makeOr(BarVal->formula(), QuxVal->formula())));
4175         });
4176   }
4177 
4178   {
4179     std::string Code = R"(
4180     void target(bool Foo, bool Bar, bool Qux) {
4181       bool Baz = (Foo && Qux) || (Bar);
4182       // [[p]]
4183     }
4184   )";
4185     runDataflow(
4186         Code,
4187         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4188            ASTContext &ASTCtx) {
4189           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4190           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4191 
4192           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4193           ASSERT_THAT(FooDecl, NotNull());
4194 
4195           const auto *FooVal =
4196               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4197           ASSERT_THAT(FooVal, NotNull());
4198 
4199           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4200           ASSERT_THAT(BarDecl, NotNull());
4201 
4202           const auto *BarVal =
4203               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4204           ASSERT_THAT(BarVal, NotNull());
4205 
4206           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4207           ASSERT_THAT(QuxDecl, NotNull());
4208 
4209           const auto *QuxVal =
4210               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
4211           ASSERT_THAT(QuxVal, NotNull());
4212 
4213           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4214           ASSERT_THAT(BazDecl, NotNull());
4215 
4216           const auto *BazVal =
4217               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
4218           ASSERT_THAT(BazVal, NotNull());
4219           auto &A = Env.arena();
4220           EXPECT_EQ(&BazVal->formula(),
4221                     &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()),
4222                               BarVal->formula()));
4223         });
4224   }
4225 
4226   {
4227     std::string Code = R"(
4228       void target(bool A, bool B, bool C, bool D) {
4229         bool Foo = ((A && B) && C) && D;
4230         // [[p]]
4231       }
4232     )";
4233     runDataflow(
4234         Code,
4235         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4236            ASTContext &ASTCtx) {
4237           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4238           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4239 
4240           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
4241           ASSERT_THAT(ADecl, NotNull());
4242 
4243           const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl));
4244           ASSERT_THAT(AVal, NotNull());
4245 
4246           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4247           ASSERT_THAT(BDecl, NotNull());
4248 
4249           const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl));
4250           ASSERT_THAT(BVal, NotNull());
4251 
4252           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4253           ASSERT_THAT(CDecl, NotNull());
4254 
4255           const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl));
4256           ASSERT_THAT(CVal, NotNull());
4257 
4258           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
4259           ASSERT_THAT(DDecl, NotNull());
4260 
4261           const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl));
4262           ASSERT_THAT(DVal, NotNull());
4263 
4264           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4265           ASSERT_THAT(FooDecl, NotNull());
4266 
4267           const auto *FooVal =
4268               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4269           ASSERT_THAT(FooVal, NotNull());
4270           auto &A = Env.arena();
4271           EXPECT_EQ(
4272               &FooVal->formula(),
4273               &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()),
4274                                    CVal->formula()),
4275                          DVal->formula()));
4276         });
4277   }
4278 }
4279 
4280 TEST(TransferTest, AssignFromBoolNegation) {
4281   std::string Code = R"(
4282     void target() {
4283       bool Foo = true;
4284       bool Bar = !(Foo);
4285       // [[p]]
4286     }
4287   )";
4288   runDataflow(
4289       Code,
4290       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4291          ASTContext &ASTCtx) {
4292         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4293         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4294 
4295         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4296         ASSERT_THAT(FooDecl, NotNull());
4297 
4298         const auto *FooVal =
4299             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4300         ASSERT_THAT(FooVal, NotNull());
4301 
4302         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4303         ASSERT_THAT(BarDecl, NotNull());
4304 
4305         const auto *BarVal =
4306             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4307         ASSERT_THAT(BarVal, NotNull());
4308         auto &A = Env.arena();
4309         EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula()));
4310       });
4311 }
4312 
4313 TEST(TransferTest, BuiltinExpect) {
4314   std::string Code = R"(
4315     void target(long Foo) {
4316       long Bar = __builtin_expect(Foo, true);
4317       /*[[p]]*/
4318     }
4319   )";
4320   runDataflow(
4321       Code,
4322       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4323          ASTContext &ASTCtx) {
4324         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4325         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4326 
4327         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4328         ASSERT_THAT(FooDecl, NotNull());
4329 
4330         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4331         ASSERT_THAT(BarDecl, NotNull());
4332 
4333         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4334       });
4335 }
4336 
4337 // `__builtin_expect` takes and returns a `long` argument, so other types
4338 // involve casts. This verifies that we identify the input and output in that
4339 // case.
4340 TEST(TransferTest, BuiltinExpectBoolArg) {
4341   std::string Code = R"(
4342     void target(bool Foo) {
4343       bool Bar = __builtin_expect(Foo, true);
4344       /*[[p]]*/
4345     }
4346   )";
4347   runDataflow(
4348       Code,
4349       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4350          ASTContext &ASTCtx) {
4351         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4352         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4353 
4354         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4355         ASSERT_THAT(FooDecl, NotNull());
4356 
4357         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4358         ASSERT_THAT(BarDecl, NotNull());
4359 
4360         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4361       });
4362 }
4363 
4364 TEST(TransferTest, BuiltinUnreachable) {
4365   std::string Code = R"(
4366     void target(bool Foo) {
4367       bool Bar = false;
4368       if (Foo)
4369         Bar = Foo;
4370       else
4371         __builtin_unreachable();
4372       (void)0;
4373       /*[[p]]*/
4374     }
4375   )";
4376   runDataflow(
4377       Code,
4378       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4379          ASTContext &ASTCtx) {
4380         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4381         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4382 
4383         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4384         ASSERT_THAT(FooDecl, NotNull());
4385 
4386         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4387         ASSERT_THAT(BarDecl, NotNull());
4388 
4389         // `__builtin_unreachable` promises that the code is
4390         // unreachable, so the compiler treats the "then" branch as the
4391         // only possible predecessor of this statement.
4392         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4393       });
4394 }
4395 
4396 TEST(TransferTest, BuiltinTrap) {
4397   std::string Code = R"(
4398     void target(bool Foo) {
4399       bool Bar = false;
4400       if (Foo)
4401         Bar = Foo;
4402       else
4403         __builtin_trap();
4404       (void)0;
4405       /*[[p]]*/
4406     }
4407   )";
4408   runDataflow(
4409       Code,
4410       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4411          ASTContext &ASTCtx) {
4412         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4413         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4414 
4415         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4416         ASSERT_THAT(FooDecl, NotNull());
4417 
4418         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4419         ASSERT_THAT(BarDecl, NotNull());
4420 
4421         // `__builtin_trap` ensures program termination, so only the
4422         // "then" branch is a predecessor of this statement.
4423         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4424       });
4425 }
4426 
4427 TEST(TransferTest, BuiltinDebugTrap) {
4428   std::string Code = R"(
4429     void target(bool Foo) {
4430       bool Bar = false;
4431       if (Foo)
4432         Bar = Foo;
4433       else
4434         __builtin_debugtrap();
4435       (void)0;
4436       /*[[p]]*/
4437     }
4438   )";
4439   runDataflow(
4440       Code,
4441       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4442          ASTContext &ASTCtx) {
4443         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4444         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4445 
4446         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4447         ASSERT_THAT(FooDecl, NotNull());
4448 
4449         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4450         ASSERT_THAT(BarDecl, NotNull());
4451 
4452         // `__builtin_debugtrap` doesn't ensure program termination.
4453         EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4454       });
4455 }
4456 
4457 TEST(TransferTest, StaticIntSingleVarDecl) {
4458   std::string Code = R"(
4459     void target() {
4460       static int Foo;
4461       // [[p]]
4462     }
4463   )";
4464   runDataflow(
4465       Code,
4466       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4467          ASTContext &ASTCtx) {
4468         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4469         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4470 
4471         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4472         ASSERT_THAT(FooDecl, NotNull());
4473 
4474         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
4475         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
4476 
4477         const Value *FooVal = Env.getValue(*FooLoc);
4478         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
4479       });
4480 }
4481 
4482 TEST(TransferTest, StaticIntGroupVarDecl) {
4483   std::string Code = R"(
4484     void target() {
4485       static int Foo, Bar;
4486       (void)0;
4487       // [[p]]
4488     }
4489   )";
4490   runDataflow(
4491       Code,
4492       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4493          ASTContext &ASTCtx) {
4494         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4495         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4496 
4497         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4498         ASSERT_THAT(FooDecl, NotNull());
4499 
4500         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4501         ASSERT_THAT(BarDecl, NotNull());
4502 
4503         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
4504         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
4505 
4506         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4507         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
4508 
4509         const Value *FooVal = Env.getValue(*FooLoc);
4510         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
4511 
4512         const Value *BarVal = Env.getValue(*BarLoc);
4513         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
4514 
4515         EXPECT_NE(FooVal, BarVal);
4516       });
4517 }
4518 
4519 TEST(TransferTest, GlobalIntVarDecl) {
4520   std::string Code = R"(
4521     static int Foo;
4522 
4523     void target() {
4524       int Bar = Foo;
4525       int Baz = Foo;
4526       // [[p]]
4527     }
4528   )";
4529   runDataflow(
4530       Code,
4531       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4532          ASTContext &ASTCtx) {
4533         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4534         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4535 
4536         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4537         ASSERT_THAT(BarDecl, NotNull());
4538 
4539         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4540         ASSERT_THAT(BazDecl, NotNull());
4541 
4542         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4543         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4544         EXPECT_EQ(BarVal, BazVal);
4545       });
4546 }
4547 
4548 TEST(TransferTest, StaticMemberIntVarDecl) {
4549   std::string Code = R"(
4550     struct A {
4551       static int Foo;
4552     };
4553 
4554     void target(A a) {
4555       int Bar = a.Foo;
4556       int Baz = a.Foo;
4557       // [[p]]
4558     }
4559   )";
4560   runDataflow(
4561       Code,
4562       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4563          ASTContext &ASTCtx) {
4564         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4565         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4566 
4567         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4568         ASSERT_THAT(BarDecl, NotNull());
4569 
4570         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4571         ASSERT_THAT(BazDecl, NotNull());
4572 
4573         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4574         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4575         EXPECT_EQ(BarVal, BazVal);
4576       });
4577 }
4578 
4579 TEST(TransferTest, StaticMemberRefVarDecl) {
4580   std::string Code = R"(
4581     struct A {
4582       static int &Foo;
4583     };
4584 
4585     void target(A a) {
4586       int Bar = a.Foo;
4587       int Baz = a.Foo;
4588       // [[p]]
4589     }
4590   )";
4591   runDataflow(
4592       Code,
4593       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4594          ASTContext &ASTCtx) {
4595         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4596         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4597 
4598         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4599         ASSERT_THAT(BarDecl, NotNull());
4600 
4601         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4602         ASSERT_THAT(BazDecl, NotNull());
4603 
4604         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4605         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4606         EXPECT_EQ(BarVal, BazVal);
4607       });
4608 }
4609 
4610 TEST(TransferTest, AssignMemberBeforeCopy) {
4611   std::string Code = R"(
4612     struct A {
4613       int Foo;
4614     };
4615 
4616     void target() {
4617       A A1;
4618       A A2;
4619       int Bar;
4620       A1.Foo = Bar;
4621       A2 = A1;
4622       // [[p]]
4623     }
4624   )";
4625   runDataflow(
4626       Code,
4627       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4628          ASTContext &ASTCtx) {
4629         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4630         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4631 
4632         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4633         ASSERT_THAT(FooDecl, NotNull());
4634 
4635         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4636         ASSERT_THAT(BarDecl, NotNull());
4637 
4638         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
4639         ASSERT_THAT(A1Decl, NotNull());
4640 
4641         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
4642         ASSERT_THAT(A2Decl, NotNull());
4643 
4644         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4645 
4646         const auto &A2Loc =
4647             *cast<RecordStorageLocation>(Env.getStorageLocation(*A2Decl));
4648         EXPECT_EQ(getFieldValue(&A2Loc, *FooDecl, Env), BarVal);
4649       });
4650 }
4651 
4652 TEST(TransferTest, BooleanEquality) {
4653   std::string Code = R"(
4654     void target(bool Bar) {
4655       bool Foo = true;
4656       if (Bar == Foo) {
4657         (void)0;
4658         /*[[p-then]]*/
4659       } else {
4660         (void)0;
4661         /*[[p-else]]*/
4662       }
4663     }
4664   )";
4665   runDataflow(
4666       Code,
4667       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4668          ASTContext &ASTCtx) {
4669         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4670         const Environment &EnvThen =
4671             getEnvironmentAtAnnotation(Results, "p-then");
4672         const Environment &EnvElse =
4673             getEnvironmentAtAnnotation(Results, "p-else");
4674 
4675         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4676         ASSERT_THAT(BarDecl, NotNull());
4677 
4678         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4679         EXPECT_TRUE(EnvThen.proves(BarValThen));
4680 
4681         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4682         EXPECT_TRUE(EnvElse.proves(EnvElse.arena().makeNot(BarValElse)));
4683       });
4684 }
4685 
4686 TEST(TransferTest, BooleanInequality) {
4687   std::string Code = R"(
4688     void target(bool Bar) {
4689       bool Foo = true;
4690       if (Bar != Foo) {
4691         (void)0;
4692         /*[[p-then]]*/
4693       } else {
4694         (void)0;
4695         /*[[p-else]]*/
4696       }
4697     }
4698   )";
4699   runDataflow(
4700       Code,
4701       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4702          ASTContext &ASTCtx) {
4703         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4704         const Environment &EnvThen =
4705             getEnvironmentAtAnnotation(Results, "p-then");
4706         const Environment &EnvElse =
4707             getEnvironmentAtAnnotation(Results, "p-else");
4708 
4709         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4710         ASSERT_THAT(BarDecl, NotNull());
4711 
4712         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4713         EXPECT_TRUE(EnvThen.proves(EnvThen.arena().makeNot(BarValThen)));
4714 
4715         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4716         EXPECT_TRUE(EnvElse.proves(BarValElse));
4717       });
4718 }
4719 
4720 TEST(TransferTest, PointerEquality) {
4721   std::string Code = R"cc(
4722     void target() {
4723       int i = 0;
4724       int i_other = 0;
4725       int *p1 = &i;
4726       int *p2 = &i;
4727       int *p_other = &i_other;
4728       int *null = nullptr;
4729 
4730       bool p1_eq_p1 = (p1 == p1);
4731       bool p1_eq_p2 = (p1 == p2);
4732       bool p1_eq_p_other = (p1 == p_other);
4733 
4734       bool p1_eq_null = (p1 == null);
4735       bool p1_eq_nullptr = (p1 == nullptr);
4736       bool null_eq_nullptr = (null == nullptr);
4737       bool nullptr_eq_nullptr = (nullptr == nullptr);
4738 
4739       // We won't duplicate all of the tests above with `!=`, as we know that
4740       // the implementation simply negates the result of the `==` comparison.
4741       // Instaed, just spot-check one case.
4742       bool p1_ne_p1 = (p1 != p1);
4743 
4744       (void)0; // [[p]]
4745     }
4746   )cc";
4747   runDataflow(
4748       Code,
4749       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4750          ASTContext &ASTCtx) {
4751         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4752 
4753         // Check the we have indeed set things up so that `p1` and `p2` have
4754         // different pointer values.
4755         EXPECT_NE(&getValueForDecl<PointerValue>(ASTCtx, Env, "p1"),
4756                   &getValueForDecl<PointerValue>(ASTCtx, Env, "p2"));
4757 
4758         EXPECT_EQ(&getValueForDecl<BoolValue>(ASTCtx, Env, "p1_eq_p1"),
4759                   &Env.getBoolLiteralValue(true));
4760         EXPECT_EQ(&getValueForDecl<BoolValue>(ASTCtx, Env, "p1_eq_p2"),
4761                   &Env.getBoolLiteralValue(true));
4762         EXPECT_TRUE(isa<AtomicBoolValue>(
4763             getValueForDecl<BoolValue>(ASTCtx, Env, "p1_eq_p_other")));
4764 
4765         EXPECT_TRUE(isa<AtomicBoolValue>(
4766             getValueForDecl<BoolValue>(ASTCtx, Env, "p1_eq_null")));
4767         EXPECT_TRUE(isa<AtomicBoolValue>(
4768             getValueForDecl<BoolValue>(ASTCtx, Env, "p1_eq_nullptr")));
4769         EXPECT_EQ(&getValueForDecl<BoolValue>(ASTCtx, Env, "null_eq_nullptr"),
4770                   &Env.getBoolLiteralValue(true));
4771         EXPECT_EQ(
4772             &getValueForDecl<BoolValue>(ASTCtx, Env, "nullptr_eq_nullptr"),
4773             &Env.getBoolLiteralValue(true));
4774 
4775         EXPECT_EQ(&getValueForDecl<BoolValue>(ASTCtx, Env, "p1_ne_p1"),
4776                   &Env.getBoolLiteralValue(false));
4777       });
4778 }
4779 
4780 TEST(TransferTest, PointerEqualityUnionMembers) {
4781   std::string Code = R"cc(
4782     union U {
4783       int i1;
4784       int i2;
4785     };
4786     void target() {
4787       U u;
4788       bool i1_eq_i2 = (&u.i1 == &u.i2);
4789 
4790       (void)0; // [[p]]
4791     }
4792   )cc";
4793   runDataflow(
4794       Code,
4795       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4796          ASTContext &ASTCtx) {
4797         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4798 
4799         // FIXME: By the standard, `u.i1` and `u.i2` should have the same
4800         // address, but we don't yet model this property of union members
4801         // correctly. The result is therefore weaker than it could be (just an
4802         // atom rather than a true literal), though not wrong.
4803         EXPECT_TRUE(isa<AtomicBoolValue>(
4804             getValueForDecl<BoolValue>(ASTCtx, Env, "i1_eq_i2")));
4805       });
4806 }
4807 
4808 TEST(TransferTest, IntegerLiteralEquality) {
4809   std::string Code = R"(
4810     void target() {
4811       bool equal = (42 == 42);
4812       // [[p]]
4813     }
4814   )";
4815   runDataflow(
4816       Code,
4817       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4818          ASTContext &ASTCtx) {
4819         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4820 
4821         auto &Equal =
4822             getValueForDecl<BoolValue>(ASTCtx, Env, "equal").formula();
4823         EXPECT_TRUE(Env.proves(Equal));
4824       });
4825 }
4826 
4827 TEST(TransferTest, CorrelatedBranches) {
4828   std::string Code = R"(
4829     void target(bool B, bool C) {
4830       if (B) {
4831         return;
4832       }
4833       (void)0;
4834       /*[[p0]]*/
4835       if (C) {
4836         B = true;
4837         /*[[p1]]*/
4838       }
4839       if (B) {
4840         (void)0;
4841         /*[[p2]]*/
4842       }
4843     }
4844   )";
4845   runDataflow(
4846       Code,
4847       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4848          ASTContext &ASTCtx) {
4849         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
4850 
4851         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4852         ASSERT_THAT(CDecl, NotNull());
4853 
4854         {
4855           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
4856           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4857           ASSERT_THAT(BDecl, NotNull());
4858           auto &BVal = getFormula(*BDecl, Env);
4859 
4860           EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal)));
4861         }
4862 
4863         {
4864           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
4865           auto &CVal = getFormula(*CDecl, Env);
4866           EXPECT_TRUE(Env.proves(CVal));
4867         }
4868 
4869         {
4870           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
4871           auto &CVal = getFormula(*CDecl, Env);
4872           EXPECT_TRUE(Env.proves(CVal));
4873         }
4874       });
4875 }
4876 
4877 TEST(TransferTest, LoopWithAssignmentConverges) {
4878   std::string Code = R"(
4879     bool foo();
4880 
4881     void target() {
4882        do {
4883         bool Bar = foo();
4884         if (Bar) break;
4885         (void)Bar;
4886         /*[[p]]*/
4887       } while (true);
4888     }
4889   )";
4890   // The key property that we are verifying is implicit in `runDataflow` --
4891   // namely, that the analysis succeeds, rather than hitting the maximum number
4892   // of iterations.
4893   runDataflow(
4894       Code,
4895       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4896          ASTContext &ASTCtx) {
4897         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4898         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4899 
4900         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4901         ASSERT_THAT(BarDecl, NotNull());
4902 
4903         auto &BarVal = getFormula(*BarDecl, Env);
4904         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4905       });
4906 }
4907 
4908 TEST(TransferTest, LoopWithStagedAssignments) {
4909   std::string Code = R"(
4910     bool foo();
4911 
4912     void target() {
4913       bool Bar = false;
4914       bool Err = false;
4915       while (foo()) {
4916         if (Bar)
4917           Err = true;
4918         Bar = true;
4919         /*[[p]]*/
4920       }
4921     }
4922   )";
4923   runDataflow(
4924       Code,
4925       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4926          ASTContext &ASTCtx) {
4927         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4928         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4929 
4930         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4931         ASSERT_THAT(BarDecl, NotNull());
4932         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
4933         ASSERT_THAT(ErrDecl, NotNull());
4934 
4935         auto &BarVal = getFormula(*BarDecl, Env);
4936         auto &ErrVal = getFormula(*ErrDecl, Env);
4937         EXPECT_TRUE(Env.proves(BarVal));
4938         // An unsound analysis, for example only evaluating the loop once, can
4939         // conclude that `Err` is false. So, we test that this conclusion is not
4940         // reached.
4941         EXPECT_FALSE(Env.proves(Env.arena().makeNot(ErrVal)));
4942       });
4943 }
4944 
4945 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
4946   std::string Code = R"(
4947     bool &foo();
4948 
4949     void target() {
4950        do {
4951         bool& Bar = foo();
4952         if (Bar) break;
4953         (void)Bar;
4954         /*[[p]]*/
4955       } while (true);
4956     }
4957   )";
4958   // The key property that we are verifying is that the analysis succeeds,
4959   // rather than hitting the maximum number of iterations.
4960   runDataflow(
4961       Code,
4962       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4963          ASTContext &ASTCtx) {
4964         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4965         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4966 
4967         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4968         ASSERT_THAT(BarDecl, NotNull());
4969 
4970         auto &BarVal = getFormula(*BarDecl, Env);
4971         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4972       });
4973 }
4974 
4975 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
4976   std::string Code = R"(
4977     struct Lookup {
4978       int x;
4979     };
4980 
4981     void target(Lookup val, bool b) {
4982       const Lookup* l = nullptr;
4983       while (b) {
4984         l = &val;
4985         /*[[p-inner]]*/
4986       }
4987       (void)0;
4988       /*[[p-outer]]*/
4989     }
4990   )";
4991   // The key property that we are verifying is implicit in `runDataflow` --
4992   // namely, that the analysis succeeds, rather than hitting the maximum number
4993   // of iterations.
4994   runDataflow(
4995       Code,
4996       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4997          ASTContext &ASTCtx) {
4998         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
4999         const Environment &InnerEnv =
5000             getEnvironmentAtAnnotation(Results, "p-inner");
5001         const Environment &OuterEnv =
5002             getEnvironmentAtAnnotation(Results, "p-outer");
5003 
5004         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
5005         ASSERT_THAT(ValDecl, NotNull());
5006 
5007         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
5008         ASSERT_THAT(LDecl, NotNull());
5009 
5010         // Inner.
5011         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
5012         ASSERT_THAT(LVal, NotNull());
5013 
5014         EXPECT_EQ(&LVal->getPointeeLoc(),
5015                   InnerEnv.getStorageLocation(*ValDecl));
5016 
5017         // Outer.
5018         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
5019         ASSERT_THAT(LVal, NotNull());
5020 
5021         // The loop body may not have been executed, so we should not conclude
5022         // that `l` points to `val`.
5023         EXPECT_NE(&LVal->getPointeeLoc(),
5024                   OuterEnv.getStorageLocation(*ValDecl));
5025       });
5026 }
5027 
5028 TEST(TransferTest, LoopDereferencingChangingPointerConverges) {
5029   std::string Code = R"cc(
5030     bool some_condition();
5031 
5032     void target(int i1, int i2) {
5033       int *p = &i1;
5034       while (true) {
5035         (void)*p;
5036         if (some_condition())
5037           p = &i1;
5038         else
5039           p = &i2;
5040       }
5041     }
5042   )cc";
5043   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
5044 }
5045 
5046 TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
5047   std::string Code = R"cc(
5048     struct Lookup {
5049       int x;
5050     };
5051 
5052     bool some_condition();
5053 
5054     void target(Lookup l1, Lookup l2) {
5055       Lookup *l = &l1;
5056       while (true) {
5057         (void)l->x;
5058         if (some_condition())
5059           l = &l1;
5060         else
5061           l = &l2;
5062       }
5063     }
5064   )cc";
5065   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
5066 }
5067 
5068 TEST(TransferTest, LoopWithShortCircuitedConditionConverges) {
5069   std::string Code = R"cc(
5070     bool foo();
5071 
5072     void target() {
5073       bool c = false;
5074       while (foo() || foo()) {
5075         c = true;
5076       }
5077     }
5078   )cc";
5079   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
5080 }
5081 
5082 TEST(TransferTest, LoopCanProveInvariantForBoolean) {
5083   // Check that we can prove `b` is always false in the loop.
5084   // This test exercises the logic in `widenDistinctValues()` that preserves
5085   // information if the boolean can be proved to be either true or false in both
5086   // the previous and current iteration.
5087   std::string Code = R"cc(
5088     int return_int();
5089     void target() {
5090       bool b = return_int() == 0;
5091       if (b) return;
5092       while (true) {
5093         b;
5094         // [[p]]
5095         b = return_int() == 0;
5096         if (b) return;
5097       }
5098     }
5099   )cc";
5100   runDataflow(
5101       Code,
5102       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5103          ASTContext &ASTCtx) {
5104         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5105         auto &BVal = getValueForDecl<BoolValue>(ASTCtx, Env, "b");
5106         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal.formula())));
5107       });
5108 }
5109 
5110 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
5111   std::string Code = R"cc(
5112     union Union {
5113       int A;
5114       float B;
5115     };
5116 
5117     void foo() {
5118       Union A;
5119       Union B;
5120       A = B;
5121     }
5122   )cc";
5123   // This is a crash regression test when calling the transfer function on a
5124   // `CXXThisExpr` that refers to a union.
5125   runDataflow(
5126       Code,
5127       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
5128          ASTContext &) {},
5129       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
5130 }
5131 
5132 TEST(TransferTest, DoesNotCrashOnNullChildren) {
5133   std::string Code = (CoroutineLibrary + R"cc(
5134     task target() noexcept {
5135       co_return;
5136     }
5137   )cc")
5138                          .str();
5139   // This is a crash regression test when calling `AdornedCFG::build` on a
5140   // statement (in this case, the `CoroutineBodyStmt`) with null children.
5141   runDataflow(
5142       Code,
5143       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
5144          ASTContext &) {},
5145       LangStandard::lang_cxx20, /*ApplyBuiltinTransfer=*/true);
5146 }
5147 
5148 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
5149   std::string Code = R"(
5150     struct A {
5151       int Foo;
5152       int Bar;
5153     };
5154 
5155     void target() {
5156       int Qux;
5157       A Baz;
5158       Baz.Foo = Qux;
5159       auto &FooRef = Baz.Foo;
5160       auto &BarRef = Baz.Bar;
5161       auto &[BoundFooRef, BoundBarRef] = Baz;
5162       // [[p]]
5163     }
5164   )";
5165   runDataflow(
5166       Code,
5167       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5168          ASTContext &ASTCtx) {
5169         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5170         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5171 
5172         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
5173         ASSERT_THAT(FooRefDecl, NotNull());
5174 
5175         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
5176         ASSERT_THAT(BarRefDecl, NotNull());
5177 
5178         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
5179         ASSERT_THAT(QuxDecl, NotNull());
5180 
5181         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
5182         ASSERT_THAT(BoundFooRefDecl, NotNull());
5183 
5184         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
5185         ASSERT_THAT(BoundBarRefDecl, NotNull());
5186 
5187         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
5188         ASSERT_THAT(FooRefLoc, NotNull());
5189 
5190         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
5191         ASSERT_THAT(BarRefLoc, NotNull());
5192 
5193         const Value *QuxVal = Env.getValue(*QuxDecl);
5194         ASSERT_THAT(QuxVal, NotNull());
5195 
5196         const StorageLocation *BoundFooRefLoc =
5197             Env.getStorageLocation(*BoundFooRefDecl);
5198         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
5199 
5200         const StorageLocation *BoundBarRefLoc =
5201             Env.getStorageLocation(*BoundBarRefDecl);
5202         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
5203 
5204         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
5205       });
5206 }
5207 
5208 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
5209   std::string Code = R"(
5210     struct A {
5211       int &Foo;
5212       int &Bar;
5213     };
5214 
5215     void target(A Baz) {
5216       int Qux;
5217       Baz.Foo = Qux;
5218       auto &FooRef = Baz.Foo;
5219       auto &BarRef = Baz.Bar;
5220       auto &[BoundFooRef, BoundBarRef] = Baz;
5221       // [[p]]
5222     }
5223   )";
5224   runDataflow(
5225       Code,
5226       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5227          ASTContext &ASTCtx) {
5228         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5229         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5230 
5231         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
5232         ASSERT_THAT(FooRefDecl, NotNull());
5233 
5234         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
5235         ASSERT_THAT(BarRefDecl, NotNull());
5236 
5237         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
5238         ASSERT_THAT(QuxDecl, NotNull());
5239 
5240         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
5241         ASSERT_THAT(BoundFooRefDecl, NotNull());
5242 
5243         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
5244         ASSERT_THAT(BoundBarRefDecl, NotNull());
5245 
5246         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
5247         ASSERT_THAT(FooRefLoc, NotNull());
5248 
5249         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
5250         ASSERT_THAT(BarRefLoc, NotNull());
5251 
5252         const Value *QuxVal = Env.getValue(*QuxDecl);
5253         ASSERT_THAT(QuxVal, NotNull());
5254 
5255         const StorageLocation *BoundFooRefLoc =
5256             Env.getStorageLocation(*BoundFooRefDecl);
5257         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
5258 
5259         const StorageLocation *BoundBarRefLoc =
5260             Env.getStorageLocation(*BoundBarRefDecl);
5261         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
5262 
5263         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
5264       });
5265 }
5266 
5267 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
5268   std::string Code = R"(
5269     struct A {
5270       int Foo;
5271       int Bar;
5272     };
5273 
5274     void target() {
5275       int Qux;
5276       A Baz;
5277       Baz.Foo = Qux;
5278       auto &FooRef = Baz.Foo;
5279       auto &BarRef = Baz.Bar;
5280       auto [BoundFoo, BoundBar] = Baz;
5281       // [[p]]
5282     }
5283   )";
5284   runDataflow(
5285       Code,
5286       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5287          ASTContext &ASTCtx) {
5288         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5289         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5290 
5291         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
5292         ASSERT_THAT(FooRefDecl, NotNull());
5293 
5294         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
5295         ASSERT_THAT(BarRefDecl, NotNull());
5296 
5297         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5298         ASSERT_THAT(BoundFooDecl, NotNull());
5299 
5300         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5301         ASSERT_THAT(BoundBarDecl, NotNull());
5302 
5303         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
5304         ASSERT_THAT(QuxDecl, NotNull());
5305 
5306         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
5307         ASSERT_THAT(FooRefLoc, NotNull());
5308 
5309         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
5310         ASSERT_THAT(BarRefLoc, NotNull());
5311 
5312         const Value *QuxVal = Env.getValue(*QuxDecl);
5313         ASSERT_THAT(QuxVal, NotNull());
5314 
5315         const StorageLocation *BoundFooLoc =
5316             Env.getStorageLocation(*BoundFooDecl);
5317         EXPECT_NE(BoundFooLoc, FooRefLoc);
5318 
5319         const StorageLocation *BoundBarLoc =
5320             Env.getStorageLocation(*BoundBarDecl);
5321         EXPECT_NE(BoundBarLoc, BarRefLoc);
5322 
5323         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
5324       });
5325 }
5326 
5327 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
5328   std::string Code = R"(
5329     namespace std {
5330     using size_t = int;
5331     template <class> struct tuple_size;
5332     template <std::size_t, class> struct tuple_element;
5333     template <class...> class tuple;
5334 
5335     namespace {
5336     template <class T, T v>
5337     struct size_helper { static const T value = v; };
5338     } // namespace
5339 
5340     template <class... T>
5341     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
5342 
5343     template <std::size_t I, class... T>
5344     struct tuple_element<I, tuple<T...>> {
5345       using type =  __type_pack_element<I, T...>;
5346     };
5347 
5348     template <class...> class tuple {};
5349 
5350     template <std::size_t I, class... T>
5351     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
5352     } // namespace std
5353 
5354     std::tuple<bool, int> makeTuple();
5355 
5356     void target(bool B) {
5357       auto [BoundFoo, BoundBar] = makeTuple();
5358       bool Baz;
5359       // Include if-then-else to test interaction of `BindingDecl` with join.
5360       if (B) {
5361         Baz = BoundFoo;
5362         (void)BoundBar;
5363         // [[p1]]
5364       } else {
5365         Baz = BoundFoo;
5366       }
5367       (void)0;
5368       // [[p2]]
5369     }
5370   )";
5371   runDataflow(
5372       Code,
5373       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5374          ASTContext &ASTCtx) {
5375         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
5376         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
5377 
5378         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5379         ASSERT_THAT(BoundFooDecl, NotNull());
5380 
5381         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5382         ASSERT_THAT(BoundBarDecl, NotNull());
5383 
5384         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5385         ASSERT_THAT(BazDecl, NotNull());
5386 
5387         // BindingDecls always map to references -- either lvalue or rvalue, so
5388         // we still need to skip here.
5389         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
5390         ASSERT_THAT(BoundFooValue, NotNull());
5391         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
5392 
5393         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
5394         ASSERT_THAT(BoundBarValue, NotNull());
5395         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
5396 
5397         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
5398         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
5399 
5400         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
5401 
5402         // Test that `BoundFooDecl` retains the value we expect, after the join.
5403         BoundFooValue = Env2.getValue(*BoundFooDecl);
5404         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
5405       });
5406 }
5407 
5408 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
5409   std::string Code = R"(
5410     namespace std {
5411     using size_t = int;
5412     template <class> struct tuple_size;
5413     template <std::size_t, class> struct tuple_element;
5414     template <class...> class tuple;
5415 
5416     namespace {
5417     template <class T, T v>
5418     struct size_helper { static const T value = v; };
5419     } // namespace
5420 
5421     template <class... T>
5422     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
5423 
5424     template <std::size_t I, class... T>
5425     struct tuple_element<I, tuple<T...>> {
5426       using type =  __type_pack_element<I, T...>;
5427     };
5428 
5429     template <class...> class tuple {};
5430 
5431     template <std::size_t I, class... T>
5432     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
5433     } // namespace std
5434 
5435     std::tuple<bool, int> &getTuple();
5436 
5437     void target(bool B) {
5438       auto &[BoundFoo, BoundBar] = getTuple();
5439       bool Baz;
5440       // Include if-then-else to test interaction of `BindingDecl` with join.
5441       if (B) {
5442         Baz = BoundFoo;
5443         (void)BoundBar;
5444         // [[p1]]
5445       } else {
5446         Baz = BoundFoo;
5447       }
5448       (void)0;
5449       // [[p2]]
5450     }
5451   )";
5452   runDataflow(
5453       Code,
5454       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5455          ASTContext &ASTCtx) {
5456         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
5457         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
5458 
5459         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5460         ASSERT_THAT(BoundFooDecl, NotNull());
5461 
5462         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5463         ASSERT_THAT(BoundBarDecl, NotNull());
5464 
5465         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5466         ASSERT_THAT(BazDecl, NotNull());
5467 
5468         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
5469         ASSERT_THAT(BoundFooValue, NotNull());
5470         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
5471 
5472         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
5473         ASSERT_THAT(BoundBarValue, NotNull());
5474         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
5475 
5476         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
5477         // works as expected. We don't test aliasing properties of the
5478         // reference, because we don't model `std::get` and so have no way to
5479         // equate separate references into the tuple.
5480         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
5481 
5482         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
5483 
5484         // Test that `BoundFooDecl` retains the value we expect, after the join.
5485         BoundFooValue = Env2.getValue(*BoundFooDecl);
5486         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
5487       });
5488 }
5489 
5490 TEST(TransferTest, BinaryOperatorComma) {
5491   std::string Code = R"(
5492     void target(int Foo, int Bar) {
5493       int &Baz = (Foo, Bar);
5494       // [[p]]
5495     }
5496   )";
5497   runDataflow(
5498       Code,
5499       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5500          ASTContext &ASTCtx) {
5501         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5502         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5503 
5504         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5505         ASSERT_THAT(BarDecl, NotNull());
5506 
5507         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5508         ASSERT_THAT(BazDecl, NotNull());
5509 
5510         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
5511         ASSERT_THAT(BarLoc, NotNull());
5512 
5513         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
5514         EXPECT_EQ(BazLoc, BarLoc);
5515       });
5516 }
5517 
5518 TEST(TransferTest, ConditionalOperatorValue) {
5519   std::string Code = R"(
5520     void target(bool Cond, bool B1, bool B2) {
5521       bool JoinSame = Cond ? B1 : B1;
5522       bool JoinDifferent = Cond ? B1 : B2;
5523       // [[p]]
5524     }
5525   )";
5526   runDataflow(
5527       Code,
5528       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5529          ASTContext &ASTCtx) {
5530         Environment Env = getEnvironmentAtAnnotation(Results, "p").fork();
5531 
5532         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "B1");
5533         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "B2");
5534         auto &JoinSame = getValueForDecl<BoolValue>(ASTCtx, Env, "JoinSame");
5535         auto &JoinDifferent =
5536             getValueForDecl<BoolValue>(ASTCtx, Env, "JoinDifferent");
5537 
5538         EXPECT_EQ(&JoinSame, &B1);
5539 
5540         const Formula &JoinDifferentEqB1 =
5541             Env.arena().makeEquals(JoinDifferent.formula(), B1.formula());
5542         EXPECT_TRUE(Env.allows(JoinDifferentEqB1));
5543         EXPECT_FALSE(Env.proves(JoinDifferentEqB1));
5544 
5545         const Formula &JoinDifferentEqB2 =
5546             Env.arena().makeEquals(JoinDifferent.formula(), B2.formula());
5547         EXPECT_TRUE(Env.allows(JoinDifferentEqB2));
5548         EXPECT_FALSE(Env.proves(JoinDifferentEqB1));
5549       });
5550 }
5551 
5552 TEST(TransferTest, ConditionalOperatorLocation) {
5553   std::string Code = R"(
5554     void target(bool Cond, int I1, int I2) {
5555       int &JoinSame = Cond ? I1 : I1;
5556       int &JoinDifferent = Cond ? I1 : I2;
5557       // [[p]]
5558     }
5559   )";
5560   runDataflow(
5561       Code,
5562       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5563          ASTContext &ASTCtx) {
5564         Environment Env = getEnvironmentAtAnnotation(Results, "p").fork();
5565 
5566         StorageLocation &I1 = getLocForDecl(ASTCtx, Env, "I1");
5567         StorageLocation &I2 = getLocForDecl(ASTCtx, Env, "I2");
5568         StorageLocation &JoinSame = getLocForDecl(ASTCtx, Env, "JoinSame");
5569         StorageLocation &JoinDifferent =
5570             getLocForDecl(ASTCtx, Env, "JoinDifferent");
5571 
5572         EXPECT_EQ(&JoinSame, &I1);
5573 
5574         EXPECT_NE(&JoinDifferent, &I1);
5575         EXPECT_NE(&JoinDifferent, &I2);
5576       });
5577 }
5578 
5579 TEST(TransferTest, ConditionalOperatorOnConstantExpr) {
5580   // This is a regression test: We used to crash when a `ConstantExpr` was used
5581   // in the branches of a conditional operator.
5582   std::string Code = R"cc(
5583     consteval bool identity(bool B) { return B; }
5584     void target(bool Cond) {
5585       bool JoinTrueTrue = Cond ? identity(true) : identity(true);
5586       bool JoinTrueFalse = Cond ? identity(true) : identity(false);
5587       // [[p]]
5588     }
5589   )cc";
5590   runDataflow(
5591       Code,
5592       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5593          ASTContext &ASTCtx) {
5594         Environment Env = getEnvironmentAtAnnotation(Results, "p").fork();
5595 
5596         auto &JoinTrueTrue =
5597             getValueForDecl<BoolValue>(ASTCtx, Env, "JoinTrueTrue");
5598         // FIXME: This test documents the current behavior, namely that we
5599         // don't actually use the constant result of the `ConstantExpr` and
5600         // instead treat it like a normal function call.
5601         EXPECT_EQ(JoinTrueTrue.formula().kind(), Formula::Kind::AtomRef);
5602         // EXPECT_TRUE(JoinTrueTrue.formula().literal());
5603 
5604         auto &JoinTrueFalse =
5605             getValueForDecl<BoolValue>(ASTCtx, Env, "JoinTrueFalse");
5606         EXPECT_EQ(JoinTrueFalse.formula().kind(), Formula::Kind::AtomRef);
5607       },
5608       LangStandard::lang_cxx20);
5609 }
5610 
5611 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
5612   std::string Code = R"(
5613     void target(bool Foo) {
5614       if (Foo) {
5615         (void)0;
5616         // [[if_then]]
5617       } else {
5618         (void)0;
5619         // [[if_else]]
5620       }
5621     }
5622   )";
5623   runDataflow(
5624       Code,
5625       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5626          ASTContext &ASTCtx) {
5627         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
5628         const Environment &ThenEnv =
5629             getEnvironmentAtAnnotation(Results, "if_then");
5630         const Environment &ElseEnv =
5631             getEnvironmentAtAnnotation(Results, "if_else");
5632 
5633         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5634         ASSERT_THAT(FooDecl, NotNull());
5635 
5636         auto &ThenFooVal= getFormula(*FooDecl, ThenEnv);
5637         EXPECT_TRUE(ThenEnv.proves(ThenFooVal));
5638 
5639         auto &ElseFooVal = getFormula(*FooDecl, ElseEnv);
5640         EXPECT_TRUE(ElseEnv.proves(ElseEnv.arena().makeNot(ElseFooVal)));
5641       });
5642 }
5643 
5644 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
5645   std::string Code = R"(
5646     void target(bool Foo) {
5647       while (Foo) {
5648         (void)0;
5649         // [[loop_body]]
5650       }
5651       (void)0;
5652       // [[after_loop]]
5653     }
5654   )";
5655   runDataflow(
5656       Code,
5657       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5658          ASTContext &ASTCtx) {
5659         ASSERT_THAT(Results.keys(),
5660                     UnorderedElementsAre("loop_body", "after_loop"));
5661         const Environment &LoopBodyEnv =
5662             getEnvironmentAtAnnotation(Results, "loop_body");
5663         const Environment &AfterLoopEnv =
5664             getEnvironmentAtAnnotation(Results, "after_loop");
5665 
5666         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5667         ASSERT_THAT(FooDecl, NotNull());
5668 
5669         auto &LoopBodyFooVal = getFormula(*FooDecl, LoopBodyEnv);
5670         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
5671 
5672         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5673         EXPECT_TRUE(
5674             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
5675       });
5676 }
5677 
5678 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
5679   std::string Code = R"(
5680     void target(bool Foo) {
5681       bool Bar = true;
5682       do {
5683         (void)0;
5684         // [[loop_body]]
5685         Bar = false;
5686       } while (Foo);
5687       (void)0;
5688       // [[after_loop]]
5689     }
5690   )";
5691   runDataflow(
5692       Code,
5693       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5694          ASTContext &ASTCtx) {
5695         ASSERT_THAT(Results.keys(),
5696                     UnorderedElementsAre("loop_body", "after_loop"));
5697         const Environment &LoopBodyEnv =
5698             getEnvironmentAtAnnotation(Results, "loop_body");
5699         const Environment &AfterLoopEnv =
5700             getEnvironmentAtAnnotation(Results, "after_loop");
5701         auto &A = AfterLoopEnv.arena();
5702 
5703         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5704         ASSERT_THAT(FooDecl, NotNull());
5705 
5706         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5707         ASSERT_THAT(BarDecl, NotNull());
5708 
5709         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5710         auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv);
5711         EXPECT_TRUE(
5712             LoopBodyEnv.proves(A.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
5713 
5714         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5715         auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv);
5716         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopFooVal)));
5717         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopBarVal)));
5718       });
5719 }
5720 
5721 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
5722   std::string Code = R"(
5723     void target(bool Foo) {
5724       for (; Foo;) {
5725         (void)0;
5726         // [[loop_body]]
5727       }
5728       (void)0;
5729       // [[after_loop]]
5730     }
5731   )";
5732   runDataflow(
5733       Code,
5734       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5735          ASTContext &ASTCtx) {
5736         ASSERT_THAT(Results.keys(),
5737                     UnorderedElementsAre("loop_body", "after_loop"));
5738         const Environment &LoopBodyEnv =
5739             getEnvironmentAtAnnotation(Results, "loop_body");
5740         const Environment &AfterLoopEnv =
5741             getEnvironmentAtAnnotation(Results, "after_loop");
5742 
5743         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5744         ASSERT_THAT(FooDecl, NotNull());
5745 
5746         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5747         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
5748 
5749         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5750         EXPECT_TRUE(
5751             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
5752       });
5753 }
5754 
5755 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
5756   std::string Code = R"(
5757     void target(bool Foo) {
5758       for (;;) {
5759         (void)0;
5760         // [[loop_body]]
5761       }
5762     }
5763   )";
5764   runDataflow(
5765       Code,
5766       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5767          ASTContext &ASTCtx) {
5768         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
5769         const Environment &LoopBodyEnv =
5770             getEnvironmentAtAnnotation(Results, "loop_body");
5771 
5772         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5773         ASSERT_THAT(FooDecl, NotNull());
5774 
5775         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5776         EXPECT_FALSE(LoopBodyEnv.proves(LoopBodyFooVal));
5777       });
5778 }
5779 
5780 TEST(TransferTest, ContextSensitiveOptionDisabled) {
5781   std::string Code = R"(
5782     bool GiveBool();
5783     void SetBool(bool &Var) { Var = true; }
5784 
5785     void target() {
5786       bool Foo = GiveBool();
5787       SetBool(Foo);
5788       // [[p]]
5789     }
5790   )";
5791   runDataflow(
5792       Code,
5793       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5794          ASTContext &ASTCtx) {
5795         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5796         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5797 
5798         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5799         ASSERT_THAT(FooDecl, NotNull());
5800 
5801         auto &FooVal = getFormula(*FooDecl, Env);
5802         EXPECT_FALSE(Env.proves(FooVal));
5803         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5804       },
5805       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
5806 }
5807 
5808 TEST(TransferTest, ContextSensitiveReturnReference) {
5809   std::string Code = R"(
5810     class S {};
5811     S& target(bool b, S &s) {
5812       return s;
5813       // [[p]]
5814     }
5815   )";
5816   runDataflow(
5817       Code,
5818       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5819          ASTContext &ASTCtx) {
5820         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5821 
5822         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5823         ASSERT_THAT(SDecl, NotNull());
5824 
5825         auto *SLoc = Env.getStorageLocation(*SDecl);
5826         ASSERT_THAT(SLoc, NotNull());
5827 
5828         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
5829       },
5830       {BuiltinOptions{ContextSensitiveOptions{}}});
5831 }
5832 
5833 // This test is a regression test, based on a real crash.
5834 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
5835   std::string Code = R"(
5836     class S {};
5837     S& target(bool b, S &s) {
5838       return b ? s : s;
5839       // [[p]]
5840     }
5841   )";
5842   runDataflow(
5843       Code,
5844       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5845          ASTContext &ASTCtx) {
5846         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5847         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5848 
5849         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5850         ASSERT_THAT(SDecl, NotNull());
5851 
5852         auto *SLoc = Env.getStorageLocation(*SDecl);
5853         EXPECT_THAT(SLoc, NotNull());
5854 
5855         auto *Loc = Env.getReturnStorageLocation();
5856         EXPECT_THAT(Loc, NotNull());
5857 
5858         EXPECT_EQ(Loc, SLoc);
5859       },
5860       {BuiltinOptions{ContextSensitiveOptions{}}});
5861 }
5862 
5863 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
5864   std::string Code = R"(
5865     class S {};
5866     S &callee(bool b, S &s1_parm, S &s2_parm) {
5867       if (b)
5868         return s1_parm;
5869       else
5870         return s2_parm;
5871     }
5872     void target(bool b) {
5873       S s1;
5874       S s2;
5875       S &return_s1 = s1;
5876       S &return_s2 = s2;
5877       S &return_dont_know = callee(b, s1, s2);
5878       // [[p]]
5879     }
5880   )";
5881   runDataflow(
5882       Code,
5883       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5884          ASTContext &ASTCtx) {
5885         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5886 
5887         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
5888         ASSERT_THAT(S1, NotNull());
5889         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
5890         ASSERT_THAT(S2, NotNull());
5891         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
5892         ASSERT_THAT(ReturnS1, NotNull());
5893         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
5894         ASSERT_THAT(ReturnS2, NotNull());
5895         const ValueDecl *ReturnDontKnow =
5896             findValueDecl(ASTCtx, "return_dont_know");
5897         ASSERT_THAT(ReturnDontKnow, NotNull());
5898 
5899         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
5900         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
5901 
5902         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
5903         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
5904 
5905         // In the case where we don't have a consistent storage location for
5906         // the return value, the framework creates a new storage location, which
5907         // should be different from the storage locations of `s1` and `s2`.
5908         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
5909         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
5910       },
5911       {BuiltinOptions{ContextSensitiveOptions{}}});
5912 }
5913 
5914 TEST(TransferTest, ContextSensitiveDepthZero) {
5915   std::string Code = R"(
5916     bool GiveBool();
5917     void SetBool(bool &Var) { Var = true; }
5918 
5919     void target() {
5920       bool Foo = GiveBool();
5921       SetBool(Foo);
5922       // [[p]]
5923     }
5924   )";
5925   runDataflow(
5926       Code,
5927       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5928          ASTContext &ASTCtx) {
5929         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5930         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5931 
5932         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5933         ASSERT_THAT(FooDecl, NotNull());
5934 
5935         auto &FooVal = getFormula(*FooDecl, Env);
5936         EXPECT_FALSE(Env.proves(FooVal));
5937         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5938       },
5939       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
5940 }
5941 
5942 TEST(TransferTest, ContextSensitiveSetTrue) {
5943   std::string Code = R"(
5944     bool GiveBool();
5945     void SetBool(bool &Var) { Var = true; }
5946 
5947     void target() {
5948       bool Foo = GiveBool();
5949       SetBool(Foo);
5950       // [[p]]
5951     }
5952   )";
5953   runDataflow(
5954       Code,
5955       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5956          ASTContext &ASTCtx) {
5957         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5958         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5959 
5960         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5961         ASSERT_THAT(FooDecl, NotNull());
5962 
5963         auto &FooVal = getFormula(*FooDecl, Env);
5964         EXPECT_TRUE(Env.proves(FooVal));
5965       },
5966       {BuiltinOptions{ContextSensitiveOptions{}}});
5967 }
5968 
5969 TEST(TransferTest, ContextSensitiveSetFalse) {
5970   std::string Code = R"(
5971     bool GiveBool();
5972     void SetBool(bool &Var) { Var = false; }
5973 
5974     void target() {
5975       bool Foo = GiveBool();
5976       SetBool(Foo);
5977       // [[p]]
5978     }
5979   )";
5980   runDataflow(
5981       Code,
5982       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5983          ASTContext &ASTCtx) {
5984         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5985         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5986 
5987         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5988         ASSERT_THAT(FooDecl, NotNull());
5989 
5990         auto &FooVal = getFormula(*FooDecl, Env);
5991         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
5992       },
5993       {BuiltinOptions{ContextSensitiveOptions{}}});
5994 }
5995 
5996 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
5997   std::string Code = R"(
5998     bool GiveBool();
5999     void SetBool(bool &Var, bool Val) { Var = Val; }
6000 
6001     void target() {
6002       bool Foo = GiveBool();
6003       bool Bar = GiveBool();
6004       SetBool(Foo, true);
6005       SetBool(Bar, false);
6006       // [[p]]
6007     }
6008   )";
6009   runDataflow(
6010       Code,
6011       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6012          ASTContext &ASTCtx) {
6013         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6014         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6015         auto &A = Env.arena();
6016 
6017         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6018         ASSERT_THAT(FooDecl, NotNull());
6019 
6020         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6021         ASSERT_THAT(BarDecl, NotNull());
6022 
6023         auto &FooVal = getFormula(*FooDecl, Env);
6024         EXPECT_TRUE(Env.proves(FooVal));
6025         EXPECT_FALSE(Env.proves(A.makeNot(FooVal)));
6026 
6027         auto &BarVal = getFormula(*BarDecl, Env);
6028         EXPECT_FALSE(Env.proves(BarVal));
6029         EXPECT_TRUE(Env.proves(A.makeNot(BarVal)));
6030       },
6031       {BuiltinOptions{ContextSensitiveOptions{}}});
6032 }
6033 
6034 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
6035   std::string Code = R"(
6036     bool GiveBool();
6037     void SetBool1(bool &Var) { Var = true; }
6038     void SetBool2(bool &Var) { SetBool1(Var); }
6039 
6040     void target() {
6041       bool Foo = GiveBool();
6042       SetBool2(Foo);
6043       // [[p]]
6044     }
6045   )";
6046   runDataflow(
6047       Code,
6048       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6049          ASTContext &ASTCtx) {
6050         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6051         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6052 
6053         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6054         ASSERT_THAT(FooDecl, NotNull());
6055 
6056         auto &FooVal = getFormula(*FooDecl, Env);
6057         EXPECT_FALSE(Env.proves(FooVal));
6058         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
6059       },
6060       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
6061 }
6062 
6063 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
6064   std::string Code = R"(
6065     bool GiveBool();
6066     void SetBool1(bool &Var) { Var = true; }
6067     void SetBool2(bool &Var) { SetBool1(Var); }
6068 
6069     void target() {
6070       bool Foo = GiveBool();
6071       SetBool2(Foo);
6072       // [[p]]
6073     }
6074   )";
6075   runDataflow(
6076       Code,
6077       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6078          ASTContext &ASTCtx) {
6079         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6080         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6081 
6082         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6083         ASSERT_THAT(FooDecl, NotNull());
6084 
6085         auto &FooVal = getFormula(*FooDecl, Env);
6086         EXPECT_TRUE(Env.proves(FooVal));
6087       },
6088       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
6089 }
6090 
6091 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
6092   std::string Code = R"(
6093     bool GiveBool();
6094     void SetBool1(bool &Var) { Var = true; }
6095     void SetBool2(bool &Var) { SetBool1(Var); }
6096     void SetBool3(bool &Var) { SetBool2(Var); }
6097 
6098     void target() {
6099       bool Foo = GiveBool();
6100       SetBool3(Foo);
6101       // [[p]]
6102     }
6103   )";
6104   runDataflow(
6105       Code,
6106       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6107          ASTContext &ASTCtx) {
6108         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6109         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6110 
6111         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6112         ASSERT_THAT(FooDecl, NotNull());
6113 
6114         auto &FooVal = getFormula(*FooDecl, Env);
6115         EXPECT_FALSE(Env.proves(FooVal));
6116         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
6117       },
6118       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
6119 }
6120 
6121 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
6122   std::string Code = R"(
6123     bool GiveBool();
6124     void SetBool1(bool &Var) { Var = true; }
6125     void SetBool2(bool &Var) { SetBool1(Var); }
6126     void SetBool3(bool &Var) { SetBool2(Var); }
6127 
6128     void target() {
6129       bool Foo = GiveBool();
6130       SetBool3(Foo);
6131       // [[p]]
6132     }
6133   )";
6134   runDataflow(
6135       Code,
6136       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6137          ASTContext &ASTCtx) {
6138         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6139         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6140 
6141         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6142         ASSERT_THAT(FooDecl, NotNull());
6143 
6144         auto &FooVal = getFormula(*FooDecl, Env);
6145         EXPECT_TRUE(Env.proves(FooVal));
6146       },
6147       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
6148 }
6149 
6150 TEST(TransferTest, ContextSensitiveMutualRecursion) {
6151   std::string Code = R"(
6152     bool Pong(bool X, bool Y);
6153 
6154     bool Ping(bool X, bool Y) {
6155       if (X) {
6156         return Y;
6157       } else {
6158         return Pong(!X, Y);
6159       }
6160     }
6161 
6162     bool Pong(bool X, bool Y) {
6163       if (Y) {
6164         return X;
6165       } else {
6166         return Ping(X, !Y);
6167       }
6168     }
6169 
6170     void target() {
6171       bool Foo = Ping(false, false);
6172       // [[p]]
6173     }
6174   )";
6175   runDataflow(
6176       Code,
6177       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6178          ASTContext &ASTCtx) {
6179         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6180         // The analysis doesn't crash...
6181         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6182 
6183         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6184         ASSERT_THAT(FooDecl, NotNull());
6185 
6186         auto &FooVal = getFormula(*FooDecl, Env);
6187         // ... but it also can't prove anything here.
6188         EXPECT_FALSE(Env.proves(FooVal));
6189         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
6190       },
6191       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
6192 }
6193 
6194 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
6195   std::string Code = R"(
6196     void SetBools(bool &Var1, bool &Var2) {
6197       Var1 = true;
6198       Var2 = false;
6199     }
6200 
6201     void target() {
6202       bool Foo = false;
6203       bool Bar = true;
6204       SetBools(Foo, Bar);
6205       // [[p]]
6206     }
6207   )";
6208   runDataflow(
6209       Code,
6210       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6211          ASTContext &ASTCtx) {
6212         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6213         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6214 
6215         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6216         ASSERT_THAT(FooDecl, NotNull());
6217 
6218         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6219         ASSERT_THAT(BarDecl, NotNull());
6220 
6221         auto &FooVal = getFormula(*FooDecl, Env);
6222         EXPECT_TRUE(Env.proves(FooVal));
6223         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
6224 
6225         auto &BarVal = getFormula(*BarDecl, Env);
6226         EXPECT_FALSE(Env.proves(BarVal));
6227         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
6228       },
6229       {BuiltinOptions{ContextSensitiveOptions{}}});
6230 }
6231 
6232 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
6233   std::string Code = R"(
6234     void IfCond(bool Cond, bool &Then, bool &Else) {
6235       if (Cond) {
6236         Then = true;
6237       } else {
6238         Else = true;
6239       }
6240     }
6241 
6242     void target() {
6243       bool Foo = false;
6244       bool Bar = false;
6245       bool Baz = false;
6246       IfCond(Foo, Bar, Baz);
6247       // [[p]]
6248     }
6249   )";
6250   runDataflow(
6251       Code,
6252       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6253          ASTContext &ASTCtx) {
6254         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6255         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6256 
6257         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6258         ASSERT_THAT(BarDecl, NotNull());
6259 
6260         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
6261         ASSERT_THAT(BazDecl, NotNull());
6262 
6263         auto &BarVal = getFormula(*BarDecl, Env);
6264         EXPECT_FALSE(Env.proves(BarVal));
6265         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
6266 
6267         auto &BazVal = getFormula(*BazDecl, Env);
6268         EXPECT_TRUE(Env.proves(BazVal));
6269         EXPECT_FALSE(Env.proves(Env.arena().makeNot(BazVal)));
6270       },
6271       {BuiltinOptions{ContextSensitiveOptions{}}});
6272 }
6273 
6274 TEST(TransferTest, ContextSensitiveReturnVoid) {
6275   std::string Code = R"(
6276     void Noop() { return; }
6277 
6278     void target() {
6279       Noop();
6280       // [[p]]
6281     }
6282   )";
6283   runDataflow(
6284       Code,
6285       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6286          ASTContext &ASTCtx) {
6287         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6288         // This just tests that the analysis doesn't crash.
6289       },
6290       {BuiltinOptions{ContextSensitiveOptions{}}});
6291 }
6292 
6293 TEST(TransferTest, ContextSensitiveReturnTrue) {
6294   std::string Code = R"(
6295     bool GiveBool() { return true; }
6296 
6297     void target() {
6298       bool Foo = GiveBool();
6299       // [[p]]
6300     }
6301   )";
6302   runDataflow(
6303       Code,
6304       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6305          ASTContext &ASTCtx) {
6306         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6307         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6308 
6309         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6310         ASSERT_THAT(FooDecl, NotNull());
6311 
6312         auto &FooVal = getFormula(*FooDecl, Env);
6313         EXPECT_TRUE(Env.proves(FooVal));
6314       },
6315       {BuiltinOptions{ContextSensitiveOptions{}}});
6316 }
6317 
6318 TEST(TransferTest, ContextSensitiveReturnFalse) {
6319   std::string Code = R"(
6320     bool GiveBool() { return false; }
6321 
6322     void target() {
6323       bool Foo = GiveBool();
6324       // [[p]]
6325     }
6326   )";
6327   runDataflow(
6328       Code,
6329       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6330          ASTContext &ASTCtx) {
6331         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6332         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6333 
6334         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6335         ASSERT_THAT(FooDecl, NotNull());
6336 
6337         auto &FooVal = getFormula(*FooDecl, Env);
6338         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
6339       },
6340       {BuiltinOptions{ContextSensitiveOptions{}}});
6341 }
6342 
6343 TEST(TransferTest, ContextSensitiveReturnArg) {
6344   std::string Code = R"(
6345     bool GiveBool();
6346     bool GiveBack(bool Arg) { return Arg; }
6347 
6348     void target() {
6349       bool Foo = GiveBool();
6350       bool Bar = GiveBack(Foo);
6351       bool Baz = Foo == Bar;
6352       // [[p]]
6353     }
6354   )";
6355   runDataflow(
6356       Code,
6357       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6358          ASTContext &ASTCtx) {
6359         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6360         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6361 
6362         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
6363         ASSERT_THAT(BazDecl, NotNull());
6364 
6365         auto &BazVal = getFormula(*BazDecl, Env);
6366         EXPECT_TRUE(Env.proves(BazVal));
6367       },
6368       {BuiltinOptions{ContextSensitiveOptions{}}});
6369 }
6370 
6371 TEST(TransferTest, ContextSensitiveReturnInt) {
6372   std::string Code = R"(
6373     int identity(int x) { return x; }
6374 
6375     void target() {
6376       int y = identity(42);
6377       // [[p]]
6378     }
6379   )";
6380   runDataflow(
6381       Code,
6382       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6383          ASTContext &ASTCtx) {
6384         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6385         // This just tests that the analysis doesn't crash.
6386       },
6387       {BuiltinOptions{ContextSensitiveOptions{}}});
6388 }
6389 
6390 TEST(TransferTest, ContextSensitiveReturnRecord) {
6391   std::string Code = R"(
6392     struct S {
6393       bool B;
6394     };
6395 
6396     S makeS(bool BVal) { return {BVal}; }
6397 
6398     void target() {
6399       S FalseS = makeS(false);
6400       S TrueS = makeS(true);
6401       // [[p]]
6402     }
6403   )";
6404   runDataflow(
6405       Code,
6406       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6407          ASTContext &ASTCtx) {
6408         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6409 
6410         auto &FalseSLoc =
6411             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "FalseS");
6412         auto &TrueSLoc =
6413             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "TrueS");
6414 
6415         EXPECT_EQ(getFieldValue(&FalseSLoc, "B", ASTCtx, Env),
6416                   &Env.getBoolLiteralValue(false));
6417         EXPECT_EQ(getFieldValue(&TrueSLoc, "B", ASTCtx, Env),
6418                   &Env.getBoolLiteralValue(true));
6419       },
6420       {BuiltinOptions{ContextSensitiveOptions{}}});
6421 }
6422 
6423 TEST(TransferTest, ContextSensitiveReturnSelfReferentialRecord) {
6424   std::string Code = R"(
6425     struct S {
6426       S() { self = this; }
6427       S *self;
6428     };
6429 
6430     S makeS() {
6431       // RVO guarantees that this will be constructed directly into `MyS`.
6432       return S();
6433     }
6434 
6435     void target() {
6436       S MyS = makeS();
6437       // [[p]]
6438     }
6439   )";
6440   runDataflow(
6441       Code,
6442       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6443          ASTContext &ASTCtx) {
6444         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6445 
6446         auto &MySLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MyS");
6447 
6448         auto *SelfVal =
6449             cast<PointerValue>(getFieldValue(&MySLoc, "self", ASTCtx, Env));
6450         EXPECT_EQ(&SelfVal->getPointeeLoc(), &MySLoc);
6451       },
6452       {BuiltinOptions{ContextSensitiveOptions{}}});
6453 }
6454 
6455 TEST(TransferTest, ContextSensitiveMethodLiteral) {
6456   std::string Code = R"(
6457     class MyClass {
6458     public:
6459       bool giveBool() { return true; }
6460     };
6461 
6462     void target() {
6463       MyClass MyObj;
6464       bool Foo = MyObj.giveBool();
6465       // [[p]]
6466     }
6467   )";
6468   runDataflow(
6469       Code,
6470       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6471          ASTContext &ASTCtx) {
6472         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6473         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6474 
6475         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6476         ASSERT_THAT(FooDecl, NotNull());
6477 
6478         auto &FooVal = getFormula(*FooDecl, Env);
6479         EXPECT_TRUE(Env.proves(FooVal));
6480       },
6481       {BuiltinOptions{ContextSensitiveOptions{}}});
6482 }
6483 
6484 TEST(TransferTest, ContextSensitiveMethodGetter) {
6485   std::string Code = R"(
6486     class MyClass {
6487     public:
6488       bool getField() { return Field; }
6489 
6490       bool Field;
6491     };
6492 
6493     void target() {
6494       MyClass MyObj;
6495       MyObj.Field = true;
6496       bool Foo = MyObj.getField();
6497       // [[p]]
6498     }
6499   )";
6500   runDataflow(
6501       Code,
6502       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6503          ASTContext &ASTCtx) {
6504         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6505         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6506 
6507         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6508         ASSERT_THAT(FooDecl, NotNull());
6509 
6510         auto &FooVal = getFormula(*FooDecl, Env);
6511         EXPECT_TRUE(Env.proves(FooVal));
6512       },
6513       {BuiltinOptions{ContextSensitiveOptions{}}});
6514 }
6515 
6516 TEST(TransferTest, ContextSensitiveMethodSetter) {
6517   std::string Code = R"(
6518     class MyClass {
6519     public:
6520       void setField(bool Val) { Field = Val; }
6521 
6522       bool Field;
6523     };
6524 
6525     void target() {
6526       MyClass MyObj;
6527       MyObj.setField(true);
6528       bool Foo = MyObj.Field;
6529       // [[p]]
6530     }
6531   )";
6532   runDataflow(
6533       Code,
6534       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6535          ASTContext &ASTCtx) {
6536         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6537         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6538 
6539         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6540         ASSERT_THAT(FooDecl, NotNull());
6541 
6542         auto &FooVal = getFormula(*FooDecl, Env);
6543         EXPECT_TRUE(Env.proves(FooVal));
6544       },
6545       {BuiltinOptions{ContextSensitiveOptions{}}});
6546 }
6547 
6548 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
6549   std::string Code = R"(
6550     class MyClass {
6551     public:
6552       bool getField() { return Field; }
6553       void setField(bool Val) { Field = Val; }
6554 
6555     private:
6556       bool Field;
6557     };
6558 
6559     void target() {
6560       MyClass MyObj;
6561       MyObj.setField(true);
6562       bool Foo = MyObj.getField();
6563       // [[p]]
6564     }
6565   )";
6566   runDataflow(
6567       Code,
6568       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6569          ASTContext &ASTCtx) {
6570         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6571         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6572 
6573         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6574         ASSERT_THAT(FooDecl, NotNull());
6575 
6576         auto &FooVal = getFormula(*FooDecl, Env);
6577         EXPECT_TRUE(Env.proves(FooVal));
6578       },
6579       {BuiltinOptions{ContextSensitiveOptions{}}});
6580 }
6581 
6582 
6583 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
6584   std::string Code = R"(
6585     class MyClass {
6586     public:
6587       void Inner() { MyField = true; }
6588       void Outer() { Inner(); }
6589 
6590       bool MyField;
6591     };
6592 
6593     void target() {
6594       MyClass MyObj;
6595       MyObj.Outer();
6596       bool Foo = MyObj.MyField;
6597       // [[p]]
6598     }
6599   )";
6600   runDataflow(
6601       Code,
6602       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6603          ASTContext &ASTCtx) {
6604         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6605         ;
6606         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6607 
6608         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6609         ASSERT_THAT(FooDecl, NotNull());
6610 
6611         auto &FooVal = getFormula(*FooDecl, Env);
6612         EXPECT_TRUE(Env.proves(FooVal));
6613       },
6614       {BuiltinOptions{ContextSensitiveOptions{}}});
6615 }
6616 
6617 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
6618   std::string Code = R"(
6619     class MyClass {
6620     public:
6621       bool Inner() { return MyField; }
6622       bool Outer() { return Inner(); }
6623 
6624       bool MyField;
6625     };
6626 
6627     void target() {
6628       MyClass MyObj;
6629       MyObj.MyField = true;
6630       bool Foo = MyObj.Outer();
6631       // [[p]]
6632     }
6633   )";
6634   runDataflow(
6635       Code,
6636       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6637          ASTContext &ASTCtx) {
6638         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6639         ;
6640         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6641 
6642         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6643         ASSERT_THAT(FooDecl, NotNull());
6644 
6645         auto &FooVal = getFormula(*FooDecl, Env);
6646         EXPECT_TRUE(Env.proves(FooVal));
6647       },
6648       {BuiltinOptions{ContextSensitiveOptions{}}});
6649 }
6650 
6651 TEST(TransferTest, ContextSensitiveConstructorBody) {
6652   std::string Code = R"(
6653     class MyClass {
6654     public:
6655       MyClass() { MyField = true; }
6656 
6657       bool MyField;
6658     };
6659 
6660     void target() {
6661       MyClass MyObj;
6662       bool Foo = MyObj.MyField;
6663       // [[p]]
6664     }
6665   )";
6666   runDataflow(
6667       Code,
6668       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6669          ASTContext &ASTCtx) {
6670         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6671         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6672 
6673         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6674         ASSERT_THAT(FooDecl, NotNull());
6675 
6676         auto &FooVal = getFormula(*FooDecl, Env);
6677         EXPECT_TRUE(Env.proves(FooVal));
6678       },
6679       {BuiltinOptions{ContextSensitiveOptions{}}});
6680 }
6681 
6682 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
6683   std::string Code = R"(
6684     class MyClass {
6685     public:
6686       MyClass() : MyField(true) {}
6687 
6688       bool MyField;
6689     };
6690 
6691     void target() {
6692       MyClass MyObj;
6693       bool Foo = MyObj.MyField;
6694       // [[p]]
6695     }
6696   )";
6697   runDataflow(
6698       Code,
6699       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6700          ASTContext &ASTCtx) {
6701         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6702         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6703 
6704         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6705         ASSERT_THAT(FooDecl, NotNull());
6706 
6707         auto &FooVal = getFormula(*FooDecl, Env);
6708         EXPECT_TRUE(Env.proves(FooVal));
6709       },
6710       {BuiltinOptions{ContextSensitiveOptions{}}});
6711 }
6712 
6713 TEST(TransferTest, ContextSensitiveConstructorDefault) {
6714   std::string Code = R"(
6715     class MyClass {
6716     public:
6717       MyClass() = default;
6718 
6719       bool MyField = true;
6720     };
6721 
6722     void target() {
6723       MyClass MyObj;
6724       bool Foo = MyObj.MyField;
6725       // [[p]]
6726     }
6727   )";
6728   runDataflow(
6729       Code,
6730       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6731          ASTContext &ASTCtx) {
6732         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6733         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6734 
6735         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6736         ASSERT_THAT(FooDecl, NotNull());
6737 
6738         auto &FooVal = getFormula(*FooDecl, Env);
6739         EXPECT_TRUE(Env.proves(FooVal));
6740       },
6741       {BuiltinOptions{ContextSensitiveOptions{}}});
6742 }
6743 
6744 TEST(TransferTest, ContextSensitiveSelfReferentialClass) {
6745   // Test that the `this` pointer seen in the constructor has the same value
6746   // as the address of the variable the object is constructed into.
6747   std::string Code = R"(
6748     class MyClass {
6749     public:
6750       MyClass() : Self(this) {}
6751       MyClass *Self;
6752     };
6753 
6754     void target() {
6755       MyClass MyObj;
6756       MyClass *SelfPtr = MyObj.Self;
6757       // [[p]]
6758     }
6759   )";
6760   runDataflow(
6761       Code,
6762       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6763          ASTContext &ASTCtx) {
6764         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6765 
6766         const ValueDecl *MyObjDecl = findValueDecl(ASTCtx, "MyObj");
6767         ASSERT_THAT(MyObjDecl, NotNull());
6768 
6769         const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "SelfPtr");
6770         ASSERT_THAT(SelfDecl, NotNull());
6771 
6772         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6773         auto &SelfVal = *cast<PointerValue>(Env.getValue(*SelfDecl));
6774         EXPECT_EQ(Env.getStorageLocation(*MyObjDecl), &SelfVal.getPointeeLoc());
6775       },
6776       {BuiltinOptions{ContextSensitiveOptions{}}});
6777 }
6778 
6779 TEST(TransferTest, UnnamedBitfieldInitializer) {
6780   std::string Code = R"(
6781     struct B {};
6782     struct A {
6783       unsigned a;
6784       unsigned : 4;
6785       unsigned c;
6786       B b;
6787     };
6788     void target() {
6789       A a = {};
6790       A test = a;
6791       (void)test.c;
6792     }
6793   )";
6794   runDataflow(
6795       Code,
6796       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6797          ASTContext &ASTCtx) {
6798         // This doesn't need a body because this test was crashing the framework
6799         // before handling correctly Unnamed bitfields in `InitListExpr`.
6800       });
6801 }
6802 
6803 // Repro for a crash that used to occur with chained short-circuiting logical
6804 // operators.
6805 TEST(TransferTest, ChainedLogicalOps) {
6806   std::string Code = R"(
6807     bool target() {
6808       bool b = true || false || false || false;
6809       // [[p]]
6810       return b;
6811     }
6812   )";
6813   runDataflow(
6814       Code,
6815       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6816          ASTContext &ASTCtx) {
6817         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6818         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
6819         EXPECT_TRUE(Env.proves(B));
6820       });
6821 }
6822 
6823 // Repro for a crash that used to occur when we call a `noreturn` function
6824 // within one of the operands of a `&&` or `||` operator.
6825 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
6826   std::string Code = R"(
6827     __attribute__((noreturn)) int doesnt_return();
6828     bool some_condition();
6829     void target(bool b1, bool b2) {
6830       // Neither of these should crash. In addition, if we don't terminate the
6831       // program, we know that the operators need to trigger the short-circuit
6832       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
6833       // will be true.
6834       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
6835       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
6836 
6837       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
6838       // entire expression unreachable. So we know that in both of the following
6839       // cases, if `target()` terminates, the `else` branch was taken.
6840       bool NoreturnOnLhsMakesAndUnreachable = false;
6841       if (some_condition())
6842          doesnt_return() > 0 && some_condition();
6843       else
6844          NoreturnOnLhsMakesAndUnreachable = true;
6845 
6846       bool NoreturnOnLhsMakesOrUnreachable = false;
6847       if (some_condition())
6848          doesnt_return() > 0 || some_condition();
6849       else
6850          NoreturnOnLhsMakesOrUnreachable = true;
6851 
6852       // [[p]]
6853     }
6854   )";
6855   runDataflow(
6856       Code,
6857       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6858          ASTContext &ASTCtx) {
6859         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6860         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6861         auto &A = Env.arena();
6862 
6863         // Check that [[p]] is reachable with a non-false flow condition.
6864         EXPECT_FALSE(Env.proves(A.makeLiteral(false)));
6865 
6866         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula();
6867         EXPECT_TRUE(Env.proves(A.makeNot(B1)));
6868 
6869         auto &NoreturnOnRhsOfAnd =
6870             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula();
6871         EXPECT_TRUE(Env.proves(A.makeNot(NoreturnOnRhsOfAnd)));
6872 
6873         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula();
6874         EXPECT_TRUE(Env.proves(B2));
6875 
6876         auto &NoreturnOnRhsOfOr =
6877             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr")
6878                 .formula();
6879         EXPECT_TRUE(Env.proves(NoreturnOnRhsOfOr));
6880 
6881         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
6882             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula();
6883         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesAndUnreachable));
6884 
6885         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
6886             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula();
6887         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesOrUnreachable));
6888       });
6889 }
6890 
6891 TEST(TransferTest, NewExpressions) {
6892   std::string Code = R"(
6893     void target() {
6894       int *p = new int(42);
6895       // [[after_new]]
6896     }
6897   )";
6898   runDataflow(
6899       Code,
6900       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6901          ASTContext &ASTCtx) {
6902         const Environment &Env =
6903             getEnvironmentAtAnnotation(Results, "after_new");
6904 
6905         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
6906 
6907         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
6908       });
6909 }
6910 
6911 TEST(TransferTest, NewExpressions_Structs) {
6912   std::string Code = R"(
6913     struct Inner {
6914       int InnerField;
6915     };
6916 
6917     struct Outer {
6918       Inner OuterField;
6919     };
6920 
6921     void target() {
6922       Outer *p = new Outer;
6923       // Access the fields to make sure the analysis actually generates children
6924       // for them in the `RecordStorageLocation`.
6925       p->OuterField.InnerField;
6926       // [[after_new]]
6927     }
6928   )";
6929   runDataflow(
6930       Code,
6931       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6932          ASTContext &ASTCtx) {
6933         const Environment &Env =
6934             getEnvironmentAtAnnotation(Results, "after_new");
6935 
6936         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
6937         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
6938 
6939         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
6940 
6941         auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
6942         auto &OuterFieldLoc =
6943             *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
6944         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
6945 
6946         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
6947       });
6948 }
6949 
6950 TEST(TransferTest, FunctionToPointerDecayHasValue) {
6951   std::string Code = R"(
6952     struct A { static void static_member_func(); };
6953     void target() {
6954       // To check that we're treating function-to-pointer decay correctly,
6955       // create two pointers, then verify they refer to the same storage
6956       // location.
6957       // We need to do the test this way because even if an initializer (in this
6958       // case, the function-to-pointer decay) does not create a value, we still
6959       // create a value for the variable.
6960       void (*non_member_p1)() = target;
6961       void (*non_member_p2)() = target;
6962 
6963       // Do the same thing but for a static member function.
6964       void (*member_p1)() = A::static_member_func;
6965       void (*member_p2)() = A::static_member_func;
6966       // [[p]]
6967     }
6968   )";
6969   runDataflow(
6970       Code,
6971       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6972          ASTContext &ASTCtx) {
6973         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6974 
6975         auto &NonMemberP1 =
6976             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
6977         auto &NonMemberP2 =
6978             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
6979         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
6980 
6981         auto &MemberP1 =
6982             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
6983         auto &MemberP2 =
6984             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
6985         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
6986       });
6987 }
6988 
6989 // Check that a builtin function is not associated with a value. (It's only
6990 // possible to call builtin functions directly, not take their address.)
6991 TEST(TransferTest, BuiltinFunctionModeled) {
6992   std::string Code = R"(
6993     void target() {
6994       __builtin_expect(0, 0);
6995       // [[p]]
6996     }
6997   )";
6998   runDataflow(
6999       Code,
7000       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7001          ASTContext &ASTCtx) {
7002         using ast_matchers::selectFirst;
7003         using ast_matchers::match;
7004         using ast_matchers::traverse;
7005         using ast_matchers::implicitCastExpr;
7006         using ast_matchers::hasCastKind;
7007 
7008         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7009 
7010         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
7011             "implicit_cast",
7012             match(traverse(TK_AsIs,
7013                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
7014                                .bind("implicit_cast")),
7015                   ASTCtx));
7016 
7017         ASSERT_THAT(ImplicitCast, NotNull());
7018         EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull());
7019       });
7020 }
7021 
7022 // Check that a callee of a member operator call is modeled as a `PointerValue`.
7023 // Member operator calls are unusual in that their callee is a pointer that
7024 // stems from a `FunctionToPointerDecay`. In calls to non-operator non-static
7025 // member functions, the callee is a `MemberExpr` (which does not have pointer
7026 // type).
7027 // We want to make sure that we produce a pointer value for the callee in this
7028 // specific scenario and that its storage location is durable (for convergence).
7029 TEST(TransferTest, MemberOperatorCallModelsPointerForCallee) {
7030   std::string Code = R"(
7031     struct S {
7032       bool operator!=(S s);
7033     };
7034     void target() {
7035       S s;
7036       (void)(s != s);
7037       (void)(s != s);
7038       // [[p]]
7039     }
7040   )";
7041   runDataflow(
7042       Code,
7043       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7044          ASTContext &ASTCtx) {
7045         using ast_matchers::selectFirst;
7046         using ast_matchers::match;
7047         using ast_matchers::traverse;
7048         using ast_matchers::cxxOperatorCallExpr;
7049 
7050         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7051 
7052         auto Matches = match(
7053             traverse(TK_AsIs, cxxOperatorCallExpr().bind("call")), ASTCtx);
7054 
7055         ASSERT_EQ(Matches.size(), 2UL);
7056 
7057         auto *Call1 = Matches[0].getNodeAs<CXXOperatorCallExpr>("call");
7058         auto *Call2 = Matches[1].getNodeAs<CXXOperatorCallExpr>("call");
7059 
7060         ASSERT_THAT(Call1, NotNull());
7061         ASSERT_THAT(Call2, NotNull());
7062 
7063         EXPECT_EQ(cast<ImplicitCastExpr>(Call1->getCallee())->getCastKind(),
7064                   CK_FunctionToPointerDecay);
7065         EXPECT_EQ(cast<ImplicitCastExpr>(Call2->getCallee())->getCastKind(),
7066                   CK_FunctionToPointerDecay);
7067 
7068         auto *Ptr1 = cast<PointerValue>(Env.getValue(*Call1->getCallee()));
7069         auto *Ptr2 = cast<PointerValue>(Env.getValue(*Call2->getCallee()));
7070 
7071         ASSERT_EQ(&Ptr1->getPointeeLoc(), &Ptr2->getPointeeLoc());
7072       });
7073 }
7074 
7075 // Check that fields of anonymous records are modeled.
7076 TEST(TransferTest, AnonymousStruct) {
7077   std::string Code = R"(
7078     struct S {
7079       struct {
7080         bool b;
7081       };
7082     };
7083     void target() {
7084       S s;
7085       s.b = true;
7086       // [[p]]
7087     }
7088   )";
7089   runDataflow(
7090       Code,
7091       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7092          ASTContext &ASTCtx) {
7093         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7094         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
7095         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
7096         const IndirectFieldDecl *IndirectField =
7097             findIndirectFieldDecl(ASTCtx, "b");
7098 
7099         auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl));
7100         auto &AnonStruct = *cast<RecordStorageLocation>(
7101             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
7102 
7103         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
7104         ASSERT_TRUE(Env.proves(B->formula()));
7105       });
7106 }
7107 
7108 TEST(TransferTest, AnonymousStructWithInitializer) {
7109   std::string Code = R"(
7110     struct target {
7111       target() {
7112         (void)0;
7113         // [[p]]
7114       }
7115       struct {
7116         bool b = true;
7117       };
7118     };
7119   )";
7120   runDataflow(
7121       Code,
7122       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7123          ASTContext &ASTCtx) {
7124         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7125         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
7126         const IndirectFieldDecl *IndirectField =
7127             findIndirectFieldDecl(ASTCtx, "b");
7128 
7129         auto *ThisLoc =
7130             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
7131         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
7132             *cast<ValueDecl>(IndirectField->chain().front())));
7133 
7134         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
7135         ASSERT_TRUE(Env.proves(B->formula()));
7136       });
7137 }
7138 
7139 TEST(TransferTest, AnonymousStructWithReferenceField) {
7140   std::string Code = R"(
7141     int global_i = 0;
7142     struct target {
7143       target() {
7144         (void)0;
7145         // [[p]]
7146       }
7147       struct {
7148         int &i = global_i;
7149       };
7150     };
7151   )";
7152   runDataflow(
7153       Code,
7154       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7155          ASTContext &ASTCtx) {
7156         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7157         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
7158         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
7159         const IndirectFieldDecl *IndirectField =
7160             findIndirectFieldDecl(ASTCtx, "i");
7161 
7162         auto *ThisLoc =
7163             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
7164         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
7165             *cast<ValueDecl>(IndirectField->chain().front())));
7166 
7167         ASSERT_EQ(AnonStruct.getChild(*IDecl),
7168                   Env.getStorageLocation(*GlobalIDecl));
7169       });
7170 }
7171 
7172 TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {
7173   // This is a crash repro.
7174   // `false` block may not have been processed when we try to evaluate the `||`
7175   // after visiting `true`, because it is not necessary (and therefore the edge
7176   // is marked unreachable). Trying to get the analysis state via
7177   // `getEnvironment` for the subexpression still should not crash.
7178   std::string Code = R"(
7179     int target(int i) {
7180       if ((i < 0 && true) || false) {
7181         return 0;
7182       }
7183       return 0;
7184     }
7185   )";
7186   runDataflow(
7187       Code,
7188       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7189          ASTContext &ASTCtx) {});
7190 }
7191 
7192 TEST(TransferTest, LambdaCaptureByCopy) {
7193   std::string Code = R"(
7194     void target(int Foo, int Bar) {
7195       [Foo]() {
7196         (void)0;
7197         // [[p]]
7198       }();
7199     }
7200   )";
7201   runDataflowOnLambda(
7202       Code,
7203       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7204          ASTContext &ASTCtx) {
7205         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7206         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7207 
7208         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7209         ASSERT_THAT(FooDecl, NotNull());
7210 
7211         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7212         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7213 
7214         const Value *FooVal = Env.getValue(*FooLoc);
7215         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7216 
7217         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7218         ASSERT_THAT(BarDecl, NotNull());
7219 
7220         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7221         EXPECT_THAT(BarLoc, IsNull());
7222       });
7223 }
7224 
7225 TEST(TransferTest, LambdaCaptureByReference) {
7226   std::string Code = R"(
7227     void target(int Foo, int Bar) {
7228       [&Foo]() {
7229         (void)0;
7230         // [[p]]
7231       }();
7232     }
7233   )";
7234   runDataflowOnLambda(
7235       Code,
7236       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7237          ASTContext &ASTCtx) {
7238         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7239         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7240 
7241         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7242         ASSERT_THAT(FooDecl, NotNull());
7243 
7244         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7245         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7246 
7247         const Value *FooVal = Env.getValue(*FooLoc);
7248         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7249 
7250         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7251         ASSERT_THAT(BarDecl, NotNull());
7252 
7253         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7254         EXPECT_THAT(BarLoc, IsNull());
7255       });
7256 }
7257 
7258 TEST(TransferTest, LambdaCaptureWithInitializer) {
7259   std::string Code = R"(
7260     void target(int Bar) {
7261       [Foo=Bar]() {
7262         (void)0;
7263         // [[p]]
7264       }();
7265     }
7266   )";
7267   runDataflowOnLambda(
7268       Code,
7269       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7270          ASTContext &ASTCtx) {
7271         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7272         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7273 
7274         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7275         ASSERT_THAT(FooDecl, NotNull());
7276 
7277         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7278         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7279 
7280         const Value *FooVal = Env.getValue(*FooLoc);
7281         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7282 
7283         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7284         ASSERT_THAT(BarDecl, NotNull());
7285 
7286         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7287         EXPECT_THAT(BarLoc, IsNull());
7288       });
7289 }
7290 
7291 TEST(TransferTest, LambdaCaptureByCopyImplicit) {
7292   std::string Code = R"(
7293     void target(int Foo, int Bar) {
7294       [=]() {
7295         Foo;
7296         // [[p]]
7297       }();
7298     }
7299   )";
7300   runDataflowOnLambda(
7301       Code,
7302       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7303          ASTContext &ASTCtx) {
7304         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7305         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7306 
7307         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7308         ASSERT_THAT(FooDecl, NotNull());
7309 
7310         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7311         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7312 
7313         const Value *FooVal = Env.getValue(*FooLoc);
7314         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7315 
7316         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7317         ASSERT_THAT(BarDecl, NotNull());
7318 
7319         // There is no storage location for `Bar` because it isn't used in the
7320         // body of the lambda.
7321         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7322         EXPECT_THAT(BarLoc, IsNull());
7323       });
7324 }
7325 
7326 TEST(TransferTest, LambdaCaptureByReferenceImplicit) {
7327   std::string Code = R"(
7328     void target(int Foo, int Bar) {
7329       [&]() {
7330         Foo;
7331         // [[p]]
7332       }();
7333     }
7334   )";
7335   runDataflowOnLambda(
7336       Code,
7337       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7338          ASTContext &ASTCtx) {
7339         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7340         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7341 
7342         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7343         ASSERT_THAT(FooDecl, NotNull());
7344 
7345         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7346         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7347 
7348         const Value *FooVal = Env.getValue(*FooLoc);
7349         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7350 
7351         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7352         ASSERT_THAT(BarDecl, NotNull());
7353 
7354         // There is no storage location for `Bar` because it isn't used in the
7355         // body of the lambda.
7356         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7357         EXPECT_THAT(BarLoc, IsNull());
7358       });
7359 }
7360 
7361 TEST(TransferTest, LambdaCaptureThis) {
7362   std::string Code = R"(
7363     struct Bar {
7364       int Foo;
7365 
7366       void target() {
7367         [this]() {
7368           Foo;
7369           // [[p]]
7370         }();
7371       }
7372     };
7373   )";
7374   runDataflowOnLambda(
7375       Code,
7376       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7377          ASTContext &ASTCtx) {
7378         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7379         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7380 
7381         const RecordStorageLocation *ThisPointeeLoc =
7382             Env.getThisPointeeStorageLocation();
7383         ASSERT_THAT(ThisPointeeLoc, NotNull());
7384 
7385         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7386         ASSERT_THAT(FooDecl, NotNull());
7387 
7388         const StorageLocation *FooLoc = ThisPointeeLoc->getChild(*FooDecl);
7389         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7390 
7391         const Value *FooVal = Env.getValue(*FooLoc);
7392         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7393       });
7394 }
7395 
7396 // This test verifies correct modeling of a relational dependency that goes
7397 // through unmodeled functions (the simple `cond()` in this case).
7398 TEST(TransferTest, ConditionalRelation) {
7399   std::string Code = R"(
7400     bool cond();
7401     void target() {
7402        bool a = true;
7403        bool b = true;
7404        if (cond()) {
7405          a = false;
7406          if (cond()) {
7407            b = false;
7408          }
7409        }
7410        (void)0;
7411        // [[p]]
7412     }
7413  )";
7414   runDataflow(
7415       Code,
7416       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7417          ASTContext &ASTCtx) {
7418         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7419         auto &A = Env.arena();
7420         auto &VarA = getValueForDecl<BoolValue>(ASTCtx, Env, "a").formula();
7421         auto &VarB = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
7422 
7423         EXPECT_FALSE(Env.allows(A.makeAnd(VarA, A.makeNot(VarB))));
7424       });
7425 }
7426 
7427 // This is a crash repro.
7428 // We used to crash while transferring `S().i` because Clang contained a bug
7429 // causing the AST to be malformed.
7430 TEST(TransferTest, AnonymousUnionMemberExprInTemplate) {
7431   using ast_matchers::functionDecl;
7432   using ast_matchers::hasName;
7433   using ast_matchers::unless;
7434 
7435   std::string Code = R"cc(
7436     struct S {
7437       struct {
7438         int i;
7439       };
7440     };
7441 
7442     template <class>
7443     void target() {
7444         S().i;
7445     }
7446 
7447     template void target<int>();
7448   )cc";
7449   auto Matcher = functionDecl(hasName("target"), unless(isTemplated()));
7450   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code, Matcher),
7451                     llvm::Succeeded());
7452 }
7453 
7454 } // namespace
7455