xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision 9ba6961ce05b17a70c22354f0b54a963ed1ab49c)
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       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 
2278           const auto *FooBazVal2 =
2279               cast<IntegerValue>(getFieldValue(FooLoc2, *BazDecl, Env2));
2280           const auto *BarBazVal2 =
2281               cast<IntegerValue>(getFieldValue(BarLoc2, *BazDecl, Env2));
2282           EXPECT_EQ(FooBazVal2, BarBazVal2);
2283         }
2284 
2285         // After value update.
2286         {
2287           const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
2288 
2289           const auto *FooLoc3 =
2290               cast<RecordStorageLocation>(Env3.getStorageLocation(*FooDecl));
2291           const auto *BarLoc3 =
2292               cast<RecordStorageLocation>(Env3.getStorageLocation(*BarDecl));
2293           EXPECT_FALSE(recordsEqual(*FooLoc3, *BarLoc3, Env3));
2294 
2295           const auto *FooBazVal3 =
2296               cast<IntegerValue>(getFieldValue(FooLoc3, *BazDecl, Env3));
2297           const auto *BarBazVal3 =
2298               cast<IntegerValue>(getFieldValue(BarLoc3, *BazDecl, Env3));
2299           EXPECT_NE(FooBazVal3, BarBazVal3);
2300         }
2301       });
2302 }
2303 
2304 // It's legal for the assignment operator to take its source parameter by value.
2305 // Check that we handle this correctly. (This is a repro -- we used to
2306 // assert-fail on this.)
2307 TEST(TransferTest, AssignmentOperator_ArgByValue) {
2308   std::string Code = R"(
2309     struct A {
2310       int Baz;
2311       A &operator=(A);
2312     };
2313 
2314     void target() {
2315       A Foo = { 1 };
2316       A Bar = { 2 };
2317       Foo = Bar;
2318       // [[p]]
2319     }
2320   )";
2321   runDataflow(
2322       Code,
2323       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2324          ASTContext &ASTCtx) {
2325         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2326         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2327 
2328         const auto &FooLoc =
2329             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo");
2330         const auto &BarLoc =
2331             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar");
2332 
2333         const auto *FooBazVal =
2334             cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env));
2335         const auto *BarBazVal =
2336             cast<IntegerValue>(getFieldValue(&BarLoc, *BazDecl, Env));
2337         EXPECT_EQ(FooBazVal, BarBazVal);
2338       });
2339 }
2340 
2341 TEST(TransferTest, AssignmentOperatorFromBase) {
2342   std::string Code = R"(
2343     struct Base {
2344       int base;
2345     };
2346     struct Derived : public Base {
2347       using Base::operator=;
2348       int derived;
2349     };
2350     void target(Base B, Derived D) {
2351       D.base = 1;
2352       D.derived = 1;
2353       // [[before]]
2354       D = B;
2355       // [[after]]
2356     }
2357   )";
2358   runDataflow(
2359       Code,
2360       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2361          ASTContext &ASTCtx) {
2362         const Environment &EnvBefore =
2363             getEnvironmentAtAnnotation(Results, "before");
2364         const Environment &EnvAfter =
2365             getEnvironmentAtAnnotation(Results, "after");
2366 
2367         auto &BLoc =
2368             getLocForDecl<RecordStorageLocation>(ASTCtx, EnvBefore, "B");
2369         auto &DLoc =
2370             getLocForDecl<RecordStorageLocation>(ASTCtx, EnvBefore, "D");
2371 
2372         EXPECT_NE(getFieldValue(&BLoc, "base", ASTCtx, EnvBefore),
2373                   getFieldValue(&DLoc, "base", ASTCtx, EnvBefore));
2374         EXPECT_EQ(getFieldValue(&BLoc, "base", ASTCtx, EnvAfter),
2375                   getFieldValue(&DLoc, "base", ASTCtx, EnvAfter));
2376 
2377         EXPECT_EQ(getFieldValue(&DLoc, "derived", ASTCtx, EnvBefore),
2378                   getFieldValue(&DLoc, "derived", ASTCtx, EnvAfter));
2379       });
2380 }
2381 
2382 TEST(TransferTest, AssignmentOperatorFromCallResult) {
2383   std::string Code = R"(
2384     struct A {};
2385     A ReturnA();
2386 
2387     void target() {
2388       A MyA;
2389       MyA = ReturnA();
2390     }
2391   )";
2392   runDataflow(
2393       Code,
2394       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2395          ASTContext &ASTCtx) {
2396         // As of this writing, we don't produce a `Value` for the call
2397         // `ReturnA()`. The only condition we're testing for is that the
2398         // analysis should not crash in this case.
2399       });
2400 }
2401 
2402 TEST(TransferTest, AssignmentOperatorWithInitAndInheritance) {
2403   // This is a crash repro.
2404   std::string Code = R"(
2405     struct B { int Foo; };
2406     struct S : public B {};
2407     void target() {
2408       S S1 = { 1 };
2409       S S2;
2410       S S3;
2411       S1 = S2;  // Only Dst has InitListExpr.
2412       S3 = S1;  // Only Src has InitListExpr.
2413       // [[p]]
2414     }
2415   )";
2416   runDataflow(
2417       Code,
2418       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2419          ASTContext &ASTCtx) {});
2420 }
2421 
2422 TEST(TransferTest, AssignmentOperatorReturnsVoid) {
2423   // This is a crash repro.
2424   std::string Code = R"(
2425     struct S {
2426       void operator=(S&& other);
2427     };
2428     void target() {
2429       S s;
2430       s = S();
2431       // [[p]]
2432     }
2433   )";
2434   runDataflow(
2435       Code,
2436       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2437          ASTContext &ASTCtx) {});
2438 }
2439 
2440 TEST(TransferTest, AssignmentOperatorReturnsByValue) {
2441   // This is a crash repro.
2442   std::string Code = R"(
2443     struct S {
2444       S operator=(S&& other);
2445     };
2446     void target() {
2447       S s;
2448       s = S();
2449       // [[p]]
2450     }
2451   )";
2452   runDataflow(
2453       Code,
2454       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2455          ASTContext &ASTCtx) {});
2456 }
2457 
2458 TEST(TransferTest, InitListExprAsXValue) {
2459   // This is a crash repro.
2460   std::string Code = R"(
2461     void target() {
2462       bool&& Foo{false};
2463       // [[p]]
2464     }
2465   )";
2466   runDataflow(
2467       Code,
2468       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2469          ASTContext &ASTCtx) {
2470         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2471         const auto &FooVal = getValueForDecl<BoolValue>(ASTCtx, Env, "Foo");
2472         ASSERT_TRUE(FooVal.formula().isLiteral(false));
2473       });
2474 }
2475 
2476 TEST(TransferTest, ArrayInitListExprOneRecordElement) {
2477   // This is a crash repro.
2478   std::string Code = R"cc(
2479     struct S {};
2480 
2481     void target() { S foo[] = {S()}; }
2482   )cc";
2483   runDataflow(
2484       Code,
2485       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2486          ASTContext &ASTCtx) {
2487         // Just verify that it doesn't crash.
2488       });
2489 }
2490 
2491 TEST(TransferTest, InitListExprAsUnion) {
2492   // This is a crash repro.
2493   std::string Code = R"cc(
2494     class target {
2495       union {
2496         int *a;
2497         bool *b;
2498       } F;
2499 
2500      public:
2501       constexpr target() : F{nullptr} {
2502         int *null = nullptr;
2503         F.b;  // Make sure we reference 'b' so it is modeled.
2504         // [[p]]
2505       }
2506     };
2507   )cc";
2508   runDataflow(
2509       Code,
2510       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2511          ASTContext &ASTCtx) {
2512         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2513 
2514         auto &FLoc = getFieldLoc<RecordStorageLocation>(
2515             *Env.getThisPointeeStorageLocation(), "F", ASTCtx);
2516         auto *AVal = cast<PointerValue>(getFieldValue(&FLoc, "a", ASTCtx, Env));
2517         EXPECT_EQ(AVal, &getValueForDecl<PointerValue>(ASTCtx, Env, "null"));
2518         EXPECT_EQ(getFieldValue(&FLoc, "b", ASTCtx, Env), nullptr);
2519       });
2520 }
2521 
2522 TEST(TransferTest, EmptyInitListExprForUnion) {
2523   // This is a crash repro.
2524   std::string Code = R"cc(
2525     class target {
2526       union {
2527         int *a;
2528         bool *b;
2529       } F;
2530 
2531      public:
2532       // Empty initializer list means that `F` is aggregate-initialized.
2533       // For a union, this has the effect that the first member of the union
2534       // is copy-initialized from an empty initializer list; in this specific
2535       // case, this has the effect of initializing `a` with null.
2536       constexpr target() : F{} {
2537         int *null = nullptr;
2538         F.b;  // Make sure we reference 'b' so it is modeled.
2539         // [[p]]
2540       }
2541     };
2542   )cc";
2543   runDataflow(
2544       Code,
2545       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2546          ASTContext &ASTCtx) {
2547         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2548 
2549         auto &FLoc = getFieldLoc<RecordStorageLocation>(
2550             *Env.getThisPointeeStorageLocation(), "F", ASTCtx);
2551         auto *AVal = cast<PointerValue>(getFieldValue(&FLoc, "a", ASTCtx, Env));
2552         EXPECT_EQ(AVal, &getValueForDecl<PointerValue>(ASTCtx, Env, "null"));
2553         EXPECT_EQ(getFieldValue(&FLoc, "b", ASTCtx, Env), nullptr);
2554       });
2555 }
2556 
2557 TEST(TransferTest, EmptyInitListExprForStruct) {
2558   std::string Code = R"cc(
2559     class target {
2560       struct {
2561         int *a;
2562         bool *b;
2563       } F;
2564 
2565      public:
2566       constexpr target() : F{} {
2567         int *NullIntPtr = nullptr;
2568         bool *NullBoolPtr = nullptr;
2569         // [[p]]
2570       }
2571     };
2572   )cc";
2573   runDataflow(
2574       Code,
2575       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2576          ASTContext &ASTCtx) {
2577         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2578 
2579         auto &FLoc = getFieldLoc<RecordStorageLocation>(
2580             *Env.getThisPointeeStorageLocation(), "F", ASTCtx);
2581         auto *AVal = cast<PointerValue>(getFieldValue(&FLoc, "a", ASTCtx, Env));
2582         EXPECT_EQ(AVal,
2583                   &getValueForDecl<PointerValue>(ASTCtx, Env, "NullIntPtr"));
2584         auto *BVal = cast<PointerValue>(getFieldValue(&FLoc, "b", ASTCtx, Env));
2585         EXPECT_EQ(BVal,
2586                   &getValueForDecl<PointerValue>(ASTCtx, Env, "NullBoolPtr"));
2587       });
2588 }
2589 
2590 TEST(TransferTest, CopyConstructor) {
2591   std::string Code = R"(
2592     struct A {
2593       int Baz;
2594     };
2595 
2596     void target() {
2597       A Foo = { 1 };
2598       A Bar = Foo;
2599       // [[after_copy]]
2600       Foo.Baz = 2;
2601       // [[after_update]]
2602     }
2603   )";
2604   runDataflow(
2605       Code,
2606       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2607          ASTContext &ASTCtx) {
2608         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2609         ASSERT_THAT(FooDecl, NotNull());
2610 
2611         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2612         ASSERT_THAT(BarDecl, NotNull());
2613 
2614         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2615         ASSERT_THAT(BazDecl, NotNull());
2616 
2617         // after_copy
2618         {
2619           const Environment &Env =
2620               getEnvironmentAtAnnotation(Results, "after_copy");
2621 
2622           const auto *FooLoc =
2623               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2624           const auto *BarLoc =
2625               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2626 
2627           // The records compare equal.
2628           EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2629 
2630           // In particular, the value of `Baz` in both records is the same.
2631           const auto *FooBazVal =
2632               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2633           const auto *BarBazVal =
2634               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2635           EXPECT_EQ(FooBazVal, BarBazVal);
2636         }
2637 
2638         // after_update
2639         {
2640           const Environment &Env =
2641               getEnvironmentAtAnnotation(Results, "after_update");
2642 
2643           const auto *FooLoc =
2644               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2645           const auto *BarLoc =
2646               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2647 
2648           EXPECT_FALSE(recordsEqual(*FooLoc, *BarLoc, Env));
2649 
2650           const auto *FooBazVal =
2651               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2652           const auto *BarBazVal =
2653               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2654           EXPECT_NE(FooBazVal, BarBazVal);
2655         }
2656       });
2657 }
2658 
2659 TEST(TransferTest, CopyConstructorWithDefaultArgument) {
2660   std::string Code = R"(
2661     struct A {
2662       int Baz;
2663       A() = default;
2664       A(const A& a, bool def = true) { Baz = a.Baz; }
2665     };
2666 
2667     void target() {
2668       A Foo;
2669       (void)Foo.Baz;
2670       A Bar = Foo;
2671       // [[p]]
2672     }
2673   )";
2674   runDataflow(
2675       Code,
2676       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2677          ASTContext &ASTCtx) {
2678         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2679         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2680 
2681         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2682         ASSERT_THAT(FooDecl, NotNull());
2683 
2684         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2685         ASSERT_THAT(BarDecl, NotNull());
2686 
2687         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2688         ASSERT_THAT(BazDecl, NotNull());
2689 
2690         const auto *FooLoc =
2691             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2692         const auto *BarLoc =
2693             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2694         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2695 
2696         const auto *FooBazVal =
2697             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2698         const auto *BarBazVal =
2699             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2700         EXPECT_EQ(FooBazVal, BarBazVal);
2701       });
2702 }
2703 
2704 TEST(TransferTest, CopyConstructorWithParens) {
2705   std::string Code = R"(
2706     struct A {
2707       int Baz;
2708     };
2709 
2710     void target() {
2711       A Foo;
2712       (void)Foo.Baz;
2713       A Bar((A(Foo)));
2714       // [[p]]
2715     }
2716   )";
2717   runDataflow(
2718       Code,
2719       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2720          ASTContext &ASTCtx) {
2721         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2722         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2723 
2724         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2725         ASSERT_THAT(FooDecl, NotNull());
2726 
2727         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2728         ASSERT_THAT(BarDecl, NotNull());
2729 
2730         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2731         ASSERT_THAT(BazDecl, NotNull());
2732 
2733         const auto *FooLoc =
2734             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2735         const auto *BarLoc =
2736             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2737         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2738 
2739         const auto *FooBazVal =
2740             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2741         const auto *BarBazVal =
2742             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2743         EXPECT_EQ(FooBazVal, BarBazVal);
2744       });
2745 }
2746 
2747 TEST(TransferTest, CopyConstructorWithInitializerListAsSyntacticSugar) {
2748   std::string Code = R"(
2749   struct A {
2750     int Baz;
2751   };
2752   void target() {
2753     A Foo = {3};
2754     (void)Foo.Baz;
2755     A Bar = {A(Foo)};
2756     // [[p]]
2757   }
2758   )";
2759   runDataflow(
2760       Code,
2761       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2762          ASTContext &ASTCtx) {
2763         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2764 
2765         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2766 
2767         const auto &FooLoc =
2768             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo");
2769         const auto &BarLoc =
2770             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar");
2771 
2772         const auto *FooBazVal =
2773             cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env));
2774         const auto *BarBazVal =
2775             cast<IntegerValue>(getFieldValue(&BarLoc, *BazDecl, Env));
2776         EXPECT_EQ(FooBazVal, BarBazVal);
2777       });
2778 }
2779 
2780 TEST(TransferTest, CopyConstructorArgIsRefReturnedByFunction) {
2781   // This is a crash repro.
2782   std::string Code = R"(
2783     struct S {};
2784     const S &returnsSRef();
2785     void target() {
2786       S s(returnsSRef());
2787     }
2788   )";
2789   runDataflow(
2790       Code,
2791       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2792          ASTContext &ASTCtx) {});
2793 }
2794 
2795 TEST(TransferTest, MoveConstructor) {
2796   std::string Code = R"(
2797     namespace std {
2798 
2799     template <typename T> struct remove_reference      { using type = T; };
2800     template <typename T> struct remove_reference<T&>  { using type = T; };
2801     template <typename T> struct remove_reference<T&&> { using type = T; };
2802 
2803     template <typename T>
2804     using remove_reference_t = typename remove_reference<T>::type;
2805 
2806     template <typename T>
2807     std::remove_reference_t<T>&& move(T&& x);
2808 
2809     } // namespace std
2810 
2811     struct A {
2812       int Baz;
2813     };
2814 
2815     void target() {
2816       A Foo;
2817       A Bar;
2818       (void)Foo.Baz;
2819       // [[p1]]
2820       Foo = std::move(Bar);
2821       // [[p2]]
2822     }
2823   )";
2824   runDataflow(
2825       Code,
2826       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2827          ASTContext &ASTCtx) {
2828         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
2829         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2830         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
2831 
2832         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2833         ASSERT_THAT(FooDecl, NotNull());
2834 
2835         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2836         ASSERT_THAT(BarDecl, NotNull());
2837 
2838         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2839         ASSERT_THAT(BazDecl, NotNull());
2840 
2841         const auto *FooLoc1 =
2842             cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
2843         const auto *BarLoc1 =
2844             cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
2845 
2846         EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
2847 
2848         const auto *FooBazVal1 =
2849             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1));
2850         const auto *BarBazVal1 =
2851             cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1));
2852         EXPECT_NE(FooBazVal1, BarBazVal1);
2853 
2854         const auto *FooLoc2 =
2855             cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
2856         EXPECT_TRUE(recordsEqual(*FooLoc2, Env2, *BarLoc1, Env1));
2857 
2858         const auto *FooBazVal2 =
2859             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env2));
2860         EXPECT_EQ(FooBazVal2, BarBazVal1);
2861       });
2862 }
2863 
2864 TEST(TransferTest, BindTemporary) {
2865   std::string Code = R"(
2866     struct A {
2867       virtual ~A() = default;
2868 
2869       int Baz;
2870     };
2871 
2872     void target(A Foo) {
2873       int Bar = A(Foo).Baz;
2874       // [[p]]
2875     }
2876   )";
2877   runDataflow(
2878       Code,
2879       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2880          ASTContext &ASTCtx) {
2881         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2882         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2883 
2884         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2885         ASSERT_THAT(FooDecl, NotNull());
2886 
2887         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2888         ASSERT_THAT(BarDecl, NotNull());
2889 
2890         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2891         ASSERT_THAT(BazDecl, NotNull());
2892 
2893         const auto &FooLoc =
2894             *cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2895         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
2896         EXPECT_EQ(BarVal, getFieldValue(&FooLoc, *BazDecl, Env));
2897       });
2898 }
2899 
2900 TEST(TransferTest, ResultObjectLocation) {
2901   std::string Code = R"(
2902     struct A {
2903       virtual ~A() = default;
2904     };
2905 
2906     void target() {
2907       0, A();
2908       (void)0; // [[p]]
2909     }
2910   )";
2911   using ast_matchers::binaryOperator;
2912   using ast_matchers::cxxBindTemporaryExpr;
2913   using ast_matchers::cxxTemporaryObjectExpr;
2914   using ast_matchers::exprWithCleanups;
2915   using ast_matchers::has;
2916   using ast_matchers::hasOperatorName;
2917   using ast_matchers::hasRHS;
2918   using ast_matchers::match;
2919   using ast_matchers::selectFirst;
2920   using ast_matchers::traverse;
2921   runDataflow(
2922       Code,
2923       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2924          ASTContext &ASTCtx) {
2925         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2926 
2927         // The expression `0, A()` in the code above produces the following
2928         // structure, consisting of four prvalues of record type.
2929         // `Env.getResultObjectLocation()` should return the same location for
2930         // all of these.
2931         auto MatchResult = match(
2932             traverse(TK_AsIs,
2933                      exprWithCleanups(
2934                          has(binaryOperator(
2935                                  hasOperatorName(","),
2936                                  hasRHS(cxxBindTemporaryExpr(
2937                                             has(cxxTemporaryObjectExpr().bind(
2938                                                 "toe")))
2939                                             .bind("bte")))
2940                                  .bind("comma")))
2941                          .bind("ewc")),
2942             ASTCtx);
2943         auto *TOE = selectFirst<CXXTemporaryObjectExpr>("toe", MatchResult);
2944         ASSERT_NE(TOE, nullptr);
2945         auto *Comma = selectFirst<BinaryOperator>("comma", MatchResult);
2946         ASSERT_NE(Comma, nullptr);
2947         auto *EWC = selectFirst<ExprWithCleanups>("ewc", MatchResult);
2948         ASSERT_NE(EWC, nullptr);
2949         auto *BTE = selectFirst<CXXBindTemporaryExpr>("bte", MatchResult);
2950         ASSERT_NE(BTE, nullptr);
2951 
2952         RecordStorageLocation &Loc = Env.getResultObjectLocation(*TOE);
2953         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*Comma));
2954         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*EWC));
2955         EXPECT_EQ(&Loc, &Env.getResultObjectLocation(*BTE));
2956       });
2957 }
2958 
2959 TEST(TransferTest, ResultObjectLocationForDefaultArgExpr) {
2960   std::string Code = R"(
2961     struct Inner {};
2962     struct Outer {
2963         Inner I = {};
2964     };
2965 
2966     void funcWithDefaultArg(Outer O = {});
2967     void target() {
2968       funcWithDefaultArg();
2969       // [[p]]
2970     }
2971   )";
2972 
2973   using ast_matchers::cxxDefaultArgExpr;
2974   using ast_matchers::match;
2975   using ast_matchers::selectFirst;
2976   runDataflow(
2977       Code,
2978       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2979          ASTContext &ASTCtx) {
2980         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2981 
2982         auto *DefaultArg = selectFirst<CXXDefaultArgExpr>(
2983             "default_arg",
2984             match(cxxDefaultArgExpr().bind("default_arg"), ASTCtx));
2985         ASSERT_NE(DefaultArg, nullptr);
2986 
2987         // The values for default arguments aren't modeled; we merely verify
2988         // that we can get a result object location for a default arg.
2989         Env.getResultObjectLocation(*DefaultArg);
2990       });
2991 }
2992 
2993 TEST(TransferTest, ResultObjectLocationForDefaultInitExpr) {
2994   std::string Code = R"(
2995     struct S {};
2996     struct target {
2997       target () {
2998         (void)0;
2999         // [[p]]
3000       }
3001       S s = {};
3002     };
3003   )";
3004 
3005   using ast_matchers::cxxCtorInitializer;
3006   using ast_matchers::match;
3007   using ast_matchers::selectFirst;
3008   runDataflow(
3009       Code,
3010       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3011          ASTContext &ASTCtx) {
3012         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3013 
3014         const ValueDecl *SField = findValueDecl(ASTCtx, "s");
3015 
3016         auto *CtorInit = selectFirst<CXXCtorInitializer>(
3017             "ctor_initializer",
3018             match(cxxCtorInitializer().bind("ctor_initializer"), ASTCtx));
3019         ASSERT_NE(CtorInit, nullptr);
3020 
3021         auto *DefaultInit = cast<CXXDefaultInitExpr>(CtorInit->getInit());
3022 
3023         RecordStorageLocation &Loc = Env.getResultObjectLocation(*DefaultInit);
3024 
3025         EXPECT_EQ(&Loc, Env.getThisPointeeStorageLocation()->getChild(*SField));
3026       });
3027 }
3028 
3029 // This test ensures that CXXOperatorCallExpr returning prvalues are correctly
3030 // handled by the transfer functions, especially that `getResultObjectLocation`
3031 // correctly returns a storage location for those.
3032 TEST(TransferTest, ResultObjectLocationForCXXOperatorCallExpr) {
3033   std::string Code = R"(
3034     struct A {
3035       A operator+(int);
3036     };
3037 
3038     void target() {
3039       A a;
3040       a + 3;
3041       (void)0; // [[p]]
3042     }
3043   )";
3044   using ast_matchers::cxxOperatorCallExpr;
3045   using ast_matchers::match;
3046   using ast_matchers::selectFirst;
3047   using ast_matchers::traverse;
3048   runDataflow(
3049       Code,
3050       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3051          ASTContext &ASTCtx) {
3052         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3053 
3054         auto *CallExpr = selectFirst<CXXOperatorCallExpr>(
3055             "call_expr",
3056             match(cxxOperatorCallExpr().bind("call_expr"), ASTCtx));
3057 
3058         EXPECT_NE(&Env.getResultObjectLocation(*CallExpr), nullptr);
3059       });
3060 }
3061 
3062 TEST(TransferTest, ResultObjectLocationForInitListExpr) {
3063   std::string Code = R"cc(
3064     struct Inner {};
3065 
3066     struct Outer { Inner I; };
3067 
3068     void target() {
3069       Outer O = { Inner() };
3070       // [[p]]
3071     }
3072   )cc";
3073   using ast_matchers::asString;
3074   using ast_matchers::cxxConstructExpr;
3075   using ast_matchers::hasType;
3076   using ast_matchers::match;
3077   using ast_matchers::selectFirst;
3078   using ast_matchers::traverse;
3079   runDataflow(
3080       Code,
3081       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3082          ASTContext &ASTCtx) {
3083         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3084 
3085         auto *Construct = selectFirst<CXXConstructExpr>(
3086             "construct",
3087             match(
3088                 cxxConstructExpr(hasType(asString("Inner"))).bind("construct"),
3089                 ASTCtx));
3090 
3091         EXPECT_EQ(
3092             &Env.getResultObjectLocation(*Construct),
3093             &getFieldLoc(getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "O"),
3094                          "I", ASTCtx));
3095       });
3096 }
3097 
3098 TEST(TransferTest, ResultObjectLocationForParenInitListExpr) {
3099   std::string Code = R"cc(
3100     struct Inner {};
3101 
3102     struct Outer { Inner I; };
3103 
3104     void target() {
3105       Outer O((Inner()));
3106       // [[p]]
3107     }
3108   )cc";
3109   using ast_matchers::asString;
3110   using ast_matchers::cxxConstructExpr;
3111   using ast_matchers::hasType;
3112   using ast_matchers::match;
3113   using ast_matchers::selectFirst;
3114   using ast_matchers::traverse;
3115   runDataflow(
3116       Code,
3117       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3118          ASTContext &ASTCtx) {
3119         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3120 
3121         auto *Construct = selectFirst<CXXConstructExpr>(
3122             "construct",
3123             match(
3124                 cxxConstructExpr(hasType(asString("Inner"))).bind("construct"),
3125                 ASTCtx));
3126 
3127         EXPECT_EQ(
3128             &Env.getResultObjectLocation(*Construct),
3129             &getFieldLoc(getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "O"),
3130                          "I", ASTCtx));
3131       },
3132       LangStandard::lang_cxx20);
3133 }
3134 
3135 // Check that the `std::strong_ordering` object returned by builtin `<=>` has a
3136 // correctly modeled result object location.
3137 TEST(TransferTest, ResultObjectLocationForBuiltinSpaceshipOperator) {
3138   std::string Code = R"(
3139     namespace std {
3140       // This is the minimal definition required to get
3141       // `Sema::CheckComparisonCategoryType()` to accept this fake.
3142       struct strong_ordering {
3143         enum class ordering { less, equal, greater };
3144         ordering o;
3145         static const strong_ordering less;
3146         static const strong_ordering equivalent;
3147         static const strong_ordering equal;
3148         static const strong_ordering greater;
3149       };
3150 
3151       inline constexpr strong_ordering strong_ordering::less =
3152         { strong_ordering::ordering::less };
3153       inline constexpr strong_ordering strong_ordering::equal =
3154         { strong_ordering::ordering::equal };
3155       inline constexpr strong_ordering strong_ordering::equivalent =
3156         { strong_ordering::ordering::equal };
3157       inline constexpr strong_ordering strong_ordering::greater =
3158         { strong_ordering::ordering::greater };
3159     }
3160     void target(int i, int j) {
3161       auto ordering = i <=> j;
3162       // [[p]]
3163     }
3164   )";
3165   using ast_matchers::binaryOperator;
3166   using ast_matchers::hasOperatorName;
3167   using ast_matchers::match;
3168   using ast_matchers::selectFirst;
3169   using ast_matchers::traverse;
3170   runDataflow(
3171       Code,
3172       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3173          ASTContext &ASTCtx) {
3174         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3175 
3176         auto *Spaceship = selectFirst<BinaryOperator>(
3177             "op",
3178             match(binaryOperator(hasOperatorName("<=>")).bind("op"), ASTCtx));
3179 
3180         EXPECT_EQ(
3181             &Env.getResultObjectLocation(*Spaceship),
3182             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "ordering"));
3183       },
3184       LangStandard::lang_cxx20);
3185 }
3186 
3187 TEST(TransferTest, ResultObjectLocationForStdInitializerListExpr) {
3188   std::string Code = R"(
3189     namespace std {
3190     template <typename T>
3191     struct initializer_list {};
3192     } // namespace std
3193 
3194     void target() {
3195       std::initializer_list<int> list = {1};
3196       // [[p]]
3197     }
3198   )";
3199 
3200   using ast_matchers::cxxStdInitializerListExpr;
3201   using ast_matchers::match;
3202   using ast_matchers::selectFirst;
3203   runDataflow(
3204       Code,
3205       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3206          ASTContext &ASTCtx) {
3207         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3208 
3209         auto *StdInitList = selectFirst<CXXStdInitializerListExpr>(
3210             "std_init_list",
3211             match(cxxStdInitializerListExpr().bind("std_init_list"), ASTCtx));
3212         ASSERT_NE(StdInitList, nullptr);
3213 
3214         EXPECT_EQ(&Env.getResultObjectLocation(*StdInitList),
3215                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "list"));
3216       });
3217 }
3218 
3219 TEST(TransferTest, ResultObjectLocationForStmtExpr) {
3220   std::string Code = R"(
3221     struct S {};
3222     void target() {
3223       S s = ({ S(); });
3224       // [[p]]
3225     }
3226   )";
3227   using ast_matchers::cxxConstructExpr;
3228   using ast_matchers::match;
3229   using ast_matchers::selectFirst;
3230   using ast_matchers::traverse;
3231   runDataflow(
3232       Code,
3233       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3234          ASTContext &ASTCtx) {
3235         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3236 
3237         auto *Construct = selectFirst<CXXConstructExpr>(
3238             "construct", match(cxxConstructExpr().bind("construct"), ASTCtx));
3239 
3240         EXPECT_EQ(&Env.getResultObjectLocation(*Construct),
3241                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s"));
3242       });
3243 }
3244 
3245 TEST(TransferTest, ResultObjectLocationForBuiltinBitCastExpr) {
3246   std::string Code = R"(
3247     struct S { int i; };
3248     void target(int i) {
3249       S s = __builtin_bit_cast(S, i);
3250       // [[p]]
3251     }
3252   )";
3253   using ast_matchers::explicitCastExpr;
3254   using ast_matchers::match;
3255   using ast_matchers::selectFirst;
3256   using ast_matchers::traverse;
3257   runDataflow(
3258       Code,
3259       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3260          ASTContext &ASTCtx) {
3261         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3262 
3263         auto *BuiltinBitCast = selectFirst<BuiltinBitCastExpr>(
3264             "cast", match(explicitCastExpr().bind("cast"), ASTCtx));
3265 
3266         EXPECT_EQ(&Env.getResultObjectLocation(*BuiltinBitCast),
3267                   &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s"));
3268       });
3269 }
3270 
3271 TEST(TransferTest, ResultObjectLocationPropagatesThroughConditionalOperator) {
3272   std::string Code = R"(
3273     struct A {
3274       A(int);
3275     };
3276 
3277     void target(bool b) {
3278       A a = b ? A(0) : A(1);
3279       (void)0; // [[p]]
3280     }
3281   )";
3282   using ast_matchers::cxxConstructExpr;
3283   using ast_matchers::equals;
3284   using ast_matchers::hasArgument;
3285   using ast_matchers::integerLiteral;
3286   using ast_matchers::match;
3287   using ast_matchers::selectFirst;
3288   using ast_matchers::traverse;
3289   runDataflow(
3290       Code,
3291       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3292          ASTContext &ASTCtx) {
3293         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3294 
3295         auto *ConstructExpr0 = selectFirst<CXXConstructExpr>(
3296             "construct",
3297             match(cxxConstructExpr(hasArgument(0, integerLiteral(equals(0))))
3298                       .bind("construct"),
3299                   ASTCtx));
3300         auto *ConstructExpr1 = selectFirst<CXXConstructExpr>(
3301             "construct",
3302             match(cxxConstructExpr(hasArgument(0, integerLiteral(equals(1))))
3303                       .bind("construct"),
3304                   ASTCtx));
3305 
3306         auto &ALoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "a");
3307         EXPECT_EQ(&Env.getResultObjectLocation(*ConstructExpr0), &ALoc);
3308         EXPECT_EQ(&Env.getResultObjectLocation(*ConstructExpr1), &ALoc);
3309       });
3310 }
3311 
3312 TEST(TransferTest, StaticCast) {
3313   std::string Code = R"(
3314     void target(int Foo) {
3315       int Bar = static_cast<int>(Foo);
3316       // [[p]]
3317     }
3318   )";
3319   runDataflow(
3320       Code,
3321       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3322          ASTContext &ASTCtx) {
3323         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3324         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3325 
3326         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3327         ASSERT_THAT(FooDecl, NotNull());
3328 
3329         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3330         ASSERT_THAT(BarDecl, NotNull());
3331 
3332         const auto *FooVal = Env.getValue(*FooDecl);
3333         const auto *BarVal = Env.getValue(*BarDecl);
3334         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3335         EXPECT_TRUE(isa<IntegerValue>(BarVal));
3336         EXPECT_EQ(FooVal, BarVal);
3337       });
3338 }
3339 
3340 TEST(TransferTest, IntegralCast) {
3341   std::string Code = R"(
3342     void target(int Foo) {
3343       long Bar = Foo;
3344       // [[p]]
3345     }
3346   )";
3347   runDataflow(
3348       Code,
3349       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3350          ASTContext &ASTCtx) {
3351         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3352         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3353 
3354         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3355         ASSERT_THAT(FooDecl, NotNull());
3356 
3357         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3358         ASSERT_THAT(BarDecl, NotNull());
3359 
3360         const auto *FooVal = Env.getValue(*FooDecl);
3361         const auto *BarVal = Env.getValue(*BarDecl);
3362         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3363         EXPECT_TRUE(isa<IntegerValue>(BarVal));
3364         EXPECT_EQ(FooVal, BarVal);
3365       });
3366 }
3367 
3368 TEST(TransferTest, IntegraltoBooleanCast) {
3369   std::string Code = R"(
3370     void target(int Foo) {
3371       bool Bar = Foo;
3372       // [[p]]
3373     }
3374   )";
3375   runDataflow(
3376       Code,
3377       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3378          ASTContext &ASTCtx) {
3379         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3380         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3381 
3382         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3383         ASSERT_THAT(FooDecl, NotNull());
3384 
3385         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3386         ASSERT_THAT(BarDecl, NotNull());
3387 
3388         const auto *FooVal = Env.getValue(*FooDecl);
3389         const auto *BarVal = Env.getValue(*BarDecl);
3390         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3391         EXPECT_TRUE(isa<BoolValue>(BarVal));
3392       });
3393 }
3394 
3395 TEST(TransferTest, IntegralToBooleanCastFromBool) {
3396   std::string Code = R"(
3397     void target(bool Foo) {
3398       int Zab = Foo;
3399       bool Bar = Zab;
3400       // [[p]]
3401     }
3402   )";
3403   runDataflow(
3404       Code,
3405       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3406          ASTContext &ASTCtx) {
3407         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3408         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3409 
3410         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3411         ASSERT_THAT(FooDecl, NotNull());
3412 
3413         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3414         ASSERT_THAT(BarDecl, NotNull());
3415 
3416         const auto *FooVal = Env.getValue(*FooDecl);
3417         const auto *BarVal = Env.getValue(*BarDecl);
3418         EXPECT_TRUE(isa<BoolValue>(FooVal));
3419         EXPECT_TRUE(isa<BoolValue>(BarVal));
3420         EXPECT_EQ(FooVal, BarVal);
3421       });
3422 }
3423 
3424 TEST(TransferTest, NullToPointerCast) {
3425   std::string Code = R"(
3426     using my_nullptr_t = decltype(nullptr);
3427     struct Baz {};
3428     void target() {
3429       int *FooX = nullptr;
3430       int *FooY = nullptr;
3431       bool **Bar = nullptr;
3432       Baz *Baz = nullptr;
3433       my_nullptr_t Null = 0;
3434       // [[p]]
3435     }
3436   )";
3437   runDataflow(
3438       Code,
3439       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3440          ASTContext &ASTCtx) {
3441         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3442         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3443 
3444         const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
3445         ASSERT_THAT(FooXDecl, NotNull());
3446 
3447         const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
3448         ASSERT_THAT(FooYDecl, NotNull());
3449 
3450         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3451         ASSERT_THAT(BarDecl, NotNull());
3452 
3453         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3454         ASSERT_THAT(BazDecl, NotNull());
3455 
3456         const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
3457         ASSERT_THAT(NullDecl, NotNull());
3458 
3459         const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl));
3460         const auto *FooYVal = cast<PointerValue>(Env.getValue(*FooYDecl));
3461         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3462         const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl));
3463         const auto *NullVal = cast<PointerValue>(Env.getValue(*NullDecl));
3464 
3465         EXPECT_EQ(FooXVal, FooYVal);
3466         EXPECT_NE(FooXVal, BarVal);
3467         EXPECT_NE(FooXVal, BazVal);
3468         EXPECT_NE(BarVal, BazVal);
3469 
3470         const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
3471         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
3472         EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
3473 
3474         const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
3475         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
3476         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
3477 
3478         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
3479         EXPECT_TRUE(isa<RecordStorageLocation>(BazPointeeLoc));
3480         EXPECT_EQ(BazVal, &Env.fork().getOrCreateNullPointerValue(
3481                               BazPointeeLoc.getType()));
3482 
3483         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
3484         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
3485         EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
3486       });
3487 }
3488 
3489 TEST(TransferTest, PointerToMemberVariable) {
3490   std::string Code = R"(
3491     struct S {
3492       int i;
3493     };
3494     void target() {
3495       int S::*MemberPointer = &S::i;
3496       // [[p]]
3497     }
3498   )";
3499   runDataflow(
3500       Code,
3501       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3502          ASTContext &ASTCtx) {
3503         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3504 
3505         const ValueDecl *MemberPointerDecl =
3506             findValueDecl(ASTCtx, "MemberPointer");
3507         ASSERT_THAT(MemberPointerDecl, NotNull());
3508         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3509       });
3510 }
3511 
3512 TEST(TransferTest, PointerToMemberFunction) {
3513   std::string Code = R"(
3514     struct S {
3515       void Method();
3516     };
3517     void target() {
3518       void (S::*MemberPointer)() = &S::Method;
3519       // [[p]]
3520     }
3521   )";
3522   runDataflow(
3523       Code,
3524       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3525          ASTContext &ASTCtx) {
3526         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3527 
3528         const ValueDecl *MemberPointerDecl =
3529             findValueDecl(ASTCtx, "MemberPointer");
3530         ASSERT_THAT(MemberPointerDecl, NotNull());
3531         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3532       });
3533 }
3534 
3535 TEST(TransferTest, NullToMemberPointerCast) {
3536   std::string Code = R"(
3537     struct Foo {};
3538     void target() {
3539       int Foo::*MemberPointer = nullptr;
3540       // [[p]]
3541     }
3542   )";
3543   runDataflow(
3544       Code,
3545       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3546          ASTContext &ASTCtx) {
3547         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3548         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3549 
3550         const ValueDecl *MemberPointerDecl =
3551             findValueDecl(ASTCtx, "MemberPointer");
3552         ASSERT_THAT(MemberPointerDecl, NotNull());
3553         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3554       });
3555 }
3556 
3557 TEST(TransferTest, AddrOfValue) {
3558   std::string Code = R"(
3559     void target() {
3560       int Foo;
3561       int *Bar = &Foo;
3562       // [[p]]
3563     }
3564   )";
3565   runDataflow(
3566       Code,
3567       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3568          ASTContext &ASTCtx) {
3569         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3570         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3571 
3572         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3573         ASSERT_THAT(FooDecl, NotNull());
3574 
3575         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3576         ASSERT_THAT(BarDecl, NotNull());
3577 
3578         const auto *FooLoc =
3579             cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
3580         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3581         EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
3582       });
3583 }
3584 
3585 TEST(TransferTest, AddrOfReference) {
3586   std::string Code = R"(
3587     void target(int *Foo) {
3588       int *Bar = &(*Foo);
3589       // [[p]]
3590     }
3591   )";
3592   runDataflow(
3593       Code,
3594       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3595          ASTContext &ASTCtx) {
3596         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3597         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3598 
3599         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3600         ASSERT_THAT(FooDecl, NotNull());
3601 
3602         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3603         ASSERT_THAT(BarDecl, NotNull());
3604 
3605         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl));
3606         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3607         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
3608       });
3609 }
3610 
3611 TEST(TransferTest, CannotAnalyzeFunctionTemplate) {
3612   std::string Code = R"(
3613     template <typename T>
3614     void target() {}
3615   )";
3616   ASSERT_THAT_ERROR(
3617       checkDataflowWithNoopAnalysis(Code),
3618       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3619 }
3620 
3621 TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) {
3622   std::string Code = R"(
3623     template <typename T>
3624     struct A {
3625       void target() {}
3626     };
3627   )";
3628   ASSERT_THAT_ERROR(
3629       checkDataflowWithNoopAnalysis(Code),
3630       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3631 }
3632 
3633 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
3634   std::string Code = R"(
3635     struct A {
3636       int i;
3637     };
3638 
3639     void target(A Foo, A Bar, bool Cond) {
3640       A Baz = Cond ?  A(Foo) : A(Bar);
3641       // Make sure A::i is modeled.
3642       Baz.i;
3643       /*[[p]]*/
3644     }
3645   )";
3646   runDataflow(
3647       Code,
3648       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3649          ASTContext &ASTCtx) {
3650         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3651 
3652         auto *FooIVal = cast<IntegerValue>(getFieldValue(
3653             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo"), "i",
3654             ASTCtx, Env));
3655         auto *BarIVal = cast<IntegerValue>(getFieldValue(
3656             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar"), "i",
3657             ASTCtx, Env));
3658         auto *BazIVal = cast<IntegerValue>(getFieldValue(
3659             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Baz"), "i",
3660             ASTCtx, Env));
3661 
3662         EXPECT_NE(BazIVal, FooIVal);
3663         EXPECT_NE(BazIVal, BarIVal);
3664       });
3665 }
3666 
3667 TEST(TransferTest, VarDeclInDoWhile) {
3668   std::string Code = R"(
3669     void target(int *Foo) {
3670       do {
3671         int Bar = *Foo;
3672         // [[in_loop]]
3673       } while (false);
3674       (void)0;
3675       // [[after_loop]]
3676     }
3677   )";
3678   runDataflow(
3679       Code,
3680       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3681          ASTContext &ASTCtx) {
3682         const Environment &EnvInLoop =
3683             getEnvironmentAtAnnotation(Results, "in_loop");
3684         const Environment &EnvAfterLoop =
3685             getEnvironmentAtAnnotation(Results, "after_loop");
3686 
3687         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3688         ASSERT_THAT(FooDecl, NotNull());
3689 
3690         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3691         ASSERT_THAT(BarDecl, NotNull());
3692 
3693         const auto *FooVal =
3694             cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl));
3695         const auto *FooPointeeVal =
3696             cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc()));
3697 
3698         const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl));
3699         EXPECT_EQ(BarVal, FooPointeeVal);
3700 
3701         ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), IsNull());
3702       });
3703 }
3704 
3705 TEST(TransferTest, UnreachableAfterWhileTrue) {
3706   std::string Code = R"(
3707     void target() {
3708       while (true) {}
3709       (void)0;
3710       /*[[p]]*/
3711     }
3712   )";
3713   runDataflow(
3714       Code,
3715       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3716          ASTContext &ASTCtx) {
3717         // The node after the while-true is pruned because it is trivially
3718         // known to be unreachable.
3719         ASSERT_TRUE(Results.empty());
3720       });
3721 }
3722 
3723 TEST(TransferTest, AggregateInitialization) {
3724   std::string BracesCode = R"(
3725     struct A {
3726       int Foo;
3727     };
3728 
3729     struct B {
3730       int Bar;
3731       A Baz;
3732       int Qux;
3733     };
3734 
3735     void target(int BarArg, int FooArg, int QuxArg) {
3736       B Quux{BarArg, {FooArg}, QuxArg};
3737       B OtherB;
3738       /*[[p]]*/
3739     }
3740   )";
3741   std::string BraceElisionCode = R"(
3742     struct A {
3743       int Foo;
3744     };
3745 
3746     struct B {
3747       int Bar;
3748       A Baz;
3749       int Qux;
3750     };
3751 
3752     void target(int BarArg, int FooArg, int QuxArg) {
3753       B Quux = {BarArg, FooArg, QuxArg};
3754       B OtherB;
3755       /*[[p]]*/
3756     }
3757   )";
3758   for (const std::string &Code : {BracesCode, BraceElisionCode}) {
3759     runDataflow(
3760         Code,
3761         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3762            ASTContext &ASTCtx) {
3763           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3764           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3765 
3766           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3767           ASSERT_THAT(FooDecl, NotNull());
3768 
3769           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3770           ASSERT_THAT(BarDecl, NotNull());
3771 
3772           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3773           ASSERT_THAT(BazDecl, NotNull());
3774 
3775           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3776           ASSERT_THAT(QuxDecl, NotNull());
3777 
3778           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
3779           ASSERT_THAT(FooArgDecl, NotNull());
3780 
3781           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
3782           ASSERT_THAT(BarArgDecl, NotNull());
3783 
3784           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
3785           ASSERT_THAT(QuxArgDecl, NotNull());
3786 
3787           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
3788           ASSERT_THAT(QuuxDecl, NotNull());
3789 
3790           const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl));
3791           const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl));
3792           const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl));
3793 
3794           const auto &QuuxLoc =
3795               *cast<RecordStorageLocation>(Env.getStorageLocation(*QuuxDecl));
3796           const auto &BazLoc =
3797               *cast<RecordStorageLocation>(QuuxLoc.getChild(*BazDecl));
3798 
3799           EXPECT_EQ(getFieldValue(&QuuxLoc, *BarDecl, Env), BarArgVal);
3800           EXPECT_EQ(getFieldValue(&BazLoc, *FooDecl, Env), FooArgVal);
3801           EXPECT_EQ(getFieldValue(&QuuxLoc, *QuxDecl, Env), QuxArgVal);
3802 
3803           // Check that fields initialized in an initializer list are always
3804           // modeled in other instances of the same type.
3805           const auto &OtherBLoc =
3806               getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "OtherB");
3807           EXPECT_THAT(OtherBLoc.getChild(*BarDecl), NotNull());
3808           EXPECT_THAT(OtherBLoc.getChild(*BazDecl), NotNull());
3809           EXPECT_THAT(OtherBLoc.getChild(*QuxDecl), NotNull());
3810         });
3811   }
3812 }
3813 
3814 TEST(TransferTest, AggregateInitializationReferenceField) {
3815   std::string Code = R"(
3816     struct S {
3817       int &RefField;
3818     };
3819 
3820     void target(int i) {
3821       S s = { i };
3822       /*[[p]]*/
3823     }
3824   )";
3825   runDataflow(
3826       Code,
3827       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3828          ASTContext &ASTCtx) {
3829         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3830 
3831         const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField");
3832 
3833         auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i");
3834         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3835 
3836         EXPECT_EQ(SLoc.getChild(*RefFieldDecl), &ILoc);
3837       });
3838 }
3839 
3840 TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) {
3841   std::string Code = R"(
3842     struct S {
3843       int i1;
3844       int i2;
3845     };
3846 
3847     void target(int i) {
3848       S s = { i };
3849       /*[[p]]*/
3850     }
3851   )";
3852   runDataflow(
3853       Code,
3854       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3855          ASTContext &ASTCtx) {
3856         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3857 
3858         const ValueDecl *I1FieldDecl = findValueDecl(ASTCtx, "i1");
3859         const ValueDecl *I2FieldDecl = findValueDecl(ASTCtx, "i2");
3860 
3861         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3862 
3863         auto &IValue = getValueForDecl<IntegerValue>(ASTCtx, Env, "i");
3864         auto &I1Value =
3865             *cast<IntegerValue>(getFieldValue(&SLoc, *I1FieldDecl, Env));
3866         EXPECT_EQ(&I1Value, &IValue);
3867         auto &I2Value =
3868             *cast<IntegerValue>(getFieldValue(&SLoc, *I2FieldDecl, Env));
3869         EXPECT_NE(&I2Value, &IValue);
3870       });
3871 }
3872 
3873 TEST(TransferTest, AggregateInitializationFunctionPointer) {
3874   // This is a repro for an assertion failure.
3875   // nullptr takes on the type of a const function pointer, but its type was
3876   // asserted to be equal to the *unqualified* type of Field, which no longer
3877   // included the const.
3878   std::string Code = R"(
3879     struct S {
3880       void (*const Field)();
3881     };
3882 
3883     void target() {
3884       S s{nullptr};
3885     }
3886   )";
3887   runDataflow(
3888       Code,
3889       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3890          ASTContext &ASTCtx) {});
3891 }
3892 
3893 TEST(TransferTest, AssignToUnionMember) {
3894   std::string Code = R"(
3895     union A {
3896       int Foo;
3897     };
3898 
3899     void target(int Bar) {
3900       A Baz;
3901       Baz.Foo = Bar;
3902       // [[p]]
3903     }
3904   )";
3905   runDataflow(
3906       Code,
3907       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3908          ASTContext &ASTCtx) {
3909         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3910         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3911 
3912         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3913         ASSERT_THAT(BazDecl, NotNull());
3914         ASSERT_TRUE(BazDecl->getType()->isUnionType());
3915 
3916         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
3917         FieldDecl *FooDecl = nullptr;
3918         for (FieldDecl *Field : BazFields) {
3919           if (Field->getNameAsString() == "Foo") {
3920             FooDecl = Field;
3921           } else {
3922             FAIL() << "Unexpected field: " << Field->getNameAsString();
3923           }
3924         }
3925         ASSERT_THAT(FooDecl, NotNull());
3926 
3927         const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>(
3928             Env.getStorageLocation(*BazDecl));
3929         ASSERT_THAT(BazLoc, NotNull());
3930 
3931         const auto *FooVal =
3932             cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env));
3933 
3934         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3935         ASSERT_THAT(BarDecl, NotNull());
3936         const auto *BarLoc = Env.getStorageLocation(*BarDecl);
3937         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3938 
3939         EXPECT_EQ(Env.getValue(*BarLoc), FooVal);
3940       });
3941 }
3942 
3943 TEST(TransferTest, AssignFromBoolLiteral) {
3944   std::string Code = R"(
3945     void target() {
3946       bool Foo = true;
3947       bool Bar = false;
3948       // [[p]]
3949     }
3950   )";
3951   runDataflow(
3952       Code,
3953       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3954          ASTContext &ASTCtx) {
3955         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3956         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3957 
3958         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3959         ASSERT_THAT(FooDecl, NotNull());
3960 
3961         const auto *FooVal =
3962             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3963         ASSERT_THAT(FooVal, NotNull());
3964 
3965         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3966         ASSERT_THAT(BarDecl, NotNull());
3967 
3968         const auto *BarVal =
3969             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3970         ASSERT_THAT(BarVal, NotNull());
3971 
3972         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
3973         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
3974       });
3975 }
3976 
3977 TEST(TransferTest, AssignFromCompositeBoolExpression) {
3978   {
3979     std::string Code = R"(
3980     void target(bool Foo, bool Bar, bool Qux) {
3981       bool Baz = (Foo) && (Bar || Qux);
3982       // [[p]]
3983     }
3984   )";
3985     runDataflow(
3986         Code,
3987         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3988            ASTContext &ASTCtx) {
3989           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3990           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3991 
3992           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3993           ASSERT_THAT(FooDecl, NotNull());
3994 
3995           const auto *FooVal =
3996               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3997           ASSERT_THAT(FooVal, NotNull());
3998 
3999           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4000           ASSERT_THAT(BarDecl, NotNull());
4001 
4002           const auto *BarVal =
4003               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4004           ASSERT_THAT(BarVal, NotNull());
4005 
4006           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4007           ASSERT_THAT(QuxDecl, NotNull());
4008 
4009           const auto *QuxVal =
4010               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
4011           ASSERT_THAT(QuxVal, NotNull());
4012 
4013           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4014           ASSERT_THAT(BazDecl, NotNull());
4015 
4016           const auto *BazVal =
4017               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
4018           ASSERT_THAT(BazVal, NotNull());
4019           auto &A = Env.arena();
4020           EXPECT_EQ(&BazVal->formula(),
4021                     &A.makeAnd(FooVal->formula(),
4022                                A.makeOr(BarVal->formula(), QuxVal->formula())));
4023         });
4024   }
4025 
4026   {
4027     std::string Code = R"(
4028     void target(bool Foo, bool Bar, bool Qux) {
4029       bool Baz = (Foo && Qux) || (Bar);
4030       // [[p]]
4031     }
4032   )";
4033     runDataflow(
4034         Code,
4035         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4036            ASTContext &ASTCtx) {
4037           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4038           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4039 
4040           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4041           ASSERT_THAT(FooDecl, NotNull());
4042 
4043           const auto *FooVal =
4044               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4045           ASSERT_THAT(FooVal, NotNull());
4046 
4047           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4048           ASSERT_THAT(BarDecl, NotNull());
4049 
4050           const auto *BarVal =
4051               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4052           ASSERT_THAT(BarVal, NotNull());
4053 
4054           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4055           ASSERT_THAT(QuxDecl, NotNull());
4056 
4057           const auto *QuxVal =
4058               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
4059           ASSERT_THAT(QuxVal, NotNull());
4060 
4061           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4062           ASSERT_THAT(BazDecl, NotNull());
4063 
4064           const auto *BazVal =
4065               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
4066           ASSERT_THAT(BazVal, NotNull());
4067           auto &A = Env.arena();
4068           EXPECT_EQ(&BazVal->formula(),
4069                     &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()),
4070                               BarVal->formula()));
4071         });
4072   }
4073 
4074   {
4075     std::string Code = R"(
4076       void target(bool A, bool B, bool C, bool D) {
4077         bool Foo = ((A && B) && C) && D;
4078         // [[p]]
4079       }
4080     )";
4081     runDataflow(
4082         Code,
4083         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4084            ASTContext &ASTCtx) {
4085           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4086           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4087 
4088           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
4089           ASSERT_THAT(ADecl, NotNull());
4090 
4091           const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl));
4092           ASSERT_THAT(AVal, NotNull());
4093 
4094           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4095           ASSERT_THAT(BDecl, NotNull());
4096 
4097           const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl));
4098           ASSERT_THAT(BVal, NotNull());
4099 
4100           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4101           ASSERT_THAT(CDecl, NotNull());
4102 
4103           const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl));
4104           ASSERT_THAT(CVal, NotNull());
4105 
4106           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
4107           ASSERT_THAT(DDecl, NotNull());
4108 
4109           const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl));
4110           ASSERT_THAT(DVal, NotNull());
4111 
4112           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4113           ASSERT_THAT(FooDecl, NotNull());
4114 
4115           const auto *FooVal =
4116               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4117           ASSERT_THAT(FooVal, NotNull());
4118           auto &A = Env.arena();
4119           EXPECT_EQ(
4120               &FooVal->formula(),
4121               &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()),
4122                                    CVal->formula()),
4123                          DVal->formula()));
4124         });
4125   }
4126 }
4127 
4128 TEST(TransferTest, AssignFromBoolNegation) {
4129   std::string Code = R"(
4130     void target() {
4131       bool Foo = true;
4132       bool Bar = !(Foo);
4133       // [[p]]
4134     }
4135   )";
4136   runDataflow(
4137       Code,
4138       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4139          ASTContext &ASTCtx) {
4140         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4141         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4142 
4143         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4144         ASSERT_THAT(FooDecl, NotNull());
4145 
4146         const auto *FooVal =
4147             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4148         ASSERT_THAT(FooVal, NotNull());
4149 
4150         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4151         ASSERT_THAT(BarDecl, NotNull());
4152 
4153         const auto *BarVal =
4154             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4155         ASSERT_THAT(BarVal, NotNull());
4156         auto &A = Env.arena();
4157         EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula()));
4158       });
4159 }
4160 
4161 TEST(TransferTest, BuiltinExpect) {
4162   std::string Code = R"(
4163     void target(long Foo) {
4164       long Bar = __builtin_expect(Foo, true);
4165       /*[[p]]*/
4166     }
4167   )";
4168   runDataflow(
4169       Code,
4170       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4171          ASTContext &ASTCtx) {
4172         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4173         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4174 
4175         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4176         ASSERT_THAT(FooDecl, NotNull());
4177 
4178         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4179         ASSERT_THAT(BarDecl, NotNull());
4180 
4181         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4182       });
4183 }
4184 
4185 // `__builtin_expect` takes and returns a `long` argument, so other types
4186 // involve casts. This verifies that we identify the input and output in that
4187 // case.
4188 TEST(TransferTest, BuiltinExpectBoolArg) {
4189   std::string Code = R"(
4190     void target(bool Foo) {
4191       bool Bar = __builtin_expect(Foo, true);
4192       /*[[p]]*/
4193     }
4194   )";
4195   runDataflow(
4196       Code,
4197       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4198          ASTContext &ASTCtx) {
4199         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4200         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4201 
4202         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4203         ASSERT_THAT(FooDecl, NotNull());
4204 
4205         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4206         ASSERT_THAT(BarDecl, NotNull());
4207 
4208         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4209       });
4210 }
4211 
4212 TEST(TransferTest, BuiltinUnreachable) {
4213   std::string Code = R"(
4214     void target(bool Foo) {
4215       bool Bar = false;
4216       if (Foo)
4217         Bar = Foo;
4218       else
4219         __builtin_unreachable();
4220       (void)0;
4221       /*[[p]]*/
4222     }
4223   )";
4224   runDataflow(
4225       Code,
4226       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4227          ASTContext &ASTCtx) {
4228         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4229         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4230 
4231         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4232         ASSERT_THAT(FooDecl, NotNull());
4233 
4234         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4235         ASSERT_THAT(BarDecl, NotNull());
4236 
4237         // `__builtin_unreachable` promises that the code is
4238         // unreachable, so the compiler treats the "then" branch as the
4239         // only possible predecessor of this statement.
4240         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4241       });
4242 }
4243 
4244 TEST(TransferTest, BuiltinTrap) {
4245   std::string Code = R"(
4246     void target(bool Foo) {
4247       bool Bar = false;
4248       if (Foo)
4249         Bar = Foo;
4250       else
4251         __builtin_trap();
4252       (void)0;
4253       /*[[p]]*/
4254     }
4255   )";
4256   runDataflow(
4257       Code,
4258       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4259          ASTContext &ASTCtx) {
4260         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4261         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4262 
4263         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4264         ASSERT_THAT(FooDecl, NotNull());
4265 
4266         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4267         ASSERT_THAT(BarDecl, NotNull());
4268 
4269         // `__builtin_trap` ensures program termination, so only the
4270         // "then" branch is a predecessor of this statement.
4271         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4272       });
4273 }
4274 
4275 TEST(TransferTest, BuiltinDebugTrap) {
4276   std::string Code = R"(
4277     void target(bool Foo) {
4278       bool Bar = false;
4279       if (Foo)
4280         Bar = Foo;
4281       else
4282         __builtin_debugtrap();
4283       (void)0;
4284       /*[[p]]*/
4285     }
4286   )";
4287   runDataflow(
4288       Code,
4289       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4290          ASTContext &ASTCtx) {
4291         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4292         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4293 
4294         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4295         ASSERT_THAT(FooDecl, NotNull());
4296 
4297         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4298         ASSERT_THAT(BarDecl, NotNull());
4299 
4300         // `__builtin_debugtrap` doesn't ensure program termination.
4301         EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4302       });
4303 }
4304 
4305 TEST(TransferTest, StaticIntSingleVarDecl) {
4306   std::string Code = R"(
4307     void target() {
4308       static int Foo;
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 StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
4323         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
4324 
4325         const Value *FooVal = Env.getValue(*FooLoc);
4326         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
4327       });
4328 }
4329 
4330 TEST(TransferTest, StaticIntGroupVarDecl) {
4331   std::string Code = R"(
4332     void target() {
4333       static int Foo, Bar;
4334       (void)0;
4335       // [[p]]
4336     }
4337   )";
4338   runDataflow(
4339       Code,
4340       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4341          ASTContext &ASTCtx) {
4342         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4343         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4344 
4345         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4346         ASSERT_THAT(FooDecl, NotNull());
4347 
4348         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4349         ASSERT_THAT(BarDecl, NotNull());
4350 
4351         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
4352         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
4353 
4354         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4355         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
4356 
4357         const Value *FooVal = Env.getValue(*FooLoc);
4358         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
4359 
4360         const Value *BarVal = Env.getValue(*BarLoc);
4361         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
4362 
4363         EXPECT_NE(FooVal, BarVal);
4364       });
4365 }
4366 
4367 TEST(TransferTest, GlobalIntVarDecl) {
4368   std::string Code = R"(
4369     static int Foo;
4370 
4371     void target() {
4372       int Bar = Foo;
4373       int Baz = Foo;
4374       // [[p]]
4375     }
4376   )";
4377   runDataflow(
4378       Code,
4379       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4380          ASTContext &ASTCtx) {
4381         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4382         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4383 
4384         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4385         ASSERT_THAT(BarDecl, NotNull());
4386 
4387         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4388         ASSERT_THAT(BazDecl, NotNull());
4389 
4390         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4391         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4392         EXPECT_EQ(BarVal, BazVal);
4393       });
4394 }
4395 
4396 TEST(TransferTest, StaticMemberIntVarDecl) {
4397   std::string Code = R"(
4398     struct A {
4399       static int Foo;
4400     };
4401 
4402     void target(A a) {
4403       int Bar = a.Foo;
4404       int Baz = a.Foo;
4405       // [[p]]
4406     }
4407   )";
4408   runDataflow(
4409       Code,
4410       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4411          ASTContext &ASTCtx) {
4412         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4413         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4414 
4415         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4416         ASSERT_THAT(BarDecl, NotNull());
4417 
4418         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4419         ASSERT_THAT(BazDecl, NotNull());
4420 
4421         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4422         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4423         EXPECT_EQ(BarVal, BazVal);
4424       });
4425 }
4426 
4427 TEST(TransferTest, StaticMemberRefVarDecl) {
4428   std::string Code = R"(
4429     struct A {
4430       static int &Foo;
4431     };
4432 
4433     void target(A a) {
4434       int Bar = a.Foo;
4435       int Baz = a.Foo;
4436       // [[p]]
4437     }
4438   )";
4439   runDataflow(
4440       Code,
4441       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4442          ASTContext &ASTCtx) {
4443         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4444         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4445 
4446         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4447         ASSERT_THAT(BarDecl, NotNull());
4448 
4449         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4450         ASSERT_THAT(BazDecl, NotNull());
4451 
4452         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4453         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4454         EXPECT_EQ(BarVal, BazVal);
4455       });
4456 }
4457 
4458 TEST(TransferTest, AssignMemberBeforeCopy) {
4459   std::string Code = R"(
4460     struct A {
4461       int Foo;
4462     };
4463 
4464     void target() {
4465       A A1;
4466       A A2;
4467       int Bar;
4468       A1.Foo = Bar;
4469       A2 = A1;
4470       // [[p]]
4471     }
4472   )";
4473   runDataflow(
4474       Code,
4475       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4476          ASTContext &ASTCtx) {
4477         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4478         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4479 
4480         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4481         ASSERT_THAT(FooDecl, NotNull());
4482 
4483         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4484         ASSERT_THAT(BarDecl, NotNull());
4485 
4486         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
4487         ASSERT_THAT(A1Decl, NotNull());
4488 
4489         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
4490         ASSERT_THAT(A2Decl, NotNull());
4491 
4492         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4493 
4494         const auto &A2Loc =
4495             *cast<RecordStorageLocation>(Env.getStorageLocation(*A2Decl));
4496         EXPECT_EQ(getFieldValue(&A2Loc, *FooDecl, Env), BarVal);
4497       });
4498 }
4499 
4500 TEST(TransferTest, BooleanEquality) {
4501   std::string Code = R"(
4502     void target(bool Bar) {
4503       bool Foo = true;
4504       if (Bar == Foo) {
4505         (void)0;
4506         /*[[p-then]]*/
4507       } else {
4508         (void)0;
4509         /*[[p-else]]*/
4510       }
4511     }
4512   )";
4513   runDataflow(
4514       Code,
4515       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4516          ASTContext &ASTCtx) {
4517         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4518         const Environment &EnvThen =
4519             getEnvironmentAtAnnotation(Results, "p-then");
4520         const Environment &EnvElse =
4521             getEnvironmentAtAnnotation(Results, "p-else");
4522 
4523         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4524         ASSERT_THAT(BarDecl, NotNull());
4525 
4526         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4527         EXPECT_TRUE(EnvThen.proves(BarValThen));
4528 
4529         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4530         EXPECT_TRUE(EnvElse.proves(EnvElse.arena().makeNot(BarValElse)));
4531       });
4532 }
4533 
4534 TEST(TransferTest, BooleanInequality) {
4535   std::string Code = R"(
4536     void target(bool Bar) {
4537       bool Foo = true;
4538       if (Bar != Foo) {
4539         (void)0;
4540         /*[[p-then]]*/
4541       } else {
4542         (void)0;
4543         /*[[p-else]]*/
4544       }
4545     }
4546   )";
4547   runDataflow(
4548       Code,
4549       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4550          ASTContext &ASTCtx) {
4551         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4552         const Environment &EnvThen =
4553             getEnvironmentAtAnnotation(Results, "p-then");
4554         const Environment &EnvElse =
4555             getEnvironmentAtAnnotation(Results, "p-else");
4556 
4557         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4558         ASSERT_THAT(BarDecl, NotNull());
4559 
4560         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4561         EXPECT_TRUE(EnvThen.proves(EnvThen.arena().makeNot(BarValThen)));
4562 
4563         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4564         EXPECT_TRUE(EnvElse.proves(BarValElse));
4565       });
4566 }
4567 
4568 TEST(TransferTest, IntegerLiteralEquality) {
4569   std::string Code = R"(
4570     void target() {
4571       bool equal = (42 == 42);
4572       // [[p]]
4573     }
4574   )";
4575   runDataflow(
4576       Code,
4577       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4578          ASTContext &ASTCtx) {
4579         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4580 
4581         auto &Equal =
4582             getValueForDecl<BoolValue>(ASTCtx, Env, "equal").formula();
4583         EXPECT_TRUE(Env.proves(Equal));
4584       });
4585 }
4586 
4587 TEST(TransferTest, CorrelatedBranches) {
4588   std::string Code = R"(
4589     void target(bool B, bool C) {
4590       if (B) {
4591         return;
4592       }
4593       (void)0;
4594       /*[[p0]]*/
4595       if (C) {
4596         B = true;
4597         /*[[p1]]*/
4598       }
4599       if (B) {
4600         (void)0;
4601         /*[[p2]]*/
4602       }
4603     }
4604   )";
4605   runDataflow(
4606       Code,
4607       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4608          ASTContext &ASTCtx) {
4609         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
4610 
4611         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4612         ASSERT_THAT(CDecl, NotNull());
4613 
4614         {
4615           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
4616           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4617           ASSERT_THAT(BDecl, NotNull());
4618           auto &BVal = getFormula(*BDecl, Env);
4619 
4620           EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal)));
4621         }
4622 
4623         {
4624           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
4625           auto &CVal = getFormula(*CDecl, Env);
4626           EXPECT_TRUE(Env.proves(CVal));
4627         }
4628 
4629         {
4630           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
4631           auto &CVal = getFormula(*CDecl, Env);
4632           EXPECT_TRUE(Env.proves(CVal));
4633         }
4634       });
4635 }
4636 
4637 TEST(TransferTest, LoopWithAssignmentConverges) {
4638   std::string Code = R"(
4639     bool foo();
4640 
4641     void target() {
4642        do {
4643         bool Bar = foo();
4644         if (Bar) break;
4645         (void)Bar;
4646         /*[[p]]*/
4647       } while (true);
4648     }
4649   )";
4650   // The key property that we are verifying is implicit in `runDataflow` --
4651   // namely, that the analysis succeeds, rather than hitting the maximum number
4652   // of iterations.
4653   runDataflow(
4654       Code,
4655       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4656          ASTContext &ASTCtx) {
4657         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4658         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4659 
4660         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4661         ASSERT_THAT(BarDecl, NotNull());
4662 
4663         auto &BarVal = getFormula(*BarDecl, Env);
4664         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4665       });
4666 }
4667 
4668 TEST(TransferTest, LoopWithStagedAssignments) {
4669   std::string Code = R"(
4670     bool foo();
4671 
4672     void target() {
4673       bool Bar = false;
4674       bool Err = false;
4675       while (foo()) {
4676         if (Bar)
4677           Err = true;
4678         Bar = true;
4679         /*[[p]]*/
4680       }
4681     }
4682   )";
4683   runDataflow(
4684       Code,
4685       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4686          ASTContext &ASTCtx) {
4687         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4688         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4689 
4690         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4691         ASSERT_THAT(BarDecl, NotNull());
4692         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
4693         ASSERT_THAT(ErrDecl, NotNull());
4694 
4695         auto &BarVal = getFormula(*BarDecl, Env);
4696         auto &ErrVal = getFormula(*ErrDecl, Env);
4697         EXPECT_TRUE(Env.proves(BarVal));
4698         // An unsound analysis, for example only evaluating the loop once, can
4699         // conclude that `Err` is false. So, we test that this conclusion is not
4700         // reached.
4701         EXPECT_FALSE(Env.proves(Env.arena().makeNot(ErrVal)));
4702       });
4703 }
4704 
4705 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
4706   std::string Code = R"(
4707     bool &foo();
4708 
4709     void target() {
4710        do {
4711         bool& Bar = foo();
4712         if (Bar) break;
4713         (void)Bar;
4714         /*[[p]]*/
4715       } while (true);
4716     }
4717   )";
4718   // The key property that we are verifying is that the analysis succeeds,
4719   // rather than hitting the maximum number of iterations.
4720   runDataflow(
4721       Code,
4722       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4723          ASTContext &ASTCtx) {
4724         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4725         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4726 
4727         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4728         ASSERT_THAT(BarDecl, NotNull());
4729 
4730         auto &BarVal = getFormula(*BarDecl, Env);
4731         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4732       });
4733 }
4734 
4735 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
4736   std::string Code = R"(
4737     struct Lookup {
4738       int x;
4739     };
4740 
4741     void target(Lookup val, bool b) {
4742       const Lookup* l = nullptr;
4743       while (b) {
4744         l = &val;
4745         /*[[p-inner]]*/
4746       }
4747       (void)0;
4748       /*[[p-outer]]*/
4749     }
4750   )";
4751   // The key property that we are verifying is implicit in `runDataflow` --
4752   // namely, that the analysis succeeds, rather than hitting the maximum number
4753   // of iterations.
4754   runDataflow(
4755       Code,
4756       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4757          ASTContext &ASTCtx) {
4758         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
4759         const Environment &InnerEnv =
4760             getEnvironmentAtAnnotation(Results, "p-inner");
4761         const Environment &OuterEnv =
4762             getEnvironmentAtAnnotation(Results, "p-outer");
4763 
4764         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
4765         ASSERT_THAT(ValDecl, NotNull());
4766 
4767         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
4768         ASSERT_THAT(LDecl, NotNull());
4769 
4770         // Inner.
4771         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
4772         ASSERT_THAT(LVal, NotNull());
4773 
4774         EXPECT_EQ(&LVal->getPointeeLoc(),
4775                   InnerEnv.getStorageLocation(*ValDecl));
4776 
4777         // Outer.
4778         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
4779         ASSERT_THAT(LVal, NotNull());
4780 
4781         // The loop body may not have been executed, so we should not conclude
4782         // that `l` points to `val`.
4783         EXPECT_NE(&LVal->getPointeeLoc(),
4784                   OuterEnv.getStorageLocation(*ValDecl));
4785       });
4786 }
4787 
4788 TEST(TransferTest, LoopDereferencingChangingPointerConverges) {
4789   std::string Code = R"cc(
4790     bool some_condition();
4791 
4792     void target(int i1, int i2) {
4793       int *p = &i1;
4794       while (true) {
4795         (void)*p;
4796         if (some_condition())
4797           p = &i1;
4798         else
4799           p = &i2;
4800       }
4801     }
4802   )cc";
4803   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4804 }
4805 
4806 TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
4807   std::string Code = R"cc(
4808     struct Lookup {
4809       int x;
4810     };
4811 
4812     bool some_condition();
4813 
4814     void target(Lookup l1, Lookup l2) {
4815       Lookup *l = &l1;
4816       while (true) {
4817         (void)l->x;
4818         if (some_condition())
4819           l = &l1;
4820         else
4821           l = &l2;
4822       }
4823     }
4824   )cc";
4825   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4826 }
4827 
4828 TEST(TransferTest, LoopWithShortCircuitedConditionConverges) {
4829   std::string Code = R"cc(
4830     bool foo();
4831 
4832     void target() {
4833       bool c = false;
4834       while (foo() || foo()) {
4835         c = true;
4836       }
4837     }
4838   )cc";
4839   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4840 }
4841 
4842 TEST(TransferTest, LoopCanProveInvariantForBoolean) {
4843   // Check that we can prove `b` is always false in the loop.
4844   // This test exercises the logic in `widenDistinctValues()` that preserves
4845   // information if the boolean can be proved to be either true or false in both
4846   // the previous and current iteration.
4847   std::string Code = R"cc(
4848     int return_int();
4849     void target() {
4850       bool b = return_int() == 0;
4851       if (b) return;
4852       while (true) {
4853         b;
4854         // [[p]]
4855         b = return_int() == 0;
4856         if (b) return;
4857       }
4858     }
4859   )cc";
4860   runDataflow(
4861       Code,
4862       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4863          ASTContext &ASTCtx) {
4864         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4865         auto &BVal = getValueForDecl<BoolValue>(ASTCtx, Env, "b");
4866         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal.formula())));
4867       });
4868 }
4869 
4870 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
4871   std::string Code = R"cc(
4872     union Union {
4873       int A;
4874       float B;
4875     };
4876 
4877     void foo() {
4878       Union A;
4879       Union B;
4880       A = B;
4881     }
4882   )cc";
4883   // This is a crash regression test when calling the transfer function on a
4884   // `CXXThisExpr` that refers to a union.
4885   runDataflow(
4886       Code,
4887       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
4888          ASTContext &) {},
4889       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
4890 }
4891 
4892 TEST(TransferTest, DoesNotCrashOnNullChildren) {
4893   std::string Code = (CoroutineLibrary + R"cc(
4894     task target() noexcept {
4895       co_return;
4896     }
4897   )cc")
4898                          .str();
4899   // This is a crash regression test when calling `AdornedCFG::build` on a
4900   // statement (in this case, the `CoroutineBodyStmt`) with null children.
4901   runDataflow(
4902       Code,
4903       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
4904          ASTContext &) {},
4905       LangStandard::lang_cxx20, /*ApplyBuiltinTransfer=*/true);
4906 }
4907 
4908 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
4909   std::string Code = R"(
4910     struct A {
4911       int Foo;
4912       int Bar;
4913     };
4914 
4915     void target() {
4916       int Qux;
4917       A Baz;
4918       Baz.Foo = Qux;
4919       auto &FooRef = Baz.Foo;
4920       auto &BarRef = Baz.Bar;
4921       auto &[BoundFooRef, BoundBarRef] = Baz;
4922       // [[p]]
4923     }
4924   )";
4925   runDataflow(
4926       Code,
4927       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4928          ASTContext &ASTCtx) {
4929         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4930         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4931 
4932         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4933         ASSERT_THAT(FooRefDecl, NotNull());
4934 
4935         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4936         ASSERT_THAT(BarRefDecl, NotNull());
4937 
4938         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4939         ASSERT_THAT(QuxDecl, NotNull());
4940 
4941         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4942         ASSERT_THAT(BoundFooRefDecl, NotNull());
4943 
4944         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4945         ASSERT_THAT(BoundBarRefDecl, NotNull());
4946 
4947         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4948         ASSERT_THAT(FooRefLoc, NotNull());
4949 
4950         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4951         ASSERT_THAT(BarRefLoc, NotNull());
4952 
4953         const Value *QuxVal = Env.getValue(*QuxDecl);
4954         ASSERT_THAT(QuxVal, NotNull());
4955 
4956         const StorageLocation *BoundFooRefLoc =
4957             Env.getStorageLocation(*BoundFooRefDecl);
4958         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4959 
4960         const StorageLocation *BoundBarRefLoc =
4961             Env.getStorageLocation(*BoundBarRefDecl);
4962         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4963 
4964         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4965       });
4966 }
4967 
4968 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
4969   std::string Code = R"(
4970     struct A {
4971       int &Foo;
4972       int &Bar;
4973     };
4974 
4975     void target(A Baz) {
4976       int Qux;
4977       Baz.Foo = Qux;
4978       auto &FooRef = Baz.Foo;
4979       auto &BarRef = Baz.Bar;
4980       auto &[BoundFooRef, BoundBarRef] = Baz;
4981       // [[p]]
4982     }
4983   )";
4984   runDataflow(
4985       Code,
4986       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4987          ASTContext &ASTCtx) {
4988         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4989         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4990 
4991         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4992         ASSERT_THAT(FooRefDecl, NotNull());
4993 
4994         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4995         ASSERT_THAT(BarRefDecl, NotNull());
4996 
4997         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4998         ASSERT_THAT(QuxDecl, NotNull());
4999 
5000         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
5001         ASSERT_THAT(BoundFooRefDecl, NotNull());
5002 
5003         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
5004         ASSERT_THAT(BoundBarRefDecl, NotNull());
5005 
5006         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
5007         ASSERT_THAT(FooRefLoc, NotNull());
5008 
5009         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
5010         ASSERT_THAT(BarRefLoc, NotNull());
5011 
5012         const Value *QuxVal = Env.getValue(*QuxDecl);
5013         ASSERT_THAT(QuxVal, NotNull());
5014 
5015         const StorageLocation *BoundFooRefLoc =
5016             Env.getStorageLocation(*BoundFooRefDecl);
5017         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
5018 
5019         const StorageLocation *BoundBarRefLoc =
5020             Env.getStorageLocation(*BoundBarRefDecl);
5021         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
5022 
5023         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
5024       });
5025 }
5026 
5027 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
5028   std::string Code = R"(
5029     struct A {
5030       int Foo;
5031       int Bar;
5032     };
5033 
5034     void target() {
5035       int Qux;
5036       A Baz;
5037       Baz.Foo = Qux;
5038       auto &FooRef = Baz.Foo;
5039       auto &BarRef = Baz.Bar;
5040       auto [BoundFoo, BoundBar] = Baz;
5041       // [[p]]
5042     }
5043   )";
5044   runDataflow(
5045       Code,
5046       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5047          ASTContext &ASTCtx) {
5048         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5049         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5050 
5051         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
5052         ASSERT_THAT(FooRefDecl, NotNull());
5053 
5054         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
5055         ASSERT_THAT(BarRefDecl, NotNull());
5056 
5057         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5058         ASSERT_THAT(BoundFooDecl, NotNull());
5059 
5060         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5061         ASSERT_THAT(BoundBarDecl, NotNull());
5062 
5063         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
5064         ASSERT_THAT(QuxDecl, NotNull());
5065 
5066         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
5067         ASSERT_THAT(FooRefLoc, NotNull());
5068 
5069         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
5070         ASSERT_THAT(BarRefLoc, NotNull());
5071 
5072         const Value *QuxVal = Env.getValue(*QuxDecl);
5073         ASSERT_THAT(QuxVal, NotNull());
5074 
5075         const StorageLocation *BoundFooLoc =
5076             Env.getStorageLocation(*BoundFooDecl);
5077         EXPECT_NE(BoundFooLoc, FooRefLoc);
5078 
5079         const StorageLocation *BoundBarLoc =
5080             Env.getStorageLocation(*BoundBarDecl);
5081         EXPECT_NE(BoundBarLoc, BarRefLoc);
5082 
5083         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
5084       });
5085 }
5086 
5087 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
5088   std::string Code = R"(
5089     namespace std {
5090     using size_t = int;
5091     template <class> struct tuple_size;
5092     template <std::size_t, class> struct tuple_element;
5093     template <class...> class tuple;
5094 
5095     namespace {
5096     template <class T, T v>
5097     struct size_helper { static const T value = v; };
5098     } // namespace
5099 
5100     template <class... T>
5101     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
5102 
5103     template <std::size_t I, class... T>
5104     struct tuple_element<I, tuple<T...>> {
5105       using type =  __type_pack_element<I, T...>;
5106     };
5107 
5108     template <class...> class tuple {};
5109 
5110     template <std::size_t I, class... T>
5111     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
5112     } // namespace std
5113 
5114     std::tuple<bool, int> makeTuple();
5115 
5116     void target(bool B) {
5117       auto [BoundFoo, BoundBar] = makeTuple();
5118       bool Baz;
5119       // Include if-then-else to test interaction of `BindingDecl` with join.
5120       if (B) {
5121         Baz = BoundFoo;
5122         (void)BoundBar;
5123         // [[p1]]
5124       } else {
5125         Baz = BoundFoo;
5126       }
5127       (void)0;
5128       // [[p2]]
5129     }
5130   )";
5131   runDataflow(
5132       Code,
5133       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5134          ASTContext &ASTCtx) {
5135         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
5136         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
5137 
5138         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5139         ASSERT_THAT(BoundFooDecl, NotNull());
5140 
5141         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5142         ASSERT_THAT(BoundBarDecl, NotNull());
5143 
5144         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5145         ASSERT_THAT(BazDecl, NotNull());
5146 
5147         // BindingDecls always map to references -- either lvalue or rvalue, so
5148         // we still need to skip here.
5149         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
5150         ASSERT_THAT(BoundFooValue, NotNull());
5151         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
5152 
5153         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
5154         ASSERT_THAT(BoundBarValue, NotNull());
5155         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
5156 
5157         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
5158         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
5159 
5160         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
5161 
5162         // Test that `BoundFooDecl` retains the value we expect, after the join.
5163         BoundFooValue = Env2.getValue(*BoundFooDecl);
5164         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
5165       });
5166 }
5167 
5168 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
5169   std::string Code = R"(
5170     namespace std {
5171     using size_t = int;
5172     template <class> struct tuple_size;
5173     template <std::size_t, class> struct tuple_element;
5174     template <class...> class tuple;
5175 
5176     namespace {
5177     template <class T, T v>
5178     struct size_helper { static const T value = v; };
5179     } // namespace
5180 
5181     template <class... T>
5182     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
5183 
5184     template <std::size_t I, class... T>
5185     struct tuple_element<I, tuple<T...>> {
5186       using type =  __type_pack_element<I, T...>;
5187     };
5188 
5189     template <class...> class tuple {};
5190 
5191     template <std::size_t I, class... T>
5192     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
5193     } // namespace std
5194 
5195     std::tuple<bool, int> &getTuple();
5196 
5197     void target(bool B) {
5198       auto &[BoundFoo, BoundBar] = getTuple();
5199       bool Baz;
5200       // Include if-then-else to test interaction of `BindingDecl` with join.
5201       if (B) {
5202         Baz = BoundFoo;
5203         (void)BoundBar;
5204         // [[p1]]
5205       } else {
5206         Baz = BoundFoo;
5207       }
5208       (void)0;
5209       // [[p2]]
5210     }
5211   )";
5212   runDataflow(
5213       Code,
5214       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5215          ASTContext &ASTCtx) {
5216         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
5217         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
5218 
5219         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5220         ASSERT_THAT(BoundFooDecl, NotNull());
5221 
5222         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5223         ASSERT_THAT(BoundBarDecl, NotNull());
5224 
5225         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5226         ASSERT_THAT(BazDecl, NotNull());
5227 
5228         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
5229         ASSERT_THAT(BoundFooValue, NotNull());
5230         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
5231 
5232         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
5233         ASSERT_THAT(BoundBarValue, NotNull());
5234         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
5235 
5236         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
5237         // works as expected. We don't test aliasing properties of the
5238         // reference, because we don't model `std::get` and so have no way to
5239         // equate separate references into the tuple.
5240         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
5241 
5242         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
5243 
5244         // Test that `BoundFooDecl` retains the value we expect, after the join.
5245         BoundFooValue = Env2.getValue(*BoundFooDecl);
5246         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
5247       });
5248 }
5249 
5250 TEST(TransferTest, BinaryOperatorComma) {
5251   std::string Code = R"(
5252     void target(int Foo, int Bar) {
5253       int &Baz = (Foo, Bar);
5254       // [[p]]
5255     }
5256   )";
5257   runDataflow(
5258       Code,
5259       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5260          ASTContext &ASTCtx) {
5261         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5262         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5263 
5264         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5265         ASSERT_THAT(BarDecl, NotNull());
5266 
5267         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5268         ASSERT_THAT(BazDecl, NotNull());
5269 
5270         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
5271         ASSERT_THAT(BarLoc, NotNull());
5272 
5273         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
5274         EXPECT_EQ(BazLoc, BarLoc);
5275       });
5276 }
5277 
5278 TEST(TransferTest, ConditionalOperatorValue) {
5279   std::string Code = R"(
5280     void target(bool Cond, bool B1, bool B2) {
5281       bool JoinSame = Cond ? B1 : B1;
5282       bool JoinDifferent = Cond ? B1 : B2;
5283       // [[p]]
5284     }
5285   )";
5286   runDataflow(
5287       Code,
5288       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5289          ASTContext &ASTCtx) {
5290         Environment Env = getEnvironmentAtAnnotation(Results, "p").fork();
5291 
5292         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "B1");
5293         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "B2");
5294         auto &JoinSame = getValueForDecl<BoolValue>(ASTCtx, Env, "JoinSame");
5295         auto &JoinDifferent =
5296             getValueForDecl<BoolValue>(ASTCtx, Env, "JoinDifferent");
5297 
5298         EXPECT_EQ(&JoinSame, &B1);
5299 
5300         const Formula &JoinDifferentEqB1 =
5301             Env.arena().makeEquals(JoinDifferent.formula(), B1.formula());
5302         EXPECT_TRUE(Env.allows(JoinDifferentEqB1));
5303         EXPECT_FALSE(Env.proves(JoinDifferentEqB1));
5304 
5305         const Formula &JoinDifferentEqB2 =
5306             Env.arena().makeEquals(JoinDifferent.formula(), B2.formula());
5307         EXPECT_TRUE(Env.allows(JoinDifferentEqB2));
5308         EXPECT_FALSE(Env.proves(JoinDifferentEqB1));
5309       });
5310 }
5311 
5312 TEST(TransferTest, ConditionalOperatorLocation) {
5313   std::string Code = R"(
5314     void target(bool Cond, int I1, int I2) {
5315       int &JoinSame = Cond ? I1 : I1;
5316       int &JoinDifferent = Cond ? I1 : I2;
5317       // [[p]]
5318     }
5319   )";
5320   runDataflow(
5321       Code,
5322       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5323          ASTContext &ASTCtx) {
5324         Environment Env = getEnvironmentAtAnnotation(Results, "p").fork();
5325 
5326         StorageLocation &I1 = getLocForDecl(ASTCtx, Env, "I1");
5327         StorageLocation &I2 = getLocForDecl(ASTCtx, Env, "I2");
5328         StorageLocation &JoinSame = getLocForDecl(ASTCtx, Env, "JoinSame");
5329         StorageLocation &JoinDifferent =
5330             getLocForDecl(ASTCtx, Env, "JoinDifferent");
5331 
5332         EXPECT_EQ(&JoinSame, &I1);
5333 
5334         EXPECT_NE(&JoinDifferent, &I1);
5335         EXPECT_NE(&JoinDifferent, &I2);
5336       });
5337 }
5338 
5339 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
5340   std::string Code = R"(
5341     void target(bool Foo) {
5342       if (Foo) {
5343         (void)0;
5344         // [[if_then]]
5345       } else {
5346         (void)0;
5347         // [[if_else]]
5348       }
5349     }
5350   )";
5351   runDataflow(
5352       Code,
5353       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5354          ASTContext &ASTCtx) {
5355         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
5356         const Environment &ThenEnv =
5357             getEnvironmentAtAnnotation(Results, "if_then");
5358         const Environment &ElseEnv =
5359             getEnvironmentAtAnnotation(Results, "if_else");
5360 
5361         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5362         ASSERT_THAT(FooDecl, NotNull());
5363 
5364         auto &ThenFooVal= getFormula(*FooDecl, ThenEnv);
5365         EXPECT_TRUE(ThenEnv.proves(ThenFooVal));
5366 
5367         auto &ElseFooVal = getFormula(*FooDecl, ElseEnv);
5368         EXPECT_TRUE(ElseEnv.proves(ElseEnv.arena().makeNot(ElseFooVal)));
5369       });
5370 }
5371 
5372 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
5373   std::string Code = R"(
5374     void target(bool Foo) {
5375       while (Foo) {
5376         (void)0;
5377         // [[loop_body]]
5378       }
5379       (void)0;
5380       // [[after_loop]]
5381     }
5382   )";
5383   runDataflow(
5384       Code,
5385       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5386          ASTContext &ASTCtx) {
5387         ASSERT_THAT(Results.keys(),
5388                     UnorderedElementsAre("loop_body", "after_loop"));
5389         const Environment &LoopBodyEnv =
5390             getEnvironmentAtAnnotation(Results, "loop_body");
5391         const Environment &AfterLoopEnv =
5392             getEnvironmentAtAnnotation(Results, "after_loop");
5393 
5394         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5395         ASSERT_THAT(FooDecl, NotNull());
5396 
5397         auto &LoopBodyFooVal = getFormula(*FooDecl, LoopBodyEnv);
5398         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
5399 
5400         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5401         EXPECT_TRUE(
5402             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
5403       });
5404 }
5405 
5406 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
5407   std::string Code = R"(
5408     void target(bool Foo) {
5409       bool Bar = true;
5410       do {
5411         (void)0;
5412         // [[loop_body]]
5413         Bar = false;
5414       } while (Foo);
5415       (void)0;
5416       // [[after_loop]]
5417     }
5418   )";
5419   runDataflow(
5420       Code,
5421       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5422          ASTContext &ASTCtx) {
5423         ASSERT_THAT(Results.keys(),
5424                     UnorderedElementsAre("loop_body", "after_loop"));
5425         const Environment &LoopBodyEnv =
5426             getEnvironmentAtAnnotation(Results, "loop_body");
5427         const Environment &AfterLoopEnv =
5428             getEnvironmentAtAnnotation(Results, "after_loop");
5429         auto &A = AfterLoopEnv.arena();
5430 
5431         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5432         ASSERT_THAT(FooDecl, NotNull());
5433 
5434         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5435         ASSERT_THAT(BarDecl, NotNull());
5436 
5437         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5438         auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv);
5439         EXPECT_TRUE(
5440             LoopBodyEnv.proves(A.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
5441 
5442         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5443         auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv);
5444         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopFooVal)));
5445         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopBarVal)));
5446       });
5447 }
5448 
5449 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
5450   std::string Code = R"(
5451     void target(bool Foo) {
5452       for (; Foo;) {
5453         (void)0;
5454         // [[loop_body]]
5455       }
5456       (void)0;
5457       // [[after_loop]]
5458     }
5459   )";
5460   runDataflow(
5461       Code,
5462       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5463          ASTContext &ASTCtx) {
5464         ASSERT_THAT(Results.keys(),
5465                     UnorderedElementsAre("loop_body", "after_loop"));
5466         const Environment &LoopBodyEnv =
5467             getEnvironmentAtAnnotation(Results, "loop_body");
5468         const Environment &AfterLoopEnv =
5469             getEnvironmentAtAnnotation(Results, "after_loop");
5470 
5471         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5472         ASSERT_THAT(FooDecl, NotNull());
5473 
5474         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5475         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
5476 
5477         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5478         EXPECT_TRUE(
5479             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
5480       });
5481 }
5482 
5483 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
5484   std::string Code = R"(
5485     void target(bool Foo) {
5486       for (;;) {
5487         (void)0;
5488         // [[loop_body]]
5489       }
5490     }
5491   )";
5492   runDataflow(
5493       Code,
5494       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5495          ASTContext &ASTCtx) {
5496         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
5497         const Environment &LoopBodyEnv =
5498             getEnvironmentAtAnnotation(Results, "loop_body");
5499 
5500         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5501         ASSERT_THAT(FooDecl, NotNull());
5502 
5503         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5504         EXPECT_FALSE(LoopBodyEnv.proves(LoopBodyFooVal));
5505       });
5506 }
5507 
5508 TEST(TransferTest, ContextSensitiveOptionDisabled) {
5509   std::string Code = R"(
5510     bool GiveBool();
5511     void SetBool(bool &Var) { Var = true; }
5512 
5513     void target() {
5514       bool Foo = GiveBool();
5515       SetBool(Foo);
5516       // [[p]]
5517     }
5518   )";
5519   runDataflow(
5520       Code,
5521       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5522          ASTContext &ASTCtx) {
5523         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5524         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5525 
5526         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5527         ASSERT_THAT(FooDecl, NotNull());
5528 
5529         auto &FooVal = getFormula(*FooDecl, Env);
5530         EXPECT_FALSE(Env.proves(FooVal));
5531         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5532       },
5533       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
5534 }
5535 
5536 TEST(TransferTest, ContextSensitiveReturnReference) {
5537   std::string Code = R"(
5538     class S {};
5539     S& target(bool b, S &s) {
5540       return s;
5541       // [[p]]
5542     }
5543   )";
5544   runDataflow(
5545       Code,
5546       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5547          ASTContext &ASTCtx) {
5548         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5549 
5550         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5551         ASSERT_THAT(SDecl, NotNull());
5552 
5553         auto *SLoc = Env.getStorageLocation(*SDecl);
5554         ASSERT_THAT(SLoc, NotNull());
5555 
5556         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
5557       },
5558       {BuiltinOptions{ContextSensitiveOptions{}}});
5559 }
5560 
5561 // This test is a regression test, based on a real crash.
5562 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
5563   std::string Code = R"(
5564     class S {};
5565     S& target(bool b, S &s) {
5566       return b ? s : s;
5567       // [[p]]
5568     }
5569   )";
5570   runDataflow(
5571       Code,
5572       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5573          ASTContext &ASTCtx) {
5574         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5575         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5576 
5577         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5578         ASSERT_THAT(SDecl, NotNull());
5579 
5580         auto *SLoc = Env.getStorageLocation(*SDecl);
5581         EXPECT_THAT(SLoc, NotNull());
5582 
5583         auto *Loc = Env.getReturnStorageLocation();
5584         EXPECT_THAT(Loc, NotNull());
5585 
5586         EXPECT_EQ(Loc, SLoc);
5587       },
5588       {BuiltinOptions{ContextSensitiveOptions{}}});
5589 }
5590 
5591 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
5592   std::string Code = R"(
5593     class S {};
5594     S &callee(bool b, S &s1_parm, S &s2_parm) {
5595       if (b)
5596         return s1_parm;
5597       else
5598         return s2_parm;
5599     }
5600     void target(bool b) {
5601       S s1;
5602       S s2;
5603       S &return_s1 = s1;
5604       S &return_s2 = s2;
5605       S &return_dont_know = callee(b, s1, s2);
5606       // [[p]]
5607     }
5608   )";
5609   runDataflow(
5610       Code,
5611       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5612          ASTContext &ASTCtx) {
5613         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5614 
5615         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
5616         ASSERT_THAT(S1, NotNull());
5617         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
5618         ASSERT_THAT(S2, NotNull());
5619         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
5620         ASSERT_THAT(ReturnS1, NotNull());
5621         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
5622         ASSERT_THAT(ReturnS2, NotNull());
5623         const ValueDecl *ReturnDontKnow =
5624             findValueDecl(ASTCtx, "return_dont_know");
5625         ASSERT_THAT(ReturnDontKnow, NotNull());
5626 
5627         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
5628         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
5629 
5630         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
5631         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
5632 
5633         // In the case where we don't have a consistent storage location for
5634         // the return value, the framework creates a new storage location, which
5635         // should be different from the storage locations of `s1` and `s2`.
5636         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
5637         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
5638       },
5639       {BuiltinOptions{ContextSensitiveOptions{}}});
5640 }
5641 
5642 TEST(TransferTest, ContextSensitiveDepthZero) {
5643   std::string Code = R"(
5644     bool GiveBool();
5645     void SetBool(bool &Var) { Var = true; }
5646 
5647     void target() {
5648       bool Foo = GiveBool();
5649       SetBool(Foo);
5650       // [[p]]
5651     }
5652   )";
5653   runDataflow(
5654       Code,
5655       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5656          ASTContext &ASTCtx) {
5657         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5658         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5659 
5660         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5661         ASSERT_THAT(FooDecl, NotNull());
5662 
5663         auto &FooVal = getFormula(*FooDecl, Env);
5664         EXPECT_FALSE(Env.proves(FooVal));
5665         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5666       },
5667       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
5668 }
5669 
5670 TEST(TransferTest, ContextSensitiveSetTrue) {
5671   std::string Code = R"(
5672     bool GiveBool();
5673     void SetBool(bool &Var) { Var = true; }
5674 
5675     void target() {
5676       bool Foo = GiveBool();
5677       SetBool(Foo);
5678       // [[p]]
5679     }
5680   )";
5681   runDataflow(
5682       Code,
5683       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5684          ASTContext &ASTCtx) {
5685         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5686         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5687 
5688         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5689         ASSERT_THAT(FooDecl, NotNull());
5690 
5691         auto &FooVal = getFormula(*FooDecl, Env);
5692         EXPECT_TRUE(Env.proves(FooVal));
5693       },
5694       {BuiltinOptions{ContextSensitiveOptions{}}});
5695 }
5696 
5697 TEST(TransferTest, ContextSensitiveSetFalse) {
5698   std::string Code = R"(
5699     bool GiveBool();
5700     void SetBool(bool &Var) { Var = false; }
5701 
5702     void target() {
5703       bool Foo = GiveBool();
5704       SetBool(Foo);
5705       // [[p]]
5706     }
5707   )";
5708   runDataflow(
5709       Code,
5710       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5711          ASTContext &ASTCtx) {
5712         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5713         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5714 
5715         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5716         ASSERT_THAT(FooDecl, NotNull());
5717 
5718         auto &FooVal = getFormula(*FooDecl, Env);
5719         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
5720       },
5721       {BuiltinOptions{ContextSensitiveOptions{}}});
5722 }
5723 
5724 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
5725   std::string Code = R"(
5726     bool GiveBool();
5727     void SetBool(bool &Var, bool Val) { Var = Val; }
5728 
5729     void target() {
5730       bool Foo = GiveBool();
5731       bool Bar = GiveBool();
5732       SetBool(Foo, true);
5733       SetBool(Bar, false);
5734       // [[p]]
5735     }
5736   )";
5737   runDataflow(
5738       Code,
5739       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5740          ASTContext &ASTCtx) {
5741         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5742         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5743         auto &A = Env.arena();
5744 
5745         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5746         ASSERT_THAT(FooDecl, NotNull());
5747 
5748         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5749         ASSERT_THAT(BarDecl, NotNull());
5750 
5751         auto &FooVal = getFormula(*FooDecl, Env);
5752         EXPECT_TRUE(Env.proves(FooVal));
5753         EXPECT_FALSE(Env.proves(A.makeNot(FooVal)));
5754 
5755         auto &BarVal = getFormula(*BarDecl, Env);
5756         EXPECT_FALSE(Env.proves(BarVal));
5757         EXPECT_TRUE(Env.proves(A.makeNot(BarVal)));
5758       },
5759       {BuiltinOptions{ContextSensitiveOptions{}}});
5760 }
5761 
5762 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
5763   std::string Code = R"(
5764     bool GiveBool();
5765     void SetBool1(bool &Var) { Var = true; }
5766     void SetBool2(bool &Var) { SetBool1(Var); }
5767 
5768     void target() {
5769       bool Foo = GiveBool();
5770       SetBool2(Foo);
5771       // [[p]]
5772     }
5773   )";
5774   runDataflow(
5775       Code,
5776       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5777          ASTContext &ASTCtx) {
5778         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5779         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5780 
5781         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5782         ASSERT_THAT(FooDecl, NotNull());
5783 
5784         auto &FooVal = getFormula(*FooDecl, Env);
5785         EXPECT_FALSE(Env.proves(FooVal));
5786         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5787       },
5788       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
5789 }
5790 
5791 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
5792   std::string Code = R"(
5793     bool GiveBool();
5794     void SetBool1(bool &Var) { Var = true; }
5795     void SetBool2(bool &Var) { SetBool1(Var); }
5796 
5797     void target() {
5798       bool Foo = GiveBool();
5799       SetBool2(Foo);
5800       // [[p]]
5801     }
5802   )";
5803   runDataflow(
5804       Code,
5805       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5806          ASTContext &ASTCtx) {
5807         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5808         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5809 
5810         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5811         ASSERT_THAT(FooDecl, NotNull());
5812 
5813         auto &FooVal = getFormula(*FooDecl, Env);
5814         EXPECT_TRUE(Env.proves(FooVal));
5815       },
5816       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5817 }
5818 
5819 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
5820   std::string Code = R"(
5821     bool GiveBool();
5822     void SetBool1(bool &Var) { Var = true; }
5823     void SetBool2(bool &Var) { SetBool1(Var); }
5824     void SetBool3(bool &Var) { SetBool2(Var); }
5825 
5826     void target() {
5827       bool Foo = GiveBool();
5828       SetBool3(Foo);
5829       // [[p]]
5830     }
5831   )";
5832   runDataflow(
5833       Code,
5834       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5835          ASTContext &ASTCtx) {
5836         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5837         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5838 
5839         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5840         ASSERT_THAT(FooDecl, NotNull());
5841 
5842         auto &FooVal = getFormula(*FooDecl, Env);
5843         EXPECT_FALSE(Env.proves(FooVal));
5844         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5845       },
5846       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5847 }
5848 
5849 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
5850   std::string Code = R"(
5851     bool GiveBool();
5852     void SetBool1(bool &Var) { Var = true; }
5853     void SetBool2(bool &Var) { SetBool1(Var); }
5854     void SetBool3(bool &Var) { SetBool2(Var); }
5855 
5856     void target() {
5857       bool Foo = GiveBool();
5858       SetBool3(Foo);
5859       // [[p]]
5860     }
5861   )";
5862   runDataflow(
5863       Code,
5864       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5865          ASTContext &ASTCtx) {
5866         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5867         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5868 
5869         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5870         ASSERT_THAT(FooDecl, NotNull());
5871 
5872         auto &FooVal = getFormula(*FooDecl, Env);
5873         EXPECT_TRUE(Env.proves(FooVal));
5874       },
5875       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
5876 }
5877 
5878 TEST(TransferTest, ContextSensitiveMutualRecursion) {
5879   std::string Code = R"(
5880     bool Pong(bool X, bool Y);
5881 
5882     bool Ping(bool X, bool Y) {
5883       if (X) {
5884         return Y;
5885       } else {
5886         return Pong(!X, Y);
5887       }
5888     }
5889 
5890     bool Pong(bool X, bool Y) {
5891       if (Y) {
5892         return X;
5893       } else {
5894         return Ping(X, !Y);
5895       }
5896     }
5897 
5898     void target() {
5899       bool Foo = Ping(false, false);
5900       // [[p]]
5901     }
5902   )";
5903   runDataflow(
5904       Code,
5905       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5906          ASTContext &ASTCtx) {
5907         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5908         // The analysis doesn't crash...
5909         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5910 
5911         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5912         ASSERT_THAT(FooDecl, NotNull());
5913 
5914         auto &FooVal = getFormula(*FooDecl, Env);
5915         // ... but it also can't prove anything here.
5916         EXPECT_FALSE(Env.proves(FooVal));
5917         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5918       },
5919       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
5920 }
5921 
5922 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
5923   std::string Code = R"(
5924     void SetBools(bool &Var1, bool &Var2) {
5925       Var1 = true;
5926       Var2 = false;
5927     }
5928 
5929     void target() {
5930       bool Foo = false;
5931       bool Bar = true;
5932       SetBools(Foo, Bar);
5933       // [[p]]
5934     }
5935   )";
5936   runDataflow(
5937       Code,
5938       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5939          ASTContext &ASTCtx) {
5940         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5941         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5942 
5943         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5944         ASSERT_THAT(FooDecl, NotNull());
5945 
5946         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5947         ASSERT_THAT(BarDecl, NotNull());
5948 
5949         auto &FooVal = getFormula(*FooDecl, Env);
5950         EXPECT_TRUE(Env.proves(FooVal));
5951         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5952 
5953         auto &BarVal = getFormula(*BarDecl, Env);
5954         EXPECT_FALSE(Env.proves(BarVal));
5955         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5956       },
5957       {BuiltinOptions{ContextSensitiveOptions{}}});
5958 }
5959 
5960 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
5961   std::string Code = R"(
5962     void IfCond(bool Cond, bool &Then, bool &Else) {
5963       if (Cond) {
5964         Then = true;
5965       } else {
5966         Else = true;
5967       }
5968     }
5969 
5970     void target() {
5971       bool Foo = false;
5972       bool Bar = false;
5973       bool Baz = false;
5974       IfCond(Foo, Bar, Baz);
5975       // [[p]]
5976     }
5977   )";
5978   runDataflow(
5979       Code,
5980       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5981          ASTContext &ASTCtx) {
5982         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5983         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5984 
5985         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5986         ASSERT_THAT(BarDecl, NotNull());
5987 
5988         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5989         ASSERT_THAT(BazDecl, NotNull());
5990 
5991         auto &BarVal = getFormula(*BarDecl, Env);
5992         EXPECT_FALSE(Env.proves(BarVal));
5993         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5994 
5995         auto &BazVal = getFormula(*BazDecl, Env);
5996         EXPECT_TRUE(Env.proves(BazVal));
5997         EXPECT_FALSE(Env.proves(Env.arena().makeNot(BazVal)));
5998       },
5999       {BuiltinOptions{ContextSensitiveOptions{}}});
6000 }
6001 
6002 TEST(TransferTest, ContextSensitiveReturnVoid) {
6003   std::string Code = R"(
6004     void Noop() { return; }
6005 
6006     void target() {
6007       Noop();
6008       // [[p]]
6009     }
6010   )";
6011   runDataflow(
6012       Code,
6013       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6014          ASTContext &ASTCtx) {
6015         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6016         // This just tests that the analysis doesn't crash.
6017       },
6018       {BuiltinOptions{ContextSensitiveOptions{}}});
6019 }
6020 
6021 TEST(TransferTest, ContextSensitiveReturnTrue) {
6022   std::string Code = R"(
6023     bool GiveBool() { return true; }
6024 
6025     void target() {
6026       bool Foo = GiveBool();
6027       // [[p]]
6028     }
6029   )";
6030   runDataflow(
6031       Code,
6032       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6033          ASTContext &ASTCtx) {
6034         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6035         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6036 
6037         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6038         ASSERT_THAT(FooDecl, NotNull());
6039 
6040         auto &FooVal = getFormula(*FooDecl, Env);
6041         EXPECT_TRUE(Env.proves(FooVal));
6042       },
6043       {BuiltinOptions{ContextSensitiveOptions{}}});
6044 }
6045 
6046 TEST(TransferTest, ContextSensitiveReturnFalse) {
6047   std::string Code = R"(
6048     bool GiveBool() { return false; }
6049 
6050     void target() {
6051       bool Foo = GiveBool();
6052       // [[p]]
6053     }
6054   )";
6055   runDataflow(
6056       Code,
6057       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6058          ASTContext &ASTCtx) {
6059         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6060         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6061 
6062         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6063         ASSERT_THAT(FooDecl, NotNull());
6064 
6065         auto &FooVal = getFormula(*FooDecl, Env);
6066         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
6067       },
6068       {BuiltinOptions{ContextSensitiveOptions{}}});
6069 }
6070 
6071 TEST(TransferTest, ContextSensitiveReturnArg) {
6072   std::string Code = R"(
6073     bool GiveBool();
6074     bool GiveBack(bool Arg) { return Arg; }
6075 
6076     void target() {
6077       bool Foo = GiveBool();
6078       bool Bar = GiveBack(Foo);
6079       bool Baz = Foo == Bar;
6080       // [[p]]
6081     }
6082   )";
6083   runDataflow(
6084       Code,
6085       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6086          ASTContext &ASTCtx) {
6087         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6088         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6089 
6090         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
6091         ASSERT_THAT(BazDecl, NotNull());
6092 
6093         auto &BazVal = getFormula(*BazDecl, Env);
6094         EXPECT_TRUE(Env.proves(BazVal));
6095       },
6096       {BuiltinOptions{ContextSensitiveOptions{}}});
6097 }
6098 
6099 TEST(TransferTest, ContextSensitiveReturnInt) {
6100   std::string Code = R"(
6101     int identity(int x) { return x; }
6102 
6103     void target() {
6104       int y = identity(42);
6105       // [[p]]
6106     }
6107   )";
6108   runDataflow(
6109       Code,
6110       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6111          ASTContext &ASTCtx) {
6112         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6113         // This just tests that the analysis doesn't crash.
6114       },
6115       {BuiltinOptions{ContextSensitiveOptions{}}});
6116 }
6117 
6118 TEST(TransferTest, ContextSensitiveReturnRecord) {
6119   std::string Code = R"(
6120     struct S {
6121       bool B;
6122     };
6123 
6124     S makeS(bool BVal) { return {BVal}; }
6125 
6126     void target() {
6127       S FalseS = makeS(false);
6128       S TrueS = makeS(true);
6129       // [[p]]
6130     }
6131   )";
6132   runDataflow(
6133       Code,
6134       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6135          ASTContext &ASTCtx) {
6136         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6137 
6138         auto &FalseSLoc =
6139             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "FalseS");
6140         auto &TrueSLoc =
6141             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "TrueS");
6142 
6143         EXPECT_EQ(getFieldValue(&FalseSLoc, "B", ASTCtx, Env),
6144                   &Env.getBoolLiteralValue(false));
6145         EXPECT_EQ(getFieldValue(&TrueSLoc, "B", ASTCtx, Env),
6146                   &Env.getBoolLiteralValue(true));
6147       },
6148       {BuiltinOptions{ContextSensitiveOptions{}}});
6149 }
6150 
6151 TEST(TransferTest, ContextSensitiveReturnSelfReferentialRecord) {
6152   std::string Code = R"(
6153     struct S {
6154       S() { self = this; }
6155       S *self;
6156     };
6157 
6158     S makeS() {
6159       // RVO guarantees that this will be constructed directly into `MyS`.
6160       return S();
6161     }
6162 
6163     void target() {
6164       S MyS = makeS();
6165       // [[p]]
6166     }
6167   )";
6168   runDataflow(
6169       Code,
6170       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6171          ASTContext &ASTCtx) {
6172         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6173 
6174         auto &MySLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MyS");
6175 
6176         auto *SelfVal =
6177             cast<PointerValue>(getFieldValue(&MySLoc, "self", ASTCtx, Env));
6178         EXPECT_EQ(&SelfVal->getPointeeLoc(), &MySLoc);
6179       },
6180       {BuiltinOptions{ContextSensitiveOptions{}}});
6181 }
6182 
6183 TEST(TransferTest, ContextSensitiveMethodLiteral) {
6184   std::string Code = R"(
6185     class MyClass {
6186     public:
6187       bool giveBool() { return true; }
6188     };
6189 
6190     void target() {
6191       MyClass MyObj;
6192       bool Foo = MyObj.giveBool();
6193       // [[p]]
6194     }
6195   )";
6196   runDataflow(
6197       Code,
6198       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6199          ASTContext &ASTCtx) {
6200         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6201         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6202 
6203         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6204         ASSERT_THAT(FooDecl, NotNull());
6205 
6206         auto &FooVal = getFormula(*FooDecl, Env);
6207         EXPECT_TRUE(Env.proves(FooVal));
6208       },
6209       {BuiltinOptions{ContextSensitiveOptions{}}});
6210 }
6211 
6212 TEST(TransferTest, ContextSensitiveMethodGetter) {
6213   std::string Code = R"(
6214     class MyClass {
6215     public:
6216       bool getField() { return Field; }
6217 
6218       bool Field;
6219     };
6220 
6221     void target() {
6222       MyClass MyObj;
6223       MyObj.Field = true;
6224       bool Foo = MyObj.getField();
6225       // [[p]]
6226     }
6227   )";
6228   runDataflow(
6229       Code,
6230       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6231          ASTContext &ASTCtx) {
6232         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6233         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6234 
6235         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6236         ASSERT_THAT(FooDecl, NotNull());
6237 
6238         auto &FooVal = getFormula(*FooDecl, Env);
6239         EXPECT_TRUE(Env.proves(FooVal));
6240       },
6241       {BuiltinOptions{ContextSensitiveOptions{}}});
6242 }
6243 
6244 TEST(TransferTest, ContextSensitiveMethodSetter) {
6245   std::string Code = R"(
6246     class MyClass {
6247     public:
6248       void setField(bool Val) { Field = Val; }
6249 
6250       bool Field;
6251     };
6252 
6253     void target() {
6254       MyClass MyObj;
6255       MyObj.setField(true);
6256       bool Foo = MyObj.Field;
6257       // [[p]]
6258     }
6259   )";
6260   runDataflow(
6261       Code,
6262       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6263          ASTContext &ASTCtx) {
6264         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6265         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6266 
6267         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6268         ASSERT_THAT(FooDecl, NotNull());
6269 
6270         auto &FooVal = getFormula(*FooDecl, Env);
6271         EXPECT_TRUE(Env.proves(FooVal));
6272       },
6273       {BuiltinOptions{ContextSensitiveOptions{}}});
6274 }
6275 
6276 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
6277   std::string Code = R"(
6278     class MyClass {
6279     public:
6280       bool getField() { return Field; }
6281       void setField(bool Val) { Field = Val; }
6282 
6283     private:
6284       bool Field;
6285     };
6286 
6287     void target() {
6288       MyClass MyObj;
6289       MyObj.setField(true);
6290       bool Foo = MyObj.getField();
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 
6311 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
6312   std::string Code = R"(
6313     class MyClass {
6314     public:
6315       void Inner() { MyField = true; }
6316       void Outer() { Inner(); }
6317 
6318       bool MyField;
6319     };
6320 
6321     void target() {
6322       MyClass MyObj;
6323       MyObj.Outer();
6324       bool Foo = MyObj.MyField;
6325       // [[p]]
6326     }
6327   )";
6328   runDataflow(
6329       Code,
6330       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6331          ASTContext &ASTCtx) {
6332         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6333         ;
6334         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6335 
6336         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6337         ASSERT_THAT(FooDecl, NotNull());
6338 
6339         auto &FooVal = getFormula(*FooDecl, Env);
6340         EXPECT_TRUE(Env.proves(FooVal));
6341       },
6342       {BuiltinOptions{ContextSensitiveOptions{}}});
6343 }
6344 
6345 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
6346   std::string Code = R"(
6347     class MyClass {
6348     public:
6349       bool Inner() { return MyField; }
6350       bool Outer() { return Inner(); }
6351 
6352       bool MyField;
6353     };
6354 
6355     void target() {
6356       MyClass MyObj;
6357       MyObj.MyField = true;
6358       bool Foo = MyObj.Outer();
6359       // [[p]]
6360     }
6361   )";
6362   runDataflow(
6363       Code,
6364       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6365          ASTContext &ASTCtx) {
6366         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6367         ;
6368         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6369 
6370         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6371         ASSERT_THAT(FooDecl, NotNull());
6372 
6373         auto &FooVal = getFormula(*FooDecl, Env);
6374         EXPECT_TRUE(Env.proves(FooVal));
6375       },
6376       {BuiltinOptions{ContextSensitiveOptions{}}});
6377 }
6378 
6379 TEST(TransferTest, ContextSensitiveConstructorBody) {
6380   std::string Code = R"(
6381     class MyClass {
6382     public:
6383       MyClass() { MyField = true; }
6384 
6385       bool MyField;
6386     };
6387 
6388     void target() {
6389       MyClass MyObj;
6390       bool Foo = MyObj.MyField;
6391       // [[p]]
6392     }
6393   )";
6394   runDataflow(
6395       Code,
6396       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6397          ASTContext &ASTCtx) {
6398         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6399         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6400 
6401         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6402         ASSERT_THAT(FooDecl, NotNull());
6403 
6404         auto &FooVal = getFormula(*FooDecl, Env);
6405         EXPECT_TRUE(Env.proves(FooVal));
6406       },
6407       {BuiltinOptions{ContextSensitiveOptions{}}});
6408 }
6409 
6410 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
6411   std::string Code = R"(
6412     class MyClass {
6413     public:
6414       MyClass() : MyField(true) {}
6415 
6416       bool MyField;
6417     };
6418 
6419     void target() {
6420       MyClass MyObj;
6421       bool Foo = MyObj.MyField;
6422       // [[p]]
6423     }
6424   )";
6425   runDataflow(
6426       Code,
6427       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6428          ASTContext &ASTCtx) {
6429         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6430         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6431 
6432         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6433         ASSERT_THAT(FooDecl, NotNull());
6434 
6435         auto &FooVal = getFormula(*FooDecl, Env);
6436         EXPECT_TRUE(Env.proves(FooVal));
6437       },
6438       {BuiltinOptions{ContextSensitiveOptions{}}});
6439 }
6440 
6441 TEST(TransferTest, ContextSensitiveConstructorDefault) {
6442   std::string Code = R"(
6443     class MyClass {
6444     public:
6445       MyClass() = default;
6446 
6447       bool MyField = true;
6448     };
6449 
6450     void target() {
6451       MyClass MyObj;
6452       bool Foo = MyObj.MyField;
6453       // [[p]]
6454     }
6455   )";
6456   runDataflow(
6457       Code,
6458       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6459          ASTContext &ASTCtx) {
6460         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6461         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6462 
6463         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6464         ASSERT_THAT(FooDecl, NotNull());
6465 
6466         auto &FooVal = getFormula(*FooDecl, Env);
6467         EXPECT_TRUE(Env.proves(FooVal));
6468       },
6469       {BuiltinOptions{ContextSensitiveOptions{}}});
6470 }
6471 
6472 TEST(TransferTest, ContextSensitiveSelfReferentialClass) {
6473   // Test that the `this` pointer seen in the constructor has the same value
6474   // as the address of the variable the object is constructed into.
6475   std::string Code = R"(
6476     class MyClass {
6477     public:
6478       MyClass() : Self(this) {}
6479       MyClass *Self;
6480     };
6481 
6482     void target() {
6483       MyClass MyObj;
6484       MyClass *SelfPtr = MyObj.Self;
6485       // [[p]]
6486     }
6487   )";
6488   runDataflow(
6489       Code,
6490       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6491          ASTContext &ASTCtx) {
6492         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6493 
6494         const ValueDecl *MyObjDecl = findValueDecl(ASTCtx, "MyObj");
6495         ASSERT_THAT(MyObjDecl, NotNull());
6496 
6497         const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "SelfPtr");
6498         ASSERT_THAT(SelfDecl, NotNull());
6499 
6500         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6501         auto &SelfVal = *cast<PointerValue>(Env.getValue(*SelfDecl));
6502         EXPECT_EQ(Env.getStorageLocation(*MyObjDecl), &SelfVal.getPointeeLoc());
6503       },
6504       {BuiltinOptions{ContextSensitiveOptions{}}});
6505 }
6506 
6507 TEST(TransferTest, UnnamedBitfieldInitializer) {
6508   std::string Code = R"(
6509     struct B {};
6510     struct A {
6511       unsigned a;
6512       unsigned : 4;
6513       unsigned c;
6514       B b;
6515     };
6516     void target() {
6517       A a = {};
6518       A test = a;
6519       (void)test.c;
6520     }
6521   )";
6522   runDataflow(
6523       Code,
6524       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6525          ASTContext &ASTCtx) {
6526         // This doesn't need a body because this test was crashing the framework
6527         // before handling correctly Unnamed bitfields in `InitListExpr`.
6528       });
6529 }
6530 
6531 // Repro for a crash that used to occur with chained short-circuiting logical
6532 // operators.
6533 TEST(TransferTest, ChainedLogicalOps) {
6534   std::string Code = R"(
6535     bool target() {
6536       bool b = true || false || false || false;
6537       // [[p]]
6538       return b;
6539     }
6540   )";
6541   runDataflow(
6542       Code,
6543       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6544          ASTContext &ASTCtx) {
6545         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6546         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
6547         EXPECT_TRUE(Env.proves(B));
6548       });
6549 }
6550 
6551 // Repro for a crash that used to occur when we call a `noreturn` function
6552 // within one of the operands of a `&&` or `||` operator.
6553 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
6554   std::string Code = R"(
6555     __attribute__((noreturn)) int doesnt_return();
6556     bool some_condition();
6557     void target(bool b1, bool b2) {
6558       // Neither of these should crash. In addition, if we don't terminate the
6559       // program, we know that the operators need to trigger the short-circuit
6560       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
6561       // will be true.
6562       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
6563       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
6564 
6565       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
6566       // entire expression unreachable. So we know that in both of the following
6567       // cases, if `target()` terminates, the `else` branch was taken.
6568       bool NoreturnOnLhsMakesAndUnreachable = false;
6569       if (some_condition())
6570          doesnt_return() > 0 && some_condition();
6571       else
6572          NoreturnOnLhsMakesAndUnreachable = true;
6573 
6574       bool NoreturnOnLhsMakesOrUnreachable = false;
6575       if (some_condition())
6576          doesnt_return() > 0 || some_condition();
6577       else
6578          NoreturnOnLhsMakesOrUnreachable = true;
6579 
6580       // [[p]]
6581     }
6582   )";
6583   runDataflow(
6584       Code,
6585       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6586          ASTContext &ASTCtx) {
6587         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6588         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6589         auto &A = Env.arena();
6590 
6591         // Check that [[p]] is reachable with a non-false flow condition.
6592         EXPECT_FALSE(Env.proves(A.makeLiteral(false)));
6593 
6594         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula();
6595         EXPECT_TRUE(Env.proves(A.makeNot(B1)));
6596 
6597         auto &NoreturnOnRhsOfAnd =
6598             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula();
6599         EXPECT_TRUE(Env.proves(A.makeNot(NoreturnOnRhsOfAnd)));
6600 
6601         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula();
6602         EXPECT_TRUE(Env.proves(B2));
6603 
6604         auto &NoreturnOnRhsOfOr =
6605             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr")
6606                 .formula();
6607         EXPECT_TRUE(Env.proves(NoreturnOnRhsOfOr));
6608 
6609         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
6610             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula();
6611         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesAndUnreachable));
6612 
6613         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
6614             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula();
6615         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesOrUnreachable));
6616       });
6617 }
6618 
6619 TEST(TransferTest, NewExpressions) {
6620   std::string Code = R"(
6621     void target() {
6622       int *p = new int(42);
6623       // [[after_new]]
6624     }
6625   )";
6626   runDataflow(
6627       Code,
6628       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6629          ASTContext &ASTCtx) {
6630         const Environment &Env =
6631             getEnvironmentAtAnnotation(Results, "after_new");
6632 
6633         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
6634 
6635         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
6636       });
6637 }
6638 
6639 TEST(TransferTest, NewExpressions_Structs) {
6640   std::string Code = R"(
6641     struct Inner {
6642       int InnerField;
6643     };
6644 
6645     struct Outer {
6646       Inner OuterField;
6647     };
6648 
6649     void target() {
6650       Outer *p = new Outer;
6651       // Access the fields to make sure the analysis actually generates children
6652       // for them in the `RecordStorageLocation`.
6653       p->OuterField.InnerField;
6654       // [[after_new]]
6655     }
6656   )";
6657   runDataflow(
6658       Code,
6659       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6660          ASTContext &ASTCtx) {
6661         const Environment &Env =
6662             getEnvironmentAtAnnotation(Results, "after_new");
6663 
6664         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
6665         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
6666 
6667         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
6668 
6669         auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
6670         auto &OuterFieldLoc =
6671             *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
6672         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
6673 
6674         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
6675       });
6676 }
6677 
6678 TEST(TransferTest, FunctionToPointerDecayHasValue) {
6679   std::string Code = R"(
6680     struct A { static void static_member_func(); };
6681     void target() {
6682       // To check that we're treating function-to-pointer decay correctly,
6683       // create two pointers, then verify they refer to the same storage
6684       // location.
6685       // We need to do the test this way because even if an initializer (in this
6686       // case, the function-to-pointer decay) does not create a value, we still
6687       // create a value for the variable.
6688       void (*non_member_p1)() = target;
6689       void (*non_member_p2)() = target;
6690 
6691       // Do the same thing but for a static member function.
6692       void (*member_p1)() = A::static_member_func;
6693       void (*member_p2)() = A::static_member_func;
6694       // [[p]]
6695     }
6696   )";
6697   runDataflow(
6698       Code,
6699       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6700          ASTContext &ASTCtx) {
6701         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6702 
6703         auto &NonMemberP1 =
6704             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
6705         auto &NonMemberP2 =
6706             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
6707         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
6708 
6709         auto &MemberP1 =
6710             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
6711         auto &MemberP2 =
6712             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
6713         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
6714       });
6715 }
6716 
6717 // Check that a builtin function is not associated with a value. (It's only
6718 // possible to call builtin functions directly, not take their address.)
6719 TEST(TransferTest, BuiltinFunctionModeled) {
6720   std::string Code = R"(
6721     void target() {
6722       __builtin_expect(0, 0);
6723       // [[p]]
6724     }
6725   )";
6726   runDataflow(
6727       Code,
6728       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6729          ASTContext &ASTCtx) {
6730         using ast_matchers::selectFirst;
6731         using ast_matchers::match;
6732         using ast_matchers::traverse;
6733         using ast_matchers::implicitCastExpr;
6734         using ast_matchers::hasCastKind;
6735 
6736         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6737 
6738         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
6739             "implicit_cast",
6740             match(traverse(TK_AsIs,
6741                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
6742                                .bind("implicit_cast")),
6743                   ASTCtx));
6744 
6745         ASSERT_THAT(ImplicitCast, NotNull());
6746         EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull());
6747       });
6748 }
6749 
6750 // Check that a callee of a member operator call is modeled as a `PointerValue`.
6751 // Member operator calls are unusual in that their callee is a pointer that
6752 // stems from a `FunctionToPointerDecay`. In calls to non-operator non-static
6753 // member functions, the callee is a `MemberExpr` (which does not have pointer
6754 // type).
6755 // We want to make sure that we produce a pointer value for the callee in this
6756 // specific scenario and that its storage location is durable (for convergence).
6757 TEST(TransferTest, MemberOperatorCallModelsPointerForCallee) {
6758   std::string Code = R"(
6759     struct S {
6760       bool operator!=(S s);
6761     };
6762     void target() {
6763       S s;
6764       (void)(s != s);
6765       (void)(s != s);
6766       // [[p]]
6767     }
6768   )";
6769   runDataflow(
6770       Code,
6771       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6772          ASTContext &ASTCtx) {
6773         using ast_matchers::selectFirst;
6774         using ast_matchers::match;
6775         using ast_matchers::traverse;
6776         using ast_matchers::cxxOperatorCallExpr;
6777 
6778         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6779 
6780         auto Matches = match(
6781             traverse(TK_AsIs, cxxOperatorCallExpr().bind("call")), ASTCtx);
6782 
6783         ASSERT_EQ(Matches.size(), 2UL);
6784 
6785         auto *Call1 = Matches[0].getNodeAs<CXXOperatorCallExpr>("call");
6786         auto *Call2 = Matches[1].getNodeAs<CXXOperatorCallExpr>("call");
6787 
6788         ASSERT_THAT(Call1, NotNull());
6789         ASSERT_THAT(Call2, NotNull());
6790 
6791         EXPECT_EQ(cast<ImplicitCastExpr>(Call1->getCallee())->getCastKind(),
6792                   CK_FunctionToPointerDecay);
6793         EXPECT_EQ(cast<ImplicitCastExpr>(Call2->getCallee())->getCastKind(),
6794                   CK_FunctionToPointerDecay);
6795 
6796         auto *Ptr1 = cast<PointerValue>(Env.getValue(*Call1->getCallee()));
6797         auto *Ptr2 = cast<PointerValue>(Env.getValue(*Call2->getCallee()));
6798 
6799         ASSERT_EQ(&Ptr1->getPointeeLoc(), &Ptr2->getPointeeLoc());
6800       });
6801 }
6802 
6803 // Check that fields of anonymous records are modeled.
6804 TEST(TransferTest, AnonymousStruct) {
6805   std::string Code = R"(
6806     struct S {
6807       struct {
6808         bool b;
6809       };
6810     };
6811     void target() {
6812       S s;
6813       s.b = true;
6814       // [[p]]
6815     }
6816   )";
6817   runDataflow(
6818       Code,
6819       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6820          ASTContext &ASTCtx) {
6821         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6822         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
6823         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6824         const IndirectFieldDecl *IndirectField =
6825             findIndirectFieldDecl(ASTCtx, "b");
6826 
6827         auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl));
6828         auto &AnonStruct = *cast<RecordStorageLocation>(
6829             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
6830 
6831         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6832         ASSERT_TRUE(Env.proves(B->formula()));
6833       });
6834 }
6835 
6836 TEST(TransferTest, AnonymousStructWithInitializer) {
6837   std::string Code = R"(
6838     struct target {
6839       target() {
6840         (void)0;
6841         // [[p]]
6842       }
6843       struct {
6844         bool b = true;
6845       };
6846     };
6847   )";
6848   runDataflow(
6849       Code,
6850       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6851          ASTContext &ASTCtx) {
6852         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6853         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6854         const IndirectFieldDecl *IndirectField =
6855             findIndirectFieldDecl(ASTCtx, "b");
6856 
6857         auto *ThisLoc =
6858             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6859         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6860             *cast<ValueDecl>(IndirectField->chain().front())));
6861 
6862         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6863         ASSERT_TRUE(Env.proves(B->formula()));
6864       });
6865 }
6866 
6867 TEST(TransferTest, AnonymousStructWithReferenceField) {
6868   std::string Code = R"(
6869     int global_i = 0;
6870     struct target {
6871       target() {
6872         (void)0;
6873         // [[p]]
6874       }
6875       struct {
6876         int &i = global_i;
6877       };
6878     };
6879   )";
6880   runDataflow(
6881       Code,
6882       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6883          ASTContext &ASTCtx) {
6884         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6885         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
6886         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
6887         const IndirectFieldDecl *IndirectField =
6888             findIndirectFieldDecl(ASTCtx, "i");
6889 
6890         auto *ThisLoc =
6891             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6892         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6893             *cast<ValueDecl>(IndirectField->chain().front())));
6894 
6895         ASSERT_EQ(AnonStruct.getChild(*IDecl),
6896                   Env.getStorageLocation(*GlobalIDecl));
6897       });
6898 }
6899 
6900 TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {
6901   // This is a crash repro.
6902   // `false` block may not have been processed when we try to evaluate the `||`
6903   // after visiting `true`, because it is not necessary (and therefore the edge
6904   // is marked unreachable). Trying to get the analysis state via
6905   // `getEnvironment` for the subexpression still should not crash.
6906   std::string Code = R"(
6907     int target(int i) {
6908       if ((i < 0 && true) || false) {
6909         return 0;
6910       }
6911       return 0;
6912     }
6913   )";
6914   runDataflow(
6915       Code,
6916       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6917          ASTContext &ASTCtx) {});
6918 }
6919 
6920 TEST(TransferTest, LambdaCaptureByCopy) {
6921   std::string Code = R"(
6922     void target(int Foo, int Bar) {
6923       [Foo]() {
6924         (void)0;
6925         // [[p]]
6926       }();
6927     }
6928   )";
6929   runDataflowOnLambda(
6930       Code,
6931       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6932          ASTContext &ASTCtx) {
6933         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6934         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6935 
6936         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6937         ASSERT_THAT(FooDecl, NotNull());
6938 
6939         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6940         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6941 
6942         const Value *FooVal = Env.getValue(*FooLoc);
6943         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6944 
6945         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6946         ASSERT_THAT(BarDecl, NotNull());
6947 
6948         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6949         EXPECT_THAT(BarLoc, IsNull());
6950       });
6951 }
6952 
6953 TEST(TransferTest, LambdaCaptureByReference) {
6954   std::string Code = R"(
6955     void target(int Foo, int Bar) {
6956       [&Foo]() {
6957         (void)0;
6958         // [[p]]
6959       }();
6960     }
6961   )";
6962   runDataflowOnLambda(
6963       Code,
6964       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6965          ASTContext &ASTCtx) {
6966         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6967         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6968 
6969         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6970         ASSERT_THAT(FooDecl, NotNull());
6971 
6972         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6973         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6974 
6975         const Value *FooVal = Env.getValue(*FooLoc);
6976         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6977 
6978         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6979         ASSERT_THAT(BarDecl, NotNull());
6980 
6981         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6982         EXPECT_THAT(BarLoc, IsNull());
6983       });
6984 }
6985 
6986 TEST(TransferTest, LambdaCaptureWithInitializer) {
6987   std::string Code = R"(
6988     void target(int Bar) {
6989       [Foo=Bar]() {
6990         (void)0;
6991         // [[p]]
6992       }();
6993     }
6994   )";
6995   runDataflowOnLambda(
6996       Code,
6997       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6998          ASTContext &ASTCtx) {
6999         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7000         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7001 
7002         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7003         ASSERT_THAT(FooDecl, NotNull());
7004 
7005         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7006         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7007 
7008         const Value *FooVal = Env.getValue(*FooLoc);
7009         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7010 
7011         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7012         ASSERT_THAT(BarDecl, NotNull());
7013 
7014         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7015         EXPECT_THAT(BarLoc, IsNull());
7016       });
7017 }
7018 
7019 TEST(TransferTest, LambdaCaptureByCopyImplicit) {
7020   std::string Code = R"(
7021     void target(int Foo, int Bar) {
7022       [=]() {
7023         Foo;
7024         // [[p]]
7025       }();
7026     }
7027   )";
7028   runDataflowOnLambda(
7029       Code,
7030       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7031          ASTContext &ASTCtx) {
7032         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7033         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7034 
7035         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7036         ASSERT_THAT(FooDecl, NotNull());
7037 
7038         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7039         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7040 
7041         const Value *FooVal = Env.getValue(*FooLoc);
7042         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7043 
7044         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7045         ASSERT_THAT(BarDecl, NotNull());
7046 
7047         // There is no storage location for `Bar` because it isn't used in the
7048         // body of the lambda.
7049         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7050         EXPECT_THAT(BarLoc, IsNull());
7051       });
7052 }
7053 
7054 TEST(TransferTest, LambdaCaptureByReferenceImplicit) {
7055   std::string Code = R"(
7056     void target(int Foo, int Bar) {
7057       [&]() {
7058         Foo;
7059         // [[p]]
7060       }();
7061     }
7062   )";
7063   runDataflowOnLambda(
7064       Code,
7065       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7066          ASTContext &ASTCtx) {
7067         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7068         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7069 
7070         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7071         ASSERT_THAT(FooDecl, NotNull());
7072 
7073         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7074         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7075 
7076         const Value *FooVal = Env.getValue(*FooLoc);
7077         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7078 
7079         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7080         ASSERT_THAT(BarDecl, NotNull());
7081 
7082         // There is no storage location for `Bar` because it isn't used in the
7083         // body of the lambda.
7084         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7085         EXPECT_THAT(BarLoc, IsNull());
7086       });
7087 }
7088 
7089 TEST(TransferTest, LambdaCaptureThis) {
7090   std::string Code = R"(
7091     struct Bar {
7092       int Foo;
7093 
7094       void target() {
7095         [this]() {
7096           Foo;
7097           // [[p]]
7098         }();
7099       }
7100     };
7101   )";
7102   runDataflowOnLambda(
7103       Code,
7104       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7105          ASTContext &ASTCtx) {
7106         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7107         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7108 
7109         const RecordStorageLocation *ThisPointeeLoc =
7110             Env.getThisPointeeStorageLocation();
7111         ASSERT_THAT(ThisPointeeLoc, NotNull());
7112 
7113         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7114         ASSERT_THAT(FooDecl, NotNull());
7115 
7116         const StorageLocation *FooLoc = ThisPointeeLoc->getChild(*FooDecl);
7117         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7118 
7119         const Value *FooVal = Env.getValue(*FooLoc);
7120         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7121       });
7122 }
7123 
7124 // This test verifies correct modeling of a relational dependency that goes
7125 // through unmodeled functions (the simple `cond()` in this case).
7126 TEST(TransferTest, ConditionalRelation) {
7127   std::string Code = R"(
7128     bool cond();
7129     void target() {
7130        bool a = true;
7131        bool b = true;
7132        if (cond()) {
7133          a = false;
7134          if (cond()) {
7135            b = false;
7136          }
7137        }
7138        (void)0;
7139        // [[p]]
7140     }
7141  )";
7142   runDataflow(
7143       Code,
7144       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7145          ASTContext &ASTCtx) {
7146         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7147         auto &A = Env.arena();
7148         auto &VarA = getValueForDecl<BoolValue>(ASTCtx, Env, "a").formula();
7149         auto &VarB = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
7150 
7151         EXPECT_FALSE(Env.allows(A.makeAnd(VarA, A.makeNot(VarB))));
7152       });
7153 }
7154 
7155 } // namespace
7156