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