xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision 597a3150e932a9423c65b5ea4b53dd431aff5865)
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, ResultObjectLocationDontVisitNestedRecordDecl) {
3313   // This is a crash repro.
3314   // We used to crash because when propagating result objects, we would visit
3315   // nested record and function declarations, but we don't model fields used
3316   // only in these.
3317   std::string Code = R"(
3318     struct S1 {};
3319     struct S2 { S1 s1; };
3320     void target() {
3321       struct Nested {
3322         void f() {
3323           S2 s2 = { S1() };
3324         }
3325       };
3326     }
3327   )";
3328   runDataflow(
3329       Code,
3330       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3331          ASTContext &ASTCtx) {});
3332 }
3333 
3334 TEST(TransferTest, ResultObjectLocationDontVisitUnevaluatedContexts) {
3335   // This is a crash repro.
3336   // We used to crash because when propagating result objects, we would visit
3337   // unevaluated contexts, but we don't model fields used only in these.
3338 
3339   auto testFunction = [](llvm::StringRef Code, llvm::StringRef TargetFun) {
3340     runDataflow(
3341         Code,
3342         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3343            ASTContext &ASTCtx) {},
3344         LangStandard::lang_gnucxx17,
3345         /* ApplyBuiltinTransfer= */ true, TargetFun);
3346   };
3347 
3348   std::string Code = R"cc(
3349     // Definitions needed for `typeid`.
3350     namespace std {
3351       class type_info {};
3352       class bad_typeid {};
3353     }  // namespace std
3354 
3355     struct S1 {};
3356     struct S2 { S1 s1; };
3357 
3358     // We test each type of unevaluated context from a different target
3359     // function. Some types of unevaluated contexts may actually cause the
3360     // field `s1` to be modeled, and we don't want this to "pollute" the tests
3361     // for the other unevaluated contexts.
3362     void decltypeTarget() {
3363         decltype(S2{}) Dummy;
3364     }
3365     void typeofTarget() {
3366         typeof(S2{}) Dummy;
3367     }
3368     void typeidTarget() {
3369         typeid(S2{});
3370     }
3371     void sizeofTarget() {
3372         sizeof(S2{});
3373     }
3374     void noexceptTarget() {
3375         noexcept(S2{});
3376     }
3377   )cc";
3378 
3379   testFunction(Code, "decltypeTarget");
3380   testFunction(Code, "typeofTarget");
3381   testFunction(Code, "typeidTarget");
3382   testFunction(Code, "sizeofTarget");
3383   testFunction(Code, "noexceptTarget");
3384 }
3385 
3386 TEST(TransferTest, StaticCast) {
3387   std::string Code = R"(
3388     void target(int Foo) {
3389       int Bar = static_cast<int>(Foo);
3390       // [[p]]
3391     }
3392   )";
3393   runDataflow(
3394       Code,
3395       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3396          ASTContext &ASTCtx) {
3397         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3398         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3399 
3400         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3401         ASSERT_THAT(FooDecl, NotNull());
3402 
3403         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3404         ASSERT_THAT(BarDecl, NotNull());
3405 
3406         const auto *FooVal = Env.getValue(*FooDecl);
3407         const auto *BarVal = Env.getValue(*BarDecl);
3408         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3409         EXPECT_TRUE(isa<IntegerValue>(BarVal));
3410         EXPECT_EQ(FooVal, BarVal);
3411       });
3412 }
3413 
3414 TEST(TransferTest, IntegralCast) {
3415   std::string Code = R"(
3416     void target(int Foo) {
3417       long Bar = Foo;
3418       // [[p]]
3419     }
3420   )";
3421   runDataflow(
3422       Code,
3423       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3424          ASTContext &ASTCtx) {
3425         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3426 
3427         const auto &FooVal = getValueForDecl<IntegerValue>(ASTCtx, Env, "Foo");
3428         const auto &BarVal = getValueForDecl<IntegerValue>(ASTCtx, Env, "Bar");
3429         EXPECT_EQ(&FooVal, &BarVal);
3430       });
3431 }
3432 
3433 TEST(TransferTest, IntegraltoBooleanCast) {
3434   std::string Code = R"(
3435     void target(int Foo) {
3436       bool Bar = Foo;
3437       // [[p]]
3438     }
3439   )";
3440   runDataflow(
3441       Code,
3442       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3443          ASTContext &ASTCtx) {
3444         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3445 
3446         const auto &FooVal = getValueForDecl(ASTCtx, Env, "Foo");
3447         const auto &BarVal = getValueForDecl(ASTCtx, Env, "Bar");
3448         EXPECT_TRUE(isa<IntegerValue>(FooVal));
3449         EXPECT_TRUE(isa<BoolValue>(BarVal));
3450       });
3451 }
3452 
3453 TEST(TransferTest, IntegralToBooleanCastFromBool) {
3454   std::string Code = R"(
3455     void target(bool Foo) {
3456       int Zab = Foo;
3457       bool Bar = Zab;
3458       // [[p]]
3459     }
3460   )";
3461   runDataflow(
3462       Code,
3463       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3464          ASTContext &ASTCtx) {
3465         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3466 
3467         const auto &FooVal = getValueForDecl<BoolValue>(ASTCtx, Env, "Foo");
3468         const auto &BarVal = getValueForDecl<BoolValue>(ASTCtx, Env, "Bar");
3469         EXPECT_EQ(&FooVal, &BarVal);
3470       });
3471 }
3472 
3473 TEST(TransferTest, WidenBoolValueInIntegerVariable) {
3474   // This is a crash repro.
3475   // This test sets up a case where we perform widening on an integer variable
3476   // that contains a `BoolValue` for the previous iteration and an
3477   // `IntegerValue` for the current iteration. We used to crash on this because
3478   // `widenDistinctValues()` assumed that if the previous iteration had a
3479   // `BoolValue`, the current iteration would too.
3480   // FIXME: The real fix here is to make sure we never store `BoolValue`s in
3481   // integer variables; see also the comment in `widenDistinctValues()`.
3482   std::string Code = R"cc(
3483     struct S {
3484       int i;
3485       S *next;
3486     };
3487     void target(S *s) {
3488       for (; s; s = s->next)
3489         s->i = false;
3490     }
3491   )cc";
3492   runDataflow(Code,
3493               [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
3494                  ASTContext &) {});
3495 }
3496 
3497 TEST(TransferTest, NullToPointerCast) {
3498   std::string Code = R"(
3499     using my_nullptr_t = decltype(nullptr);
3500     struct Baz {};
3501     void target() {
3502       int *FooX = nullptr;
3503       int *FooY = nullptr;
3504       bool **Bar = nullptr;
3505       Baz *Baz = nullptr;
3506       my_nullptr_t Null = 0;
3507       // [[p]]
3508     }
3509   )";
3510   runDataflow(
3511       Code,
3512       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3513          ASTContext &ASTCtx) {
3514         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3515         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3516 
3517         const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
3518         ASSERT_THAT(FooXDecl, NotNull());
3519 
3520         const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
3521         ASSERT_THAT(FooYDecl, NotNull());
3522 
3523         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3524         ASSERT_THAT(BarDecl, NotNull());
3525 
3526         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3527         ASSERT_THAT(BazDecl, NotNull());
3528 
3529         const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
3530         ASSERT_THAT(NullDecl, NotNull());
3531 
3532         const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl));
3533         const auto *FooYVal = cast<PointerValue>(Env.getValue(*FooYDecl));
3534         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3535         const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl));
3536         const auto *NullVal = cast<PointerValue>(Env.getValue(*NullDecl));
3537 
3538         EXPECT_EQ(FooXVal, FooYVal);
3539         EXPECT_NE(FooXVal, BarVal);
3540         EXPECT_NE(FooXVal, BazVal);
3541         EXPECT_NE(BarVal, BazVal);
3542 
3543         const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
3544         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
3545         EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
3546 
3547         const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
3548         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
3549         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
3550 
3551         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
3552         EXPECT_TRUE(isa<RecordStorageLocation>(BazPointeeLoc));
3553         EXPECT_EQ(BazVal, &Env.fork().getOrCreateNullPointerValue(
3554                               BazPointeeLoc.getType()));
3555 
3556         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
3557         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
3558         EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
3559       });
3560 }
3561 
3562 TEST(TransferTest, PointerToMemberVariable) {
3563   std::string Code = R"(
3564     struct S {
3565       int i;
3566     };
3567     void target() {
3568       int S::*MemberPointer = &S::i;
3569       // [[p]]
3570     }
3571   )";
3572   runDataflow(
3573       Code,
3574       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3575          ASTContext &ASTCtx) {
3576         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3577 
3578         const ValueDecl *MemberPointerDecl =
3579             findValueDecl(ASTCtx, "MemberPointer");
3580         ASSERT_THAT(MemberPointerDecl, NotNull());
3581         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3582       });
3583 }
3584 
3585 TEST(TransferTest, PointerToMemberFunction) {
3586   std::string Code = R"(
3587     struct S {
3588       void Method();
3589     };
3590     void target() {
3591       void (S::*MemberPointer)() = &S::Method;
3592       // [[p]]
3593     }
3594   )";
3595   runDataflow(
3596       Code,
3597       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3598          ASTContext &ASTCtx) {
3599         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3600 
3601         const ValueDecl *MemberPointerDecl =
3602             findValueDecl(ASTCtx, "MemberPointer");
3603         ASSERT_THAT(MemberPointerDecl, NotNull());
3604         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3605       });
3606 }
3607 
3608 TEST(TransferTest, NullToMemberPointerCast) {
3609   std::string Code = R"(
3610     struct Foo {};
3611     void target() {
3612       int Foo::*MemberPointer = nullptr;
3613       // [[p]]
3614     }
3615   )";
3616   runDataflow(
3617       Code,
3618       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3619          ASTContext &ASTCtx) {
3620         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3621         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3622 
3623         const ValueDecl *MemberPointerDecl =
3624             findValueDecl(ASTCtx, "MemberPointer");
3625         ASSERT_THAT(MemberPointerDecl, NotNull());
3626         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
3627       });
3628 }
3629 
3630 TEST(TransferTest, AddrOfValue) {
3631   std::string Code = R"(
3632     void target() {
3633       int Foo;
3634       int *Bar = &Foo;
3635       // [[p]]
3636     }
3637   )";
3638   runDataflow(
3639       Code,
3640       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3641          ASTContext &ASTCtx) {
3642         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3643         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3644 
3645         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3646         ASSERT_THAT(FooDecl, NotNull());
3647 
3648         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3649         ASSERT_THAT(BarDecl, NotNull());
3650 
3651         const auto *FooLoc =
3652             cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
3653         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3654         EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
3655       });
3656 }
3657 
3658 TEST(TransferTest, AddrOfReference) {
3659   std::string Code = R"(
3660     void target(int *Foo) {
3661       int *Bar = &(*Foo);
3662       // [[p]]
3663     }
3664   )";
3665   runDataflow(
3666       Code,
3667       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3668          ASTContext &ASTCtx) {
3669         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3670         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3671 
3672         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3673         ASSERT_THAT(FooDecl, NotNull());
3674 
3675         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3676         ASSERT_THAT(BarDecl, NotNull());
3677 
3678         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl));
3679         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
3680         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
3681       });
3682 }
3683 
3684 TEST(TransferTest, CannotAnalyzeFunctionTemplate) {
3685   std::string Code = R"(
3686     template <typename T>
3687     void target() {}
3688   )";
3689   ASSERT_THAT_ERROR(
3690       checkDataflowWithNoopAnalysis(Code),
3691       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3692 }
3693 
3694 TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) {
3695   std::string Code = R"(
3696     template <typename T>
3697     struct A {
3698       void target() {}
3699     };
3700   )";
3701   ASSERT_THAT_ERROR(
3702       checkDataflowWithNoopAnalysis(Code),
3703       llvm::FailedWithMessage("Cannot analyze templated declarations"));
3704 }
3705 
3706 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
3707   std::string Code = R"(
3708     struct A {
3709       int i;
3710     };
3711 
3712     void target(A Foo, A Bar, bool Cond) {
3713       A Baz = Cond ?  A(Foo) : A(Bar);
3714       // Make sure A::i is modeled.
3715       Baz.i;
3716       /*[[p]]*/
3717     }
3718   )";
3719   runDataflow(
3720       Code,
3721       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3722          ASTContext &ASTCtx) {
3723         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3724 
3725         auto *FooIVal = cast<IntegerValue>(getFieldValue(
3726             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo"), "i",
3727             ASTCtx, Env));
3728         auto *BarIVal = cast<IntegerValue>(getFieldValue(
3729             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar"), "i",
3730             ASTCtx, Env));
3731         auto *BazIVal = cast<IntegerValue>(getFieldValue(
3732             &getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Baz"), "i",
3733             ASTCtx, Env));
3734 
3735         EXPECT_NE(BazIVal, FooIVal);
3736         EXPECT_NE(BazIVal, BarIVal);
3737       });
3738 }
3739 
3740 TEST(TransferTest, VarDeclInDoWhile) {
3741   std::string Code = R"(
3742     void target(int *Foo) {
3743       do {
3744         int Bar = *Foo;
3745         // [[in_loop]]
3746       } while (false);
3747       (void)0;
3748       // [[after_loop]]
3749     }
3750   )";
3751   runDataflow(
3752       Code,
3753       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3754          ASTContext &ASTCtx) {
3755         const Environment &EnvInLoop =
3756             getEnvironmentAtAnnotation(Results, "in_loop");
3757         const Environment &EnvAfterLoop =
3758             getEnvironmentAtAnnotation(Results, "after_loop");
3759 
3760         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3761         ASSERT_THAT(FooDecl, NotNull());
3762 
3763         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3764         ASSERT_THAT(BarDecl, NotNull());
3765 
3766         const auto *FooVal =
3767             cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl));
3768         const auto *FooPointeeVal =
3769             cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc()));
3770 
3771         const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl));
3772         EXPECT_EQ(BarVal, FooPointeeVal);
3773 
3774         ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), IsNull());
3775       });
3776 }
3777 
3778 TEST(TransferTest, UnreachableAfterWhileTrue) {
3779   std::string Code = R"(
3780     void target() {
3781       while (true) {}
3782       (void)0;
3783       /*[[p]]*/
3784     }
3785   )";
3786   runDataflow(
3787       Code,
3788       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3789          ASTContext &ASTCtx) {
3790         // The node after the while-true is pruned because it is trivially
3791         // known to be unreachable.
3792         ASSERT_TRUE(Results.empty());
3793       });
3794 }
3795 
3796 TEST(TransferTest, AggregateInitialization) {
3797   std::string BracesCode = R"(
3798     struct A {
3799       int Foo;
3800     };
3801 
3802     struct B {
3803       int Bar;
3804       A Baz;
3805       int Qux;
3806     };
3807 
3808     void target(int BarArg, int FooArg, int QuxArg) {
3809       B Quux{BarArg, {FooArg}, QuxArg};
3810       B OtherB;
3811       /*[[p]]*/
3812     }
3813   )";
3814   std::string BraceElisionCode = R"(
3815     struct A {
3816       int Foo;
3817     };
3818 
3819     struct B {
3820       int Bar;
3821       A Baz;
3822       int Qux;
3823     };
3824 
3825     void target(int BarArg, int FooArg, int QuxArg) {
3826       B Quux = {BarArg, FooArg, QuxArg};
3827       B OtherB;
3828       /*[[p]]*/
3829     }
3830   )";
3831   for (const std::string &Code : {BracesCode, BraceElisionCode}) {
3832     runDataflow(
3833         Code,
3834         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3835            ASTContext &ASTCtx) {
3836           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3837           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3838 
3839           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3840           ASSERT_THAT(FooDecl, NotNull());
3841 
3842           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3843           ASSERT_THAT(BarDecl, NotNull());
3844 
3845           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3846           ASSERT_THAT(BazDecl, NotNull());
3847 
3848           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3849           ASSERT_THAT(QuxDecl, NotNull());
3850 
3851           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
3852           ASSERT_THAT(FooArgDecl, NotNull());
3853 
3854           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
3855           ASSERT_THAT(BarArgDecl, NotNull());
3856 
3857           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
3858           ASSERT_THAT(QuxArgDecl, NotNull());
3859 
3860           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
3861           ASSERT_THAT(QuuxDecl, NotNull());
3862 
3863           const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl));
3864           const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl));
3865           const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl));
3866 
3867           const auto &QuuxLoc =
3868               *cast<RecordStorageLocation>(Env.getStorageLocation(*QuuxDecl));
3869           const auto &BazLoc =
3870               *cast<RecordStorageLocation>(QuuxLoc.getChild(*BazDecl));
3871 
3872           EXPECT_EQ(getFieldValue(&QuuxLoc, *BarDecl, Env), BarArgVal);
3873           EXPECT_EQ(getFieldValue(&BazLoc, *FooDecl, Env), FooArgVal);
3874           EXPECT_EQ(getFieldValue(&QuuxLoc, *QuxDecl, Env), QuxArgVal);
3875 
3876           // Check that fields initialized in an initializer list are always
3877           // modeled in other instances of the same type.
3878           const auto &OtherBLoc =
3879               getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "OtherB");
3880           EXPECT_THAT(OtherBLoc.getChild(*BarDecl), NotNull());
3881           EXPECT_THAT(OtherBLoc.getChild(*BazDecl), NotNull());
3882           EXPECT_THAT(OtherBLoc.getChild(*QuxDecl), NotNull());
3883         });
3884   }
3885 }
3886 
3887 TEST(TransferTest, AggregateInitializationReferenceField) {
3888   std::string Code = R"(
3889     struct S {
3890       int &RefField;
3891     };
3892 
3893     void target(int i) {
3894       S s = { i };
3895       /*[[p]]*/
3896     }
3897   )";
3898   runDataflow(
3899       Code,
3900       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3901          ASTContext &ASTCtx) {
3902         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3903 
3904         const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField");
3905 
3906         auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i");
3907         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3908 
3909         EXPECT_EQ(SLoc.getChild(*RefFieldDecl), &ILoc);
3910       });
3911 }
3912 
3913 TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) {
3914   std::string Code = R"(
3915     struct S {
3916       int i1;
3917       int i2;
3918     };
3919 
3920     void target(int i) {
3921       S s = { i };
3922       /*[[p]]*/
3923     }
3924   )";
3925   runDataflow(
3926       Code,
3927       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3928          ASTContext &ASTCtx) {
3929         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3930 
3931         const ValueDecl *I1FieldDecl = findValueDecl(ASTCtx, "i1");
3932         const ValueDecl *I2FieldDecl = findValueDecl(ASTCtx, "i2");
3933 
3934         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
3935 
3936         auto &IValue = getValueForDecl<IntegerValue>(ASTCtx, Env, "i");
3937         auto &I1Value =
3938             *cast<IntegerValue>(getFieldValue(&SLoc, *I1FieldDecl, Env));
3939         EXPECT_EQ(&I1Value, &IValue);
3940         auto &I2Value =
3941             *cast<IntegerValue>(getFieldValue(&SLoc, *I2FieldDecl, Env));
3942         EXPECT_NE(&I2Value, &IValue);
3943       });
3944 }
3945 
3946 TEST(TransferTest, AggregateInitializationFunctionPointer) {
3947   // This is a repro for an assertion failure.
3948   // nullptr takes on the type of a const function pointer, but its type was
3949   // asserted to be equal to the *unqualified* type of Field, which no longer
3950   // included the const.
3951   std::string Code = R"(
3952     struct S {
3953       void (*const Field)();
3954     };
3955 
3956     void target() {
3957       S s{nullptr};
3958     }
3959   )";
3960   runDataflow(
3961       Code,
3962       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3963          ASTContext &ASTCtx) {});
3964 }
3965 
3966 TEST(TransferTest, AssignToUnionMember) {
3967   std::string Code = R"(
3968     union A {
3969       int Foo;
3970     };
3971 
3972     void target(int Bar) {
3973       A Baz;
3974       Baz.Foo = Bar;
3975       // [[p]]
3976     }
3977   )";
3978   runDataflow(
3979       Code,
3980       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3981          ASTContext &ASTCtx) {
3982         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3983         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3984 
3985         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3986         ASSERT_THAT(BazDecl, NotNull());
3987         ASSERT_TRUE(BazDecl->getType()->isUnionType());
3988 
3989         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
3990         FieldDecl *FooDecl = nullptr;
3991         for (FieldDecl *Field : BazFields) {
3992           if (Field->getNameAsString() == "Foo") {
3993             FooDecl = Field;
3994           } else {
3995             FAIL() << "Unexpected field: " << Field->getNameAsString();
3996           }
3997         }
3998         ASSERT_THAT(FooDecl, NotNull());
3999 
4000         const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>(
4001             Env.getStorageLocation(*BazDecl));
4002         ASSERT_THAT(BazLoc, NotNull());
4003 
4004         const auto *FooVal =
4005             cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env));
4006 
4007         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4008         ASSERT_THAT(BarDecl, NotNull());
4009         const auto *BarLoc = Env.getStorageLocation(*BarDecl);
4010         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
4011 
4012         EXPECT_EQ(Env.getValue(*BarLoc), FooVal);
4013       });
4014 }
4015 
4016 TEST(TransferTest, AssignFromBoolLiteral) {
4017   std::string Code = R"(
4018     void target() {
4019       bool Foo = true;
4020       bool Bar = false;
4021       // [[p]]
4022     }
4023   )";
4024   runDataflow(
4025       Code,
4026       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4027          ASTContext &ASTCtx) {
4028         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4029         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4030 
4031         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4032         ASSERT_THAT(FooDecl, NotNull());
4033 
4034         const auto *FooVal =
4035             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4036         ASSERT_THAT(FooVal, NotNull());
4037 
4038         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4039         ASSERT_THAT(BarDecl, NotNull());
4040 
4041         const auto *BarVal =
4042             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4043         ASSERT_THAT(BarVal, NotNull());
4044 
4045         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
4046         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
4047       });
4048 }
4049 
4050 TEST(TransferTest, AssignFromCompositeBoolExpression) {
4051   {
4052     std::string Code = R"(
4053     void target(bool Foo, bool Bar, bool Qux) {
4054       bool Baz = (Foo) && (Bar || Qux);
4055       // [[p]]
4056     }
4057   )";
4058     runDataflow(
4059         Code,
4060         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4061            ASTContext &ASTCtx) {
4062           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4063           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4064 
4065           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4066           ASSERT_THAT(FooDecl, NotNull());
4067 
4068           const auto *FooVal =
4069               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4070           ASSERT_THAT(FooVal, NotNull());
4071 
4072           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4073           ASSERT_THAT(BarDecl, NotNull());
4074 
4075           const auto *BarVal =
4076               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4077           ASSERT_THAT(BarVal, NotNull());
4078 
4079           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4080           ASSERT_THAT(QuxDecl, NotNull());
4081 
4082           const auto *QuxVal =
4083               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
4084           ASSERT_THAT(QuxVal, NotNull());
4085 
4086           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4087           ASSERT_THAT(BazDecl, NotNull());
4088 
4089           const auto *BazVal =
4090               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
4091           ASSERT_THAT(BazVal, NotNull());
4092           auto &A = Env.arena();
4093           EXPECT_EQ(&BazVal->formula(),
4094                     &A.makeAnd(FooVal->formula(),
4095                                A.makeOr(BarVal->formula(), QuxVal->formula())));
4096         });
4097   }
4098 
4099   {
4100     std::string Code = R"(
4101     void target(bool Foo, bool Bar, bool Qux) {
4102       bool Baz = (Foo && Qux) || (Bar);
4103       // [[p]]
4104     }
4105   )";
4106     runDataflow(
4107         Code,
4108         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4109            ASTContext &ASTCtx) {
4110           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4111           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4112 
4113           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4114           ASSERT_THAT(FooDecl, NotNull());
4115 
4116           const auto *FooVal =
4117               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4118           ASSERT_THAT(FooVal, NotNull());
4119 
4120           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4121           ASSERT_THAT(BarDecl, NotNull());
4122 
4123           const auto *BarVal =
4124               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4125           ASSERT_THAT(BarVal, NotNull());
4126 
4127           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4128           ASSERT_THAT(QuxDecl, NotNull());
4129 
4130           const auto *QuxVal =
4131               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
4132           ASSERT_THAT(QuxVal, NotNull());
4133 
4134           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4135           ASSERT_THAT(BazDecl, NotNull());
4136 
4137           const auto *BazVal =
4138               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
4139           ASSERT_THAT(BazVal, NotNull());
4140           auto &A = Env.arena();
4141           EXPECT_EQ(&BazVal->formula(),
4142                     &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()),
4143                               BarVal->formula()));
4144         });
4145   }
4146 
4147   {
4148     std::string Code = R"(
4149       void target(bool A, bool B, bool C, bool D) {
4150         bool Foo = ((A && B) && C) && D;
4151         // [[p]]
4152       }
4153     )";
4154     runDataflow(
4155         Code,
4156         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4157            ASTContext &ASTCtx) {
4158           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4159           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4160 
4161           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
4162           ASSERT_THAT(ADecl, NotNull());
4163 
4164           const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl));
4165           ASSERT_THAT(AVal, NotNull());
4166 
4167           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4168           ASSERT_THAT(BDecl, NotNull());
4169 
4170           const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl));
4171           ASSERT_THAT(BVal, NotNull());
4172 
4173           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4174           ASSERT_THAT(CDecl, NotNull());
4175 
4176           const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl));
4177           ASSERT_THAT(CVal, NotNull());
4178 
4179           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
4180           ASSERT_THAT(DDecl, NotNull());
4181 
4182           const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl));
4183           ASSERT_THAT(DVal, NotNull());
4184 
4185           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4186           ASSERT_THAT(FooDecl, NotNull());
4187 
4188           const auto *FooVal =
4189               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4190           ASSERT_THAT(FooVal, NotNull());
4191           auto &A = Env.arena();
4192           EXPECT_EQ(
4193               &FooVal->formula(),
4194               &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()),
4195                                    CVal->formula()),
4196                          DVal->formula()));
4197         });
4198   }
4199 }
4200 
4201 TEST(TransferTest, AssignFromBoolNegation) {
4202   std::string Code = R"(
4203     void target() {
4204       bool Foo = true;
4205       bool Bar = !(Foo);
4206       // [[p]]
4207     }
4208   )";
4209   runDataflow(
4210       Code,
4211       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4212          ASTContext &ASTCtx) {
4213         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4214         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4215 
4216         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4217         ASSERT_THAT(FooDecl, NotNull());
4218 
4219         const auto *FooVal =
4220             dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
4221         ASSERT_THAT(FooVal, NotNull());
4222 
4223         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4224         ASSERT_THAT(BarDecl, NotNull());
4225 
4226         const auto *BarVal =
4227             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
4228         ASSERT_THAT(BarVal, NotNull());
4229         auto &A = Env.arena();
4230         EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula()));
4231       });
4232 }
4233 
4234 TEST(TransferTest, BuiltinExpect) {
4235   std::string Code = R"(
4236     void target(long Foo) {
4237       long Bar = __builtin_expect(Foo, true);
4238       /*[[p]]*/
4239     }
4240   )";
4241   runDataflow(
4242       Code,
4243       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4244          ASTContext &ASTCtx) {
4245         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4246         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4247 
4248         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4249         ASSERT_THAT(FooDecl, NotNull());
4250 
4251         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4252         ASSERT_THAT(BarDecl, NotNull());
4253 
4254         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4255       });
4256 }
4257 
4258 // `__builtin_expect` takes and returns a `long` argument, so other types
4259 // involve casts. This verifies that we identify the input and output in that
4260 // case.
4261 TEST(TransferTest, BuiltinExpectBoolArg) {
4262   std::string Code = R"(
4263     void target(bool Foo) {
4264       bool Bar = __builtin_expect(Foo, true);
4265       /*[[p]]*/
4266     }
4267   )";
4268   runDataflow(
4269       Code,
4270       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4271          ASTContext &ASTCtx) {
4272         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4273         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4274 
4275         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4276         ASSERT_THAT(FooDecl, NotNull());
4277 
4278         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4279         ASSERT_THAT(BarDecl, NotNull());
4280 
4281         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4282       });
4283 }
4284 
4285 TEST(TransferTest, BuiltinUnreachable) {
4286   std::string Code = R"(
4287     void target(bool Foo) {
4288       bool Bar = false;
4289       if (Foo)
4290         Bar = Foo;
4291       else
4292         __builtin_unreachable();
4293       (void)0;
4294       /*[[p]]*/
4295     }
4296   )";
4297   runDataflow(
4298       Code,
4299       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4300          ASTContext &ASTCtx) {
4301         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4302         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4303 
4304         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4305         ASSERT_THAT(FooDecl, NotNull());
4306 
4307         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4308         ASSERT_THAT(BarDecl, NotNull());
4309 
4310         // `__builtin_unreachable` promises that the code is
4311         // unreachable, so the compiler treats the "then" branch as the
4312         // only possible predecessor of this statement.
4313         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4314       });
4315 }
4316 
4317 TEST(TransferTest, BuiltinTrap) {
4318   std::string Code = R"(
4319     void target(bool Foo) {
4320       bool Bar = false;
4321       if (Foo)
4322         Bar = Foo;
4323       else
4324         __builtin_trap();
4325       (void)0;
4326       /*[[p]]*/
4327     }
4328   )";
4329   runDataflow(
4330       Code,
4331       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4332          ASTContext &ASTCtx) {
4333         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4334         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4335 
4336         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4337         ASSERT_THAT(FooDecl, NotNull());
4338 
4339         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4340         ASSERT_THAT(BarDecl, NotNull());
4341 
4342         // `__builtin_trap` ensures program termination, so only the
4343         // "then" branch is a predecessor of this statement.
4344         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4345       });
4346 }
4347 
4348 TEST(TransferTest, BuiltinDebugTrap) {
4349   std::string Code = R"(
4350     void target(bool Foo) {
4351       bool Bar = false;
4352       if (Foo)
4353         Bar = Foo;
4354       else
4355         __builtin_debugtrap();
4356       (void)0;
4357       /*[[p]]*/
4358     }
4359   )";
4360   runDataflow(
4361       Code,
4362       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4363          ASTContext &ASTCtx) {
4364         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4365         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4366 
4367         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4368         ASSERT_THAT(FooDecl, NotNull());
4369 
4370         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4371         ASSERT_THAT(BarDecl, NotNull());
4372 
4373         // `__builtin_debugtrap` doesn't ensure program termination.
4374         EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
4375       });
4376 }
4377 
4378 TEST(TransferTest, StaticIntSingleVarDecl) {
4379   std::string Code = R"(
4380     void target() {
4381       static int Foo;
4382       // [[p]]
4383     }
4384   )";
4385   runDataflow(
4386       Code,
4387       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4388          ASTContext &ASTCtx) {
4389         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4390         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4391 
4392         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4393         ASSERT_THAT(FooDecl, NotNull());
4394 
4395         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
4396         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
4397 
4398         const Value *FooVal = Env.getValue(*FooLoc);
4399         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
4400       });
4401 }
4402 
4403 TEST(TransferTest, StaticIntGroupVarDecl) {
4404   std::string Code = R"(
4405     void target() {
4406       static int Foo, Bar;
4407       (void)0;
4408       // [[p]]
4409     }
4410   )";
4411   runDataflow(
4412       Code,
4413       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4414          ASTContext &ASTCtx) {
4415         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4416         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4417 
4418         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4419         ASSERT_THAT(FooDecl, NotNull());
4420 
4421         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4422         ASSERT_THAT(BarDecl, NotNull());
4423 
4424         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
4425         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
4426 
4427         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4428         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
4429 
4430         const Value *FooVal = Env.getValue(*FooLoc);
4431         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
4432 
4433         const Value *BarVal = Env.getValue(*BarLoc);
4434         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
4435 
4436         EXPECT_NE(FooVal, BarVal);
4437       });
4438 }
4439 
4440 TEST(TransferTest, GlobalIntVarDecl) {
4441   std::string Code = R"(
4442     static int Foo;
4443 
4444     void target() {
4445       int Bar = Foo;
4446       int Baz = Foo;
4447       // [[p]]
4448     }
4449   )";
4450   runDataflow(
4451       Code,
4452       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4453          ASTContext &ASTCtx) {
4454         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4455         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4456 
4457         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4458         ASSERT_THAT(BarDecl, NotNull());
4459 
4460         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4461         ASSERT_THAT(BazDecl, NotNull());
4462 
4463         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4464         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4465         EXPECT_EQ(BarVal, BazVal);
4466       });
4467 }
4468 
4469 TEST(TransferTest, StaticMemberIntVarDecl) {
4470   std::string Code = R"(
4471     struct A {
4472       static int Foo;
4473     };
4474 
4475     void target(A a) {
4476       int Bar = a.Foo;
4477       int Baz = a.Foo;
4478       // [[p]]
4479     }
4480   )";
4481   runDataflow(
4482       Code,
4483       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4484          ASTContext &ASTCtx) {
4485         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4486         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4487 
4488         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4489         ASSERT_THAT(BarDecl, NotNull());
4490 
4491         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4492         ASSERT_THAT(BazDecl, NotNull());
4493 
4494         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4495         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4496         EXPECT_EQ(BarVal, BazVal);
4497       });
4498 }
4499 
4500 TEST(TransferTest, StaticMemberRefVarDecl) {
4501   std::string Code = R"(
4502     struct A {
4503       static int &Foo;
4504     };
4505 
4506     void target(A a) {
4507       int Bar = a.Foo;
4508       int Baz = a.Foo;
4509       // [[p]]
4510     }
4511   )";
4512   runDataflow(
4513       Code,
4514       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4515          ASTContext &ASTCtx) {
4516         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4517         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4518 
4519         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4520         ASSERT_THAT(BarDecl, NotNull());
4521 
4522         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4523         ASSERT_THAT(BazDecl, NotNull());
4524 
4525         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4526         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
4527         EXPECT_EQ(BarVal, BazVal);
4528       });
4529 }
4530 
4531 TEST(TransferTest, AssignMemberBeforeCopy) {
4532   std::string Code = R"(
4533     struct A {
4534       int Foo;
4535     };
4536 
4537     void target() {
4538       A A1;
4539       A A2;
4540       int Bar;
4541       A1.Foo = Bar;
4542       A2 = A1;
4543       // [[p]]
4544     }
4545   )";
4546   runDataflow(
4547       Code,
4548       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4549          ASTContext &ASTCtx) {
4550         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4551         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4552 
4553         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4554         ASSERT_THAT(FooDecl, NotNull());
4555 
4556         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4557         ASSERT_THAT(BarDecl, NotNull());
4558 
4559         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
4560         ASSERT_THAT(A1Decl, NotNull());
4561 
4562         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
4563         ASSERT_THAT(A2Decl, NotNull());
4564 
4565         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
4566 
4567         const auto &A2Loc =
4568             *cast<RecordStorageLocation>(Env.getStorageLocation(*A2Decl));
4569         EXPECT_EQ(getFieldValue(&A2Loc, *FooDecl, Env), BarVal);
4570       });
4571 }
4572 
4573 TEST(TransferTest, BooleanEquality) {
4574   std::string Code = R"(
4575     void target(bool Bar) {
4576       bool Foo = true;
4577       if (Bar == Foo) {
4578         (void)0;
4579         /*[[p-then]]*/
4580       } else {
4581         (void)0;
4582         /*[[p-else]]*/
4583       }
4584     }
4585   )";
4586   runDataflow(
4587       Code,
4588       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4589          ASTContext &ASTCtx) {
4590         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4591         const Environment &EnvThen =
4592             getEnvironmentAtAnnotation(Results, "p-then");
4593         const Environment &EnvElse =
4594             getEnvironmentAtAnnotation(Results, "p-else");
4595 
4596         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4597         ASSERT_THAT(BarDecl, NotNull());
4598 
4599         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4600         EXPECT_TRUE(EnvThen.proves(BarValThen));
4601 
4602         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4603         EXPECT_TRUE(EnvElse.proves(EnvElse.arena().makeNot(BarValElse)));
4604       });
4605 }
4606 
4607 TEST(TransferTest, BooleanInequality) {
4608   std::string Code = R"(
4609     void target(bool Bar) {
4610       bool Foo = true;
4611       if (Bar != Foo) {
4612         (void)0;
4613         /*[[p-then]]*/
4614       } else {
4615         (void)0;
4616         /*[[p-else]]*/
4617       }
4618     }
4619   )";
4620   runDataflow(
4621       Code,
4622       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4623          ASTContext &ASTCtx) {
4624         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
4625         const Environment &EnvThen =
4626             getEnvironmentAtAnnotation(Results, "p-then");
4627         const Environment &EnvElse =
4628             getEnvironmentAtAnnotation(Results, "p-else");
4629 
4630         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4631         ASSERT_THAT(BarDecl, NotNull());
4632 
4633         auto &BarValThen = getFormula(*BarDecl, EnvThen);
4634         EXPECT_TRUE(EnvThen.proves(EnvThen.arena().makeNot(BarValThen)));
4635 
4636         auto &BarValElse = getFormula(*BarDecl, EnvElse);
4637         EXPECT_TRUE(EnvElse.proves(BarValElse));
4638       });
4639 }
4640 
4641 TEST(TransferTest, IntegerLiteralEquality) {
4642   std::string Code = R"(
4643     void target() {
4644       bool equal = (42 == 42);
4645       // [[p]]
4646     }
4647   )";
4648   runDataflow(
4649       Code,
4650       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4651          ASTContext &ASTCtx) {
4652         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4653 
4654         auto &Equal =
4655             getValueForDecl<BoolValue>(ASTCtx, Env, "equal").formula();
4656         EXPECT_TRUE(Env.proves(Equal));
4657       });
4658 }
4659 
4660 TEST(TransferTest, CorrelatedBranches) {
4661   std::string Code = R"(
4662     void target(bool B, bool C) {
4663       if (B) {
4664         return;
4665       }
4666       (void)0;
4667       /*[[p0]]*/
4668       if (C) {
4669         B = true;
4670         /*[[p1]]*/
4671       }
4672       if (B) {
4673         (void)0;
4674         /*[[p2]]*/
4675       }
4676     }
4677   )";
4678   runDataflow(
4679       Code,
4680       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4681          ASTContext &ASTCtx) {
4682         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
4683 
4684         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
4685         ASSERT_THAT(CDecl, NotNull());
4686 
4687         {
4688           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
4689           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
4690           ASSERT_THAT(BDecl, NotNull());
4691           auto &BVal = getFormula(*BDecl, Env);
4692 
4693           EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal)));
4694         }
4695 
4696         {
4697           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
4698           auto &CVal = getFormula(*CDecl, Env);
4699           EXPECT_TRUE(Env.proves(CVal));
4700         }
4701 
4702         {
4703           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
4704           auto &CVal = getFormula(*CDecl, Env);
4705           EXPECT_TRUE(Env.proves(CVal));
4706         }
4707       });
4708 }
4709 
4710 TEST(TransferTest, LoopWithAssignmentConverges) {
4711   std::string Code = R"(
4712     bool foo();
4713 
4714     void target() {
4715        do {
4716         bool Bar = foo();
4717         if (Bar) break;
4718         (void)Bar;
4719         /*[[p]]*/
4720       } while (true);
4721     }
4722   )";
4723   // The key property that we are verifying is implicit in `runDataflow` --
4724   // namely, that the analysis succeeds, rather than hitting the maximum number
4725   // of iterations.
4726   runDataflow(
4727       Code,
4728       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4729          ASTContext &ASTCtx) {
4730         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4731         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4732 
4733         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4734         ASSERT_THAT(BarDecl, NotNull());
4735 
4736         auto &BarVal = getFormula(*BarDecl, Env);
4737         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4738       });
4739 }
4740 
4741 TEST(TransferTest, LoopWithStagedAssignments) {
4742   std::string Code = R"(
4743     bool foo();
4744 
4745     void target() {
4746       bool Bar = false;
4747       bool Err = false;
4748       while (foo()) {
4749         if (Bar)
4750           Err = true;
4751         Bar = true;
4752         /*[[p]]*/
4753       }
4754     }
4755   )";
4756   runDataflow(
4757       Code,
4758       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4759          ASTContext &ASTCtx) {
4760         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4761         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4762 
4763         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4764         ASSERT_THAT(BarDecl, NotNull());
4765         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
4766         ASSERT_THAT(ErrDecl, NotNull());
4767 
4768         auto &BarVal = getFormula(*BarDecl, Env);
4769         auto &ErrVal = getFormula(*ErrDecl, Env);
4770         EXPECT_TRUE(Env.proves(BarVal));
4771         // An unsound analysis, for example only evaluating the loop once, can
4772         // conclude that `Err` is false. So, we test that this conclusion is not
4773         // reached.
4774         EXPECT_FALSE(Env.proves(Env.arena().makeNot(ErrVal)));
4775       });
4776 }
4777 
4778 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
4779   std::string Code = R"(
4780     bool &foo();
4781 
4782     void target() {
4783        do {
4784         bool& Bar = foo();
4785         if (Bar) break;
4786         (void)Bar;
4787         /*[[p]]*/
4788       } while (true);
4789     }
4790   )";
4791   // The key property that we are verifying is that the analysis succeeds,
4792   // rather than hitting the maximum number of iterations.
4793   runDataflow(
4794       Code,
4795       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4796          ASTContext &ASTCtx) {
4797         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4798         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4799 
4800         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4801         ASSERT_THAT(BarDecl, NotNull());
4802 
4803         auto &BarVal = getFormula(*BarDecl, Env);
4804         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4805       });
4806 }
4807 
4808 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
4809   std::string Code = R"(
4810     struct Lookup {
4811       int x;
4812     };
4813 
4814     void target(Lookup val, bool b) {
4815       const Lookup* l = nullptr;
4816       while (b) {
4817         l = &val;
4818         /*[[p-inner]]*/
4819       }
4820       (void)0;
4821       /*[[p-outer]]*/
4822     }
4823   )";
4824   // The key property that we are verifying is implicit in `runDataflow` --
4825   // namely, that the analysis succeeds, rather than hitting the maximum number
4826   // of iterations.
4827   runDataflow(
4828       Code,
4829       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4830          ASTContext &ASTCtx) {
4831         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
4832         const Environment &InnerEnv =
4833             getEnvironmentAtAnnotation(Results, "p-inner");
4834         const Environment &OuterEnv =
4835             getEnvironmentAtAnnotation(Results, "p-outer");
4836 
4837         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
4838         ASSERT_THAT(ValDecl, NotNull());
4839 
4840         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
4841         ASSERT_THAT(LDecl, NotNull());
4842 
4843         // Inner.
4844         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
4845         ASSERT_THAT(LVal, NotNull());
4846 
4847         EXPECT_EQ(&LVal->getPointeeLoc(),
4848                   InnerEnv.getStorageLocation(*ValDecl));
4849 
4850         // Outer.
4851         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
4852         ASSERT_THAT(LVal, NotNull());
4853 
4854         // The loop body may not have been executed, so we should not conclude
4855         // that `l` points to `val`.
4856         EXPECT_NE(&LVal->getPointeeLoc(),
4857                   OuterEnv.getStorageLocation(*ValDecl));
4858       });
4859 }
4860 
4861 TEST(TransferTest, LoopDereferencingChangingPointerConverges) {
4862   std::string Code = R"cc(
4863     bool some_condition();
4864 
4865     void target(int i1, int i2) {
4866       int *p = &i1;
4867       while (true) {
4868         (void)*p;
4869         if (some_condition())
4870           p = &i1;
4871         else
4872           p = &i2;
4873       }
4874     }
4875   )cc";
4876   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4877 }
4878 
4879 TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
4880   std::string Code = R"cc(
4881     struct Lookup {
4882       int x;
4883     };
4884 
4885     bool some_condition();
4886 
4887     void target(Lookup l1, Lookup l2) {
4888       Lookup *l = &l1;
4889       while (true) {
4890         (void)l->x;
4891         if (some_condition())
4892           l = &l1;
4893         else
4894           l = &l2;
4895       }
4896     }
4897   )cc";
4898   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4899 }
4900 
4901 TEST(TransferTest, LoopWithShortCircuitedConditionConverges) {
4902   std::string Code = R"cc(
4903     bool foo();
4904 
4905     void target() {
4906       bool c = false;
4907       while (foo() || foo()) {
4908         c = true;
4909       }
4910     }
4911   )cc";
4912   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4913 }
4914 
4915 TEST(TransferTest, LoopCanProveInvariantForBoolean) {
4916   // Check that we can prove `b` is always false in the loop.
4917   // This test exercises the logic in `widenDistinctValues()` that preserves
4918   // information if the boolean can be proved to be either true or false in both
4919   // the previous and current iteration.
4920   std::string Code = R"cc(
4921     int return_int();
4922     void target() {
4923       bool b = return_int() == 0;
4924       if (b) return;
4925       while (true) {
4926         b;
4927         // [[p]]
4928         b = return_int() == 0;
4929         if (b) return;
4930       }
4931     }
4932   )cc";
4933   runDataflow(
4934       Code,
4935       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4936          ASTContext &ASTCtx) {
4937         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4938         auto &BVal = getValueForDecl<BoolValue>(ASTCtx, Env, "b");
4939         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal.formula())));
4940       });
4941 }
4942 
4943 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
4944   std::string Code = R"cc(
4945     union Union {
4946       int A;
4947       float B;
4948     };
4949 
4950     void foo() {
4951       Union A;
4952       Union B;
4953       A = B;
4954     }
4955   )cc";
4956   // This is a crash regression test when calling the transfer function on a
4957   // `CXXThisExpr` that refers to a union.
4958   runDataflow(
4959       Code,
4960       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
4961          ASTContext &) {},
4962       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
4963 }
4964 
4965 TEST(TransferTest, DoesNotCrashOnNullChildren) {
4966   std::string Code = (CoroutineLibrary + R"cc(
4967     task target() noexcept {
4968       co_return;
4969     }
4970   )cc")
4971                          .str();
4972   // This is a crash regression test when calling `AdornedCFG::build` on a
4973   // statement (in this case, the `CoroutineBodyStmt`) with null children.
4974   runDataflow(
4975       Code,
4976       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
4977          ASTContext &) {},
4978       LangStandard::lang_cxx20, /*ApplyBuiltinTransfer=*/true);
4979 }
4980 
4981 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
4982   std::string Code = R"(
4983     struct A {
4984       int Foo;
4985       int Bar;
4986     };
4987 
4988     void target() {
4989       int Qux;
4990       A Baz;
4991       Baz.Foo = Qux;
4992       auto &FooRef = Baz.Foo;
4993       auto &BarRef = Baz.Bar;
4994       auto &[BoundFooRef, BoundBarRef] = Baz;
4995       // [[p]]
4996     }
4997   )";
4998   runDataflow(
4999       Code,
5000       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5001          ASTContext &ASTCtx) {
5002         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5003         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5004 
5005         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
5006         ASSERT_THAT(FooRefDecl, NotNull());
5007 
5008         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
5009         ASSERT_THAT(BarRefDecl, NotNull());
5010 
5011         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
5012         ASSERT_THAT(QuxDecl, NotNull());
5013 
5014         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
5015         ASSERT_THAT(BoundFooRefDecl, NotNull());
5016 
5017         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
5018         ASSERT_THAT(BoundBarRefDecl, NotNull());
5019 
5020         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
5021         ASSERT_THAT(FooRefLoc, NotNull());
5022 
5023         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
5024         ASSERT_THAT(BarRefLoc, NotNull());
5025 
5026         const Value *QuxVal = Env.getValue(*QuxDecl);
5027         ASSERT_THAT(QuxVal, NotNull());
5028 
5029         const StorageLocation *BoundFooRefLoc =
5030             Env.getStorageLocation(*BoundFooRefDecl);
5031         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
5032 
5033         const StorageLocation *BoundBarRefLoc =
5034             Env.getStorageLocation(*BoundBarRefDecl);
5035         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
5036 
5037         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
5038       });
5039 }
5040 
5041 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
5042   std::string Code = R"(
5043     struct A {
5044       int &Foo;
5045       int &Bar;
5046     };
5047 
5048     void target(A Baz) {
5049       int Qux;
5050       Baz.Foo = Qux;
5051       auto &FooRef = Baz.Foo;
5052       auto &BarRef = Baz.Bar;
5053       auto &[BoundFooRef, BoundBarRef] = Baz;
5054       // [[p]]
5055     }
5056   )";
5057   runDataflow(
5058       Code,
5059       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5060          ASTContext &ASTCtx) {
5061         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5062         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5063 
5064         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
5065         ASSERT_THAT(FooRefDecl, NotNull());
5066 
5067         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
5068         ASSERT_THAT(BarRefDecl, NotNull());
5069 
5070         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
5071         ASSERT_THAT(QuxDecl, NotNull());
5072 
5073         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
5074         ASSERT_THAT(BoundFooRefDecl, NotNull());
5075 
5076         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
5077         ASSERT_THAT(BoundBarRefDecl, NotNull());
5078 
5079         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
5080         ASSERT_THAT(FooRefLoc, NotNull());
5081 
5082         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
5083         ASSERT_THAT(BarRefLoc, NotNull());
5084 
5085         const Value *QuxVal = Env.getValue(*QuxDecl);
5086         ASSERT_THAT(QuxVal, NotNull());
5087 
5088         const StorageLocation *BoundFooRefLoc =
5089             Env.getStorageLocation(*BoundFooRefDecl);
5090         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
5091 
5092         const StorageLocation *BoundBarRefLoc =
5093             Env.getStorageLocation(*BoundBarRefDecl);
5094         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
5095 
5096         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
5097       });
5098 }
5099 
5100 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
5101   std::string Code = R"(
5102     struct A {
5103       int Foo;
5104       int Bar;
5105     };
5106 
5107     void target() {
5108       int Qux;
5109       A Baz;
5110       Baz.Foo = Qux;
5111       auto &FooRef = Baz.Foo;
5112       auto &BarRef = Baz.Bar;
5113       auto [BoundFoo, BoundBar] = Baz;
5114       // [[p]]
5115     }
5116   )";
5117   runDataflow(
5118       Code,
5119       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5120          ASTContext &ASTCtx) {
5121         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5122         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5123 
5124         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
5125         ASSERT_THAT(FooRefDecl, NotNull());
5126 
5127         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
5128         ASSERT_THAT(BarRefDecl, NotNull());
5129 
5130         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5131         ASSERT_THAT(BoundFooDecl, NotNull());
5132 
5133         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5134         ASSERT_THAT(BoundBarDecl, NotNull());
5135 
5136         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
5137         ASSERT_THAT(QuxDecl, NotNull());
5138 
5139         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
5140         ASSERT_THAT(FooRefLoc, NotNull());
5141 
5142         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
5143         ASSERT_THAT(BarRefLoc, NotNull());
5144 
5145         const Value *QuxVal = Env.getValue(*QuxDecl);
5146         ASSERT_THAT(QuxVal, NotNull());
5147 
5148         const StorageLocation *BoundFooLoc =
5149             Env.getStorageLocation(*BoundFooDecl);
5150         EXPECT_NE(BoundFooLoc, FooRefLoc);
5151 
5152         const StorageLocation *BoundBarLoc =
5153             Env.getStorageLocation(*BoundBarDecl);
5154         EXPECT_NE(BoundBarLoc, BarRefLoc);
5155 
5156         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
5157       });
5158 }
5159 
5160 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
5161   std::string Code = R"(
5162     namespace std {
5163     using size_t = int;
5164     template <class> struct tuple_size;
5165     template <std::size_t, class> struct tuple_element;
5166     template <class...> class tuple;
5167 
5168     namespace {
5169     template <class T, T v>
5170     struct size_helper { static const T value = v; };
5171     } // namespace
5172 
5173     template <class... T>
5174     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
5175 
5176     template <std::size_t I, class... T>
5177     struct tuple_element<I, tuple<T...>> {
5178       using type =  __type_pack_element<I, T...>;
5179     };
5180 
5181     template <class...> class tuple {};
5182 
5183     template <std::size_t I, class... T>
5184     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
5185     } // namespace std
5186 
5187     std::tuple<bool, int> makeTuple();
5188 
5189     void target(bool B) {
5190       auto [BoundFoo, BoundBar] = makeTuple();
5191       bool Baz;
5192       // Include if-then-else to test interaction of `BindingDecl` with join.
5193       if (B) {
5194         Baz = BoundFoo;
5195         (void)BoundBar;
5196         // [[p1]]
5197       } else {
5198         Baz = BoundFoo;
5199       }
5200       (void)0;
5201       // [[p2]]
5202     }
5203   )";
5204   runDataflow(
5205       Code,
5206       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5207          ASTContext &ASTCtx) {
5208         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
5209         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
5210 
5211         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5212         ASSERT_THAT(BoundFooDecl, NotNull());
5213 
5214         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5215         ASSERT_THAT(BoundBarDecl, NotNull());
5216 
5217         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5218         ASSERT_THAT(BazDecl, NotNull());
5219 
5220         // BindingDecls always map to references -- either lvalue or rvalue, so
5221         // we still need to skip here.
5222         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
5223         ASSERT_THAT(BoundFooValue, NotNull());
5224         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
5225 
5226         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
5227         ASSERT_THAT(BoundBarValue, NotNull());
5228         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
5229 
5230         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
5231         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
5232 
5233         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
5234 
5235         // Test that `BoundFooDecl` retains the value we expect, after the join.
5236         BoundFooValue = Env2.getValue(*BoundFooDecl);
5237         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
5238       });
5239 }
5240 
5241 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
5242   std::string Code = R"(
5243     namespace std {
5244     using size_t = int;
5245     template <class> struct tuple_size;
5246     template <std::size_t, class> struct tuple_element;
5247     template <class...> class tuple;
5248 
5249     namespace {
5250     template <class T, T v>
5251     struct size_helper { static const T value = v; };
5252     } // namespace
5253 
5254     template <class... T>
5255     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
5256 
5257     template <std::size_t I, class... T>
5258     struct tuple_element<I, tuple<T...>> {
5259       using type =  __type_pack_element<I, T...>;
5260     };
5261 
5262     template <class...> class tuple {};
5263 
5264     template <std::size_t I, class... T>
5265     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
5266     } // namespace std
5267 
5268     std::tuple<bool, int> &getTuple();
5269 
5270     void target(bool B) {
5271       auto &[BoundFoo, BoundBar] = getTuple();
5272       bool Baz;
5273       // Include if-then-else to test interaction of `BindingDecl` with join.
5274       if (B) {
5275         Baz = BoundFoo;
5276         (void)BoundBar;
5277         // [[p1]]
5278       } else {
5279         Baz = BoundFoo;
5280       }
5281       (void)0;
5282       // [[p2]]
5283     }
5284   )";
5285   runDataflow(
5286       Code,
5287       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5288          ASTContext &ASTCtx) {
5289         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
5290         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
5291 
5292         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
5293         ASSERT_THAT(BoundFooDecl, NotNull());
5294 
5295         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
5296         ASSERT_THAT(BoundBarDecl, NotNull());
5297 
5298         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5299         ASSERT_THAT(BazDecl, NotNull());
5300 
5301         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
5302         ASSERT_THAT(BoundFooValue, NotNull());
5303         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
5304 
5305         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
5306         ASSERT_THAT(BoundBarValue, NotNull());
5307         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
5308 
5309         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
5310         // works as expected. We don't test aliasing properties of the
5311         // reference, because we don't model `std::get` and so have no way to
5312         // equate separate references into the tuple.
5313         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
5314 
5315         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
5316 
5317         // Test that `BoundFooDecl` retains the value we expect, after the join.
5318         BoundFooValue = Env2.getValue(*BoundFooDecl);
5319         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
5320       });
5321 }
5322 
5323 TEST(TransferTest, BinaryOperatorComma) {
5324   std::string Code = R"(
5325     void target(int Foo, int Bar) {
5326       int &Baz = (Foo, Bar);
5327       // [[p]]
5328     }
5329   )";
5330   runDataflow(
5331       Code,
5332       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5333          ASTContext &ASTCtx) {
5334         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5335         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5336 
5337         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5338         ASSERT_THAT(BarDecl, NotNull());
5339 
5340         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5341         ASSERT_THAT(BazDecl, NotNull());
5342 
5343         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
5344         ASSERT_THAT(BarLoc, NotNull());
5345 
5346         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
5347         EXPECT_EQ(BazLoc, BarLoc);
5348       });
5349 }
5350 
5351 TEST(TransferTest, ConditionalOperatorValue) {
5352   std::string Code = R"(
5353     void target(bool Cond, bool B1, bool B2) {
5354       bool JoinSame = Cond ? B1 : B1;
5355       bool JoinDifferent = Cond ? B1 : B2;
5356       // [[p]]
5357     }
5358   )";
5359   runDataflow(
5360       Code,
5361       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5362          ASTContext &ASTCtx) {
5363         Environment Env = getEnvironmentAtAnnotation(Results, "p").fork();
5364 
5365         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "B1");
5366         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "B2");
5367         auto &JoinSame = getValueForDecl<BoolValue>(ASTCtx, Env, "JoinSame");
5368         auto &JoinDifferent =
5369             getValueForDecl<BoolValue>(ASTCtx, Env, "JoinDifferent");
5370 
5371         EXPECT_EQ(&JoinSame, &B1);
5372 
5373         const Formula &JoinDifferentEqB1 =
5374             Env.arena().makeEquals(JoinDifferent.formula(), B1.formula());
5375         EXPECT_TRUE(Env.allows(JoinDifferentEqB1));
5376         EXPECT_FALSE(Env.proves(JoinDifferentEqB1));
5377 
5378         const Formula &JoinDifferentEqB2 =
5379             Env.arena().makeEquals(JoinDifferent.formula(), B2.formula());
5380         EXPECT_TRUE(Env.allows(JoinDifferentEqB2));
5381         EXPECT_FALSE(Env.proves(JoinDifferentEqB1));
5382       });
5383 }
5384 
5385 TEST(TransferTest, ConditionalOperatorLocation) {
5386   std::string Code = R"(
5387     void target(bool Cond, int I1, int I2) {
5388       int &JoinSame = Cond ? I1 : I1;
5389       int &JoinDifferent = Cond ? I1 : I2;
5390       // [[p]]
5391     }
5392   )";
5393   runDataflow(
5394       Code,
5395       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5396          ASTContext &ASTCtx) {
5397         Environment Env = getEnvironmentAtAnnotation(Results, "p").fork();
5398 
5399         StorageLocation &I1 = getLocForDecl(ASTCtx, Env, "I1");
5400         StorageLocation &I2 = getLocForDecl(ASTCtx, Env, "I2");
5401         StorageLocation &JoinSame = getLocForDecl(ASTCtx, Env, "JoinSame");
5402         StorageLocation &JoinDifferent =
5403             getLocForDecl(ASTCtx, Env, "JoinDifferent");
5404 
5405         EXPECT_EQ(&JoinSame, &I1);
5406 
5407         EXPECT_NE(&JoinDifferent, &I1);
5408         EXPECT_NE(&JoinDifferent, &I2);
5409       });
5410 }
5411 
5412 TEST(TransferTest, ConditionalOperatorOnConstantExpr) {
5413   // This is a regression test: We used to crash when a `ConstantExpr` was used
5414   // in the branches of a conditional operator.
5415   std::string Code = R"cc(
5416     consteval bool identity(bool B) { return B; }
5417     void target(bool Cond) {
5418       bool JoinTrueTrue = Cond ? identity(true) : identity(true);
5419       bool JoinTrueFalse = Cond ? identity(true) : identity(false);
5420       // [[p]]
5421     }
5422   )cc";
5423   runDataflow(
5424       Code,
5425       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5426          ASTContext &ASTCtx) {
5427         Environment Env = getEnvironmentAtAnnotation(Results, "p").fork();
5428 
5429         auto &JoinTrueTrue =
5430             getValueForDecl<BoolValue>(ASTCtx, Env, "JoinTrueTrue");
5431         // FIXME: This test documents the current behavior, namely that we
5432         // don't actually use the constant result of the `ConstantExpr` and
5433         // instead treat it like a normal function call.
5434         EXPECT_EQ(JoinTrueTrue.formula().kind(), Formula::Kind::AtomRef);
5435         // EXPECT_TRUE(JoinTrueTrue.formula().literal());
5436 
5437         auto &JoinTrueFalse =
5438             getValueForDecl<BoolValue>(ASTCtx, Env, "JoinTrueFalse");
5439         EXPECT_EQ(JoinTrueFalse.formula().kind(), Formula::Kind::AtomRef);
5440       },
5441       LangStandard::lang_cxx20);
5442 }
5443 
5444 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
5445   std::string Code = R"(
5446     void target(bool Foo) {
5447       if (Foo) {
5448         (void)0;
5449         // [[if_then]]
5450       } else {
5451         (void)0;
5452         // [[if_else]]
5453       }
5454     }
5455   )";
5456   runDataflow(
5457       Code,
5458       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5459          ASTContext &ASTCtx) {
5460         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
5461         const Environment &ThenEnv =
5462             getEnvironmentAtAnnotation(Results, "if_then");
5463         const Environment &ElseEnv =
5464             getEnvironmentAtAnnotation(Results, "if_else");
5465 
5466         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5467         ASSERT_THAT(FooDecl, NotNull());
5468 
5469         auto &ThenFooVal= getFormula(*FooDecl, ThenEnv);
5470         EXPECT_TRUE(ThenEnv.proves(ThenFooVal));
5471 
5472         auto &ElseFooVal = getFormula(*FooDecl, ElseEnv);
5473         EXPECT_TRUE(ElseEnv.proves(ElseEnv.arena().makeNot(ElseFooVal)));
5474       });
5475 }
5476 
5477 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
5478   std::string Code = R"(
5479     void target(bool Foo) {
5480       while (Foo) {
5481         (void)0;
5482         // [[loop_body]]
5483       }
5484       (void)0;
5485       // [[after_loop]]
5486     }
5487   )";
5488   runDataflow(
5489       Code,
5490       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5491          ASTContext &ASTCtx) {
5492         ASSERT_THAT(Results.keys(),
5493                     UnorderedElementsAre("loop_body", "after_loop"));
5494         const Environment &LoopBodyEnv =
5495             getEnvironmentAtAnnotation(Results, "loop_body");
5496         const Environment &AfterLoopEnv =
5497             getEnvironmentAtAnnotation(Results, "after_loop");
5498 
5499         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5500         ASSERT_THAT(FooDecl, NotNull());
5501 
5502         auto &LoopBodyFooVal = getFormula(*FooDecl, LoopBodyEnv);
5503         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
5504 
5505         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5506         EXPECT_TRUE(
5507             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
5508       });
5509 }
5510 
5511 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
5512   std::string Code = R"(
5513     void target(bool Foo) {
5514       bool Bar = true;
5515       do {
5516         (void)0;
5517         // [[loop_body]]
5518         Bar = false;
5519       } while (Foo);
5520       (void)0;
5521       // [[after_loop]]
5522     }
5523   )";
5524   runDataflow(
5525       Code,
5526       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5527          ASTContext &ASTCtx) {
5528         ASSERT_THAT(Results.keys(),
5529                     UnorderedElementsAre("loop_body", "after_loop"));
5530         const Environment &LoopBodyEnv =
5531             getEnvironmentAtAnnotation(Results, "loop_body");
5532         const Environment &AfterLoopEnv =
5533             getEnvironmentAtAnnotation(Results, "after_loop");
5534         auto &A = AfterLoopEnv.arena();
5535 
5536         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5537         ASSERT_THAT(FooDecl, NotNull());
5538 
5539         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5540         ASSERT_THAT(BarDecl, NotNull());
5541 
5542         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5543         auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv);
5544         EXPECT_TRUE(
5545             LoopBodyEnv.proves(A.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
5546 
5547         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5548         auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv);
5549         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopFooVal)));
5550         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopBarVal)));
5551       });
5552 }
5553 
5554 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
5555   std::string Code = R"(
5556     void target(bool Foo) {
5557       for (; Foo;) {
5558         (void)0;
5559         // [[loop_body]]
5560       }
5561       (void)0;
5562       // [[after_loop]]
5563     }
5564   )";
5565   runDataflow(
5566       Code,
5567       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5568          ASTContext &ASTCtx) {
5569         ASSERT_THAT(Results.keys(),
5570                     UnorderedElementsAre("loop_body", "after_loop"));
5571         const Environment &LoopBodyEnv =
5572             getEnvironmentAtAnnotation(Results, "loop_body");
5573         const Environment &AfterLoopEnv =
5574             getEnvironmentAtAnnotation(Results, "after_loop");
5575 
5576         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5577         ASSERT_THAT(FooDecl, NotNull());
5578 
5579         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5580         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
5581 
5582         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
5583         EXPECT_TRUE(
5584             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
5585       });
5586 }
5587 
5588 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
5589   std::string Code = R"(
5590     void target(bool Foo) {
5591       for (;;) {
5592         (void)0;
5593         // [[loop_body]]
5594       }
5595     }
5596   )";
5597   runDataflow(
5598       Code,
5599       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5600          ASTContext &ASTCtx) {
5601         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
5602         const Environment &LoopBodyEnv =
5603             getEnvironmentAtAnnotation(Results, "loop_body");
5604 
5605         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5606         ASSERT_THAT(FooDecl, NotNull());
5607 
5608         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
5609         EXPECT_FALSE(LoopBodyEnv.proves(LoopBodyFooVal));
5610       });
5611 }
5612 
5613 TEST(TransferTest, ContextSensitiveOptionDisabled) {
5614   std::string Code = R"(
5615     bool GiveBool();
5616     void SetBool(bool &Var) { Var = true; }
5617 
5618     void target() {
5619       bool Foo = GiveBool();
5620       SetBool(Foo);
5621       // [[p]]
5622     }
5623   )";
5624   runDataflow(
5625       Code,
5626       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5627          ASTContext &ASTCtx) {
5628         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5629         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5630 
5631         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5632         ASSERT_THAT(FooDecl, NotNull());
5633 
5634         auto &FooVal = getFormula(*FooDecl, Env);
5635         EXPECT_FALSE(Env.proves(FooVal));
5636         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5637       },
5638       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
5639 }
5640 
5641 TEST(TransferTest, ContextSensitiveReturnReference) {
5642   std::string Code = R"(
5643     class S {};
5644     S& target(bool b, S &s) {
5645       return s;
5646       // [[p]]
5647     }
5648   )";
5649   runDataflow(
5650       Code,
5651       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5652          ASTContext &ASTCtx) {
5653         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5654 
5655         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5656         ASSERT_THAT(SDecl, NotNull());
5657 
5658         auto *SLoc = Env.getStorageLocation(*SDecl);
5659         ASSERT_THAT(SLoc, NotNull());
5660 
5661         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
5662       },
5663       {BuiltinOptions{ContextSensitiveOptions{}}});
5664 }
5665 
5666 // This test is a regression test, based on a real crash.
5667 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
5668   std::string Code = R"(
5669     class S {};
5670     S& target(bool b, S &s) {
5671       return b ? s : s;
5672       // [[p]]
5673     }
5674   )";
5675   runDataflow(
5676       Code,
5677       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5678          ASTContext &ASTCtx) {
5679         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5680         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5681 
5682         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5683         ASSERT_THAT(SDecl, NotNull());
5684 
5685         auto *SLoc = Env.getStorageLocation(*SDecl);
5686         EXPECT_THAT(SLoc, NotNull());
5687 
5688         auto *Loc = Env.getReturnStorageLocation();
5689         EXPECT_THAT(Loc, NotNull());
5690 
5691         EXPECT_EQ(Loc, SLoc);
5692       },
5693       {BuiltinOptions{ContextSensitiveOptions{}}});
5694 }
5695 
5696 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
5697   std::string Code = R"(
5698     class S {};
5699     S &callee(bool b, S &s1_parm, S &s2_parm) {
5700       if (b)
5701         return s1_parm;
5702       else
5703         return s2_parm;
5704     }
5705     void target(bool b) {
5706       S s1;
5707       S s2;
5708       S &return_s1 = s1;
5709       S &return_s2 = s2;
5710       S &return_dont_know = callee(b, s1, s2);
5711       // [[p]]
5712     }
5713   )";
5714   runDataflow(
5715       Code,
5716       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5717          ASTContext &ASTCtx) {
5718         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5719 
5720         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
5721         ASSERT_THAT(S1, NotNull());
5722         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
5723         ASSERT_THAT(S2, NotNull());
5724         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
5725         ASSERT_THAT(ReturnS1, NotNull());
5726         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
5727         ASSERT_THAT(ReturnS2, NotNull());
5728         const ValueDecl *ReturnDontKnow =
5729             findValueDecl(ASTCtx, "return_dont_know");
5730         ASSERT_THAT(ReturnDontKnow, NotNull());
5731 
5732         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
5733         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
5734 
5735         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
5736         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
5737 
5738         // In the case where we don't have a consistent storage location for
5739         // the return value, the framework creates a new storage location, which
5740         // should be different from the storage locations of `s1` and `s2`.
5741         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
5742         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
5743       },
5744       {BuiltinOptions{ContextSensitiveOptions{}}});
5745 }
5746 
5747 TEST(TransferTest, ContextSensitiveDepthZero) {
5748   std::string Code = R"(
5749     bool GiveBool();
5750     void SetBool(bool &Var) { Var = true; }
5751 
5752     void target() {
5753       bool Foo = GiveBool();
5754       SetBool(Foo);
5755       // [[p]]
5756     }
5757   )";
5758   runDataflow(
5759       Code,
5760       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5761          ASTContext &ASTCtx) {
5762         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5763         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5764 
5765         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5766         ASSERT_THAT(FooDecl, NotNull());
5767 
5768         auto &FooVal = getFormula(*FooDecl, Env);
5769         EXPECT_FALSE(Env.proves(FooVal));
5770         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5771       },
5772       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
5773 }
5774 
5775 TEST(TransferTest, ContextSensitiveSetTrue) {
5776   std::string Code = R"(
5777     bool GiveBool();
5778     void SetBool(bool &Var) { Var = true; }
5779 
5780     void target() {
5781       bool Foo = GiveBool();
5782       SetBool(Foo);
5783       // [[p]]
5784     }
5785   )";
5786   runDataflow(
5787       Code,
5788       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5789          ASTContext &ASTCtx) {
5790         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5791         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5792 
5793         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5794         ASSERT_THAT(FooDecl, NotNull());
5795 
5796         auto &FooVal = getFormula(*FooDecl, Env);
5797         EXPECT_TRUE(Env.proves(FooVal));
5798       },
5799       {BuiltinOptions{ContextSensitiveOptions{}}});
5800 }
5801 
5802 TEST(TransferTest, ContextSensitiveSetFalse) {
5803   std::string Code = R"(
5804     bool GiveBool();
5805     void SetBool(bool &Var) { Var = false; }
5806 
5807     void target() {
5808       bool Foo = GiveBool();
5809       SetBool(Foo);
5810       // [[p]]
5811     }
5812   )";
5813   runDataflow(
5814       Code,
5815       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5816          ASTContext &ASTCtx) {
5817         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5818         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5819 
5820         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5821         ASSERT_THAT(FooDecl, NotNull());
5822 
5823         auto &FooVal = getFormula(*FooDecl, Env);
5824         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
5825       },
5826       {BuiltinOptions{ContextSensitiveOptions{}}});
5827 }
5828 
5829 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
5830   std::string Code = R"(
5831     bool GiveBool();
5832     void SetBool(bool &Var, bool Val) { Var = Val; }
5833 
5834     void target() {
5835       bool Foo = GiveBool();
5836       bool Bar = GiveBool();
5837       SetBool(Foo, true);
5838       SetBool(Bar, false);
5839       // [[p]]
5840     }
5841   )";
5842   runDataflow(
5843       Code,
5844       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5845          ASTContext &ASTCtx) {
5846         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5847         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5848         auto &A = Env.arena();
5849 
5850         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5851         ASSERT_THAT(FooDecl, NotNull());
5852 
5853         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5854         ASSERT_THAT(BarDecl, NotNull());
5855 
5856         auto &FooVal = getFormula(*FooDecl, Env);
5857         EXPECT_TRUE(Env.proves(FooVal));
5858         EXPECT_FALSE(Env.proves(A.makeNot(FooVal)));
5859 
5860         auto &BarVal = getFormula(*BarDecl, Env);
5861         EXPECT_FALSE(Env.proves(BarVal));
5862         EXPECT_TRUE(Env.proves(A.makeNot(BarVal)));
5863       },
5864       {BuiltinOptions{ContextSensitiveOptions{}}});
5865 }
5866 
5867 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
5868   std::string Code = R"(
5869     bool GiveBool();
5870     void SetBool1(bool &Var) { Var = true; }
5871     void SetBool2(bool &Var) { SetBool1(Var); }
5872 
5873     void target() {
5874       bool Foo = GiveBool();
5875       SetBool2(Foo);
5876       // [[p]]
5877     }
5878   )";
5879   runDataflow(
5880       Code,
5881       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5882          ASTContext &ASTCtx) {
5883         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5884         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5885 
5886         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5887         ASSERT_THAT(FooDecl, NotNull());
5888 
5889         auto &FooVal = getFormula(*FooDecl, Env);
5890         EXPECT_FALSE(Env.proves(FooVal));
5891         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5892       },
5893       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
5894 }
5895 
5896 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
5897   std::string Code = R"(
5898     bool GiveBool();
5899     void SetBool1(bool &Var) { Var = true; }
5900     void SetBool2(bool &Var) { SetBool1(Var); }
5901 
5902     void target() {
5903       bool Foo = GiveBool();
5904       SetBool2(Foo);
5905       // [[p]]
5906     }
5907   )";
5908   runDataflow(
5909       Code,
5910       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5911          ASTContext &ASTCtx) {
5912         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5913         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5914 
5915         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5916         ASSERT_THAT(FooDecl, NotNull());
5917 
5918         auto &FooVal = getFormula(*FooDecl, Env);
5919         EXPECT_TRUE(Env.proves(FooVal));
5920       },
5921       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5922 }
5923 
5924 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
5925   std::string Code = R"(
5926     bool GiveBool();
5927     void SetBool1(bool &Var) { Var = true; }
5928     void SetBool2(bool &Var) { SetBool1(Var); }
5929     void SetBool3(bool &Var) { SetBool2(Var); }
5930 
5931     void target() {
5932       bool Foo = GiveBool();
5933       SetBool3(Foo);
5934       // [[p]]
5935     }
5936   )";
5937   runDataflow(
5938       Code,
5939       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5940          ASTContext &ASTCtx) {
5941         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5942         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5943 
5944         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5945         ASSERT_THAT(FooDecl, NotNull());
5946 
5947         auto &FooVal = getFormula(*FooDecl, Env);
5948         EXPECT_FALSE(Env.proves(FooVal));
5949         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5950       },
5951       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5952 }
5953 
5954 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
5955   std::string Code = R"(
5956     bool GiveBool();
5957     void SetBool1(bool &Var) { Var = true; }
5958     void SetBool2(bool &Var) { SetBool1(Var); }
5959     void SetBool3(bool &Var) { SetBool2(Var); }
5960 
5961     void target() {
5962       bool Foo = GiveBool();
5963       SetBool3(Foo);
5964       // [[p]]
5965     }
5966   )";
5967   runDataflow(
5968       Code,
5969       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5970          ASTContext &ASTCtx) {
5971         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5972         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5973 
5974         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5975         ASSERT_THAT(FooDecl, NotNull());
5976 
5977         auto &FooVal = getFormula(*FooDecl, Env);
5978         EXPECT_TRUE(Env.proves(FooVal));
5979       },
5980       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
5981 }
5982 
5983 TEST(TransferTest, ContextSensitiveMutualRecursion) {
5984   std::string Code = R"(
5985     bool Pong(bool X, bool Y);
5986 
5987     bool Ping(bool X, bool Y) {
5988       if (X) {
5989         return Y;
5990       } else {
5991         return Pong(!X, Y);
5992       }
5993     }
5994 
5995     bool Pong(bool X, bool Y) {
5996       if (Y) {
5997         return X;
5998       } else {
5999         return Ping(X, !Y);
6000       }
6001     }
6002 
6003     void target() {
6004       bool Foo = Ping(false, false);
6005       // [[p]]
6006     }
6007   )";
6008   runDataflow(
6009       Code,
6010       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6011          ASTContext &ASTCtx) {
6012         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6013         // The analysis doesn't crash...
6014         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6015 
6016         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6017         ASSERT_THAT(FooDecl, NotNull());
6018 
6019         auto &FooVal = getFormula(*FooDecl, Env);
6020         // ... but it also can't prove anything here.
6021         EXPECT_FALSE(Env.proves(FooVal));
6022         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
6023       },
6024       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
6025 }
6026 
6027 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
6028   std::string Code = R"(
6029     void SetBools(bool &Var1, bool &Var2) {
6030       Var1 = true;
6031       Var2 = false;
6032     }
6033 
6034     void target() {
6035       bool Foo = false;
6036       bool Bar = true;
6037       SetBools(Foo, Bar);
6038       // [[p]]
6039     }
6040   )";
6041   runDataflow(
6042       Code,
6043       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6044          ASTContext &ASTCtx) {
6045         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6046         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6047 
6048         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6049         ASSERT_THAT(FooDecl, NotNull());
6050 
6051         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6052         ASSERT_THAT(BarDecl, NotNull());
6053 
6054         auto &FooVal = getFormula(*FooDecl, Env);
6055         EXPECT_TRUE(Env.proves(FooVal));
6056         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
6057 
6058         auto &BarVal = getFormula(*BarDecl, Env);
6059         EXPECT_FALSE(Env.proves(BarVal));
6060         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
6061       },
6062       {BuiltinOptions{ContextSensitiveOptions{}}});
6063 }
6064 
6065 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
6066   std::string Code = R"(
6067     void IfCond(bool Cond, bool &Then, bool &Else) {
6068       if (Cond) {
6069         Then = true;
6070       } else {
6071         Else = true;
6072       }
6073     }
6074 
6075     void target() {
6076       bool Foo = false;
6077       bool Bar = false;
6078       bool Baz = false;
6079       IfCond(Foo, Bar, Baz);
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 *BarDecl = findValueDecl(ASTCtx, "Bar");
6091         ASSERT_THAT(BarDecl, NotNull());
6092 
6093         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
6094         ASSERT_THAT(BazDecl, NotNull());
6095 
6096         auto &BarVal = getFormula(*BarDecl, Env);
6097         EXPECT_FALSE(Env.proves(BarVal));
6098         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
6099 
6100         auto &BazVal = getFormula(*BazDecl, Env);
6101         EXPECT_TRUE(Env.proves(BazVal));
6102         EXPECT_FALSE(Env.proves(Env.arena().makeNot(BazVal)));
6103       },
6104       {BuiltinOptions{ContextSensitiveOptions{}}});
6105 }
6106 
6107 TEST(TransferTest, ContextSensitiveReturnVoid) {
6108   std::string Code = R"(
6109     void Noop() { return; }
6110 
6111     void target() {
6112       Noop();
6113       // [[p]]
6114     }
6115   )";
6116   runDataflow(
6117       Code,
6118       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6119          ASTContext &ASTCtx) {
6120         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6121         // This just tests that the analysis doesn't crash.
6122       },
6123       {BuiltinOptions{ContextSensitiveOptions{}}});
6124 }
6125 
6126 TEST(TransferTest, ContextSensitiveReturnTrue) {
6127   std::string Code = R"(
6128     bool GiveBool() { return true; }
6129 
6130     void target() {
6131       bool Foo = GiveBool();
6132       // [[p]]
6133     }
6134   )";
6135   runDataflow(
6136       Code,
6137       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6138          ASTContext &ASTCtx) {
6139         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6140         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6141 
6142         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6143         ASSERT_THAT(FooDecl, NotNull());
6144 
6145         auto &FooVal = getFormula(*FooDecl, Env);
6146         EXPECT_TRUE(Env.proves(FooVal));
6147       },
6148       {BuiltinOptions{ContextSensitiveOptions{}}});
6149 }
6150 
6151 TEST(TransferTest, ContextSensitiveReturnFalse) {
6152   std::string Code = R"(
6153     bool GiveBool() { return false; }
6154 
6155     void target() {
6156       bool Foo = GiveBool();
6157       // [[p]]
6158     }
6159   )";
6160   runDataflow(
6161       Code,
6162       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6163          ASTContext &ASTCtx) {
6164         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6165         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6166 
6167         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6168         ASSERT_THAT(FooDecl, NotNull());
6169 
6170         auto &FooVal = getFormula(*FooDecl, Env);
6171         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
6172       },
6173       {BuiltinOptions{ContextSensitiveOptions{}}});
6174 }
6175 
6176 TEST(TransferTest, ContextSensitiveReturnArg) {
6177   std::string Code = R"(
6178     bool GiveBool();
6179     bool GiveBack(bool Arg) { return Arg; }
6180 
6181     void target() {
6182       bool Foo = GiveBool();
6183       bool Bar = GiveBack(Foo);
6184       bool Baz = Foo == Bar;
6185       // [[p]]
6186     }
6187   )";
6188   runDataflow(
6189       Code,
6190       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6191          ASTContext &ASTCtx) {
6192         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6193         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6194 
6195         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
6196         ASSERT_THAT(BazDecl, NotNull());
6197 
6198         auto &BazVal = getFormula(*BazDecl, Env);
6199         EXPECT_TRUE(Env.proves(BazVal));
6200       },
6201       {BuiltinOptions{ContextSensitiveOptions{}}});
6202 }
6203 
6204 TEST(TransferTest, ContextSensitiveReturnInt) {
6205   std::string Code = R"(
6206     int identity(int x) { return x; }
6207 
6208     void target() {
6209       int y = identity(42);
6210       // [[p]]
6211     }
6212   )";
6213   runDataflow(
6214       Code,
6215       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6216          ASTContext &ASTCtx) {
6217         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6218         // This just tests that the analysis doesn't crash.
6219       },
6220       {BuiltinOptions{ContextSensitiveOptions{}}});
6221 }
6222 
6223 TEST(TransferTest, ContextSensitiveReturnRecord) {
6224   std::string Code = R"(
6225     struct S {
6226       bool B;
6227     };
6228 
6229     S makeS(bool BVal) { return {BVal}; }
6230 
6231     void target() {
6232       S FalseS = makeS(false);
6233       S TrueS = makeS(true);
6234       // [[p]]
6235     }
6236   )";
6237   runDataflow(
6238       Code,
6239       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6240          ASTContext &ASTCtx) {
6241         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6242 
6243         auto &FalseSLoc =
6244             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "FalseS");
6245         auto &TrueSLoc =
6246             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "TrueS");
6247 
6248         EXPECT_EQ(getFieldValue(&FalseSLoc, "B", ASTCtx, Env),
6249                   &Env.getBoolLiteralValue(false));
6250         EXPECT_EQ(getFieldValue(&TrueSLoc, "B", ASTCtx, Env),
6251                   &Env.getBoolLiteralValue(true));
6252       },
6253       {BuiltinOptions{ContextSensitiveOptions{}}});
6254 }
6255 
6256 TEST(TransferTest, ContextSensitiveReturnSelfReferentialRecord) {
6257   std::string Code = R"(
6258     struct S {
6259       S() { self = this; }
6260       S *self;
6261     };
6262 
6263     S makeS() {
6264       // RVO guarantees that this will be constructed directly into `MyS`.
6265       return S();
6266     }
6267 
6268     void target() {
6269       S MyS = makeS();
6270       // [[p]]
6271     }
6272   )";
6273   runDataflow(
6274       Code,
6275       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6276          ASTContext &ASTCtx) {
6277         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6278 
6279         auto &MySLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "MyS");
6280 
6281         auto *SelfVal =
6282             cast<PointerValue>(getFieldValue(&MySLoc, "self", ASTCtx, Env));
6283         EXPECT_EQ(&SelfVal->getPointeeLoc(), &MySLoc);
6284       },
6285       {BuiltinOptions{ContextSensitiveOptions{}}});
6286 }
6287 
6288 TEST(TransferTest, ContextSensitiveMethodLiteral) {
6289   std::string Code = R"(
6290     class MyClass {
6291     public:
6292       bool giveBool() { return true; }
6293     };
6294 
6295     void target() {
6296       MyClass MyObj;
6297       bool Foo = MyObj.giveBool();
6298       // [[p]]
6299     }
6300   )";
6301   runDataflow(
6302       Code,
6303       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6304          ASTContext &ASTCtx) {
6305         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6306         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6307 
6308         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6309         ASSERT_THAT(FooDecl, NotNull());
6310 
6311         auto &FooVal = getFormula(*FooDecl, Env);
6312         EXPECT_TRUE(Env.proves(FooVal));
6313       },
6314       {BuiltinOptions{ContextSensitiveOptions{}}});
6315 }
6316 
6317 TEST(TransferTest, ContextSensitiveMethodGetter) {
6318   std::string Code = R"(
6319     class MyClass {
6320     public:
6321       bool getField() { return Field; }
6322 
6323       bool Field;
6324     };
6325 
6326     void target() {
6327       MyClass MyObj;
6328       MyObj.Field = true;
6329       bool Foo = MyObj.getField();
6330       // [[p]]
6331     }
6332   )";
6333   runDataflow(
6334       Code,
6335       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6336          ASTContext &ASTCtx) {
6337         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6338         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6339 
6340         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6341         ASSERT_THAT(FooDecl, NotNull());
6342 
6343         auto &FooVal = getFormula(*FooDecl, Env);
6344         EXPECT_TRUE(Env.proves(FooVal));
6345       },
6346       {BuiltinOptions{ContextSensitiveOptions{}}});
6347 }
6348 
6349 TEST(TransferTest, ContextSensitiveMethodSetter) {
6350   std::string Code = R"(
6351     class MyClass {
6352     public:
6353       void setField(bool Val) { Field = Val; }
6354 
6355       bool Field;
6356     };
6357 
6358     void target() {
6359       MyClass MyObj;
6360       MyObj.setField(true);
6361       bool Foo = MyObj.Field;
6362       // [[p]]
6363     }
6364   )";
6365   runDataflow(
6366       Code,
6367       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6368          ASTContext &ASTCtx) {
6369         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6370         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6371 
6372         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6373         ASSERT_THAT(FooDecl, NotNull());
6374 
6375         auto &FooVal = getFormula(*FooDecl, Env);
6376         EXPECT_TRUE(Env.proves(FooVal));
6377       },
6378       {BuiltinOptions{ContextSensitiveOptions{}}});
6379 }
6380 
6381 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
6382   std::string Code = R"(
6383     class MyClass {
6384     public:
6385       bool getField() { return Field; }
6386       void setField(bool Val) { Field = Val; }
6387 
6388     private:
6389       bool Field;
6390     };
6391 
6392     void target() {
6393       MyClass MyObj;
6394       MyObj.setField(true);
6395       bool Foo = MyObj.getField();
6396       // [[p]]
6397     }
6398   )";
6399   runDataflow(
6400       Code,
6401       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6402          ASTContext &ASTCtx) {
6403         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6404         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6405 
6406         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6407         ASSERT_THAT(FooDecl, NotNull());
6408 
6409         auto &FooVal = getFormula(*FooDecl, Env);
6410         EXPECT_TRUE(Env.proves(FooVal));
6411       },
6412       {BuiltinOptions{ContextSensitiveOptions{}}});
6413 }
6414 
6415 
6416 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
6417   std::string Code = R"(
6418     class MyClass {
6419     public:
6420       void Inner() { MyField = true; }
6421       void Outer() { Inner(); }
6422 
6423       bool MyField;
6424     };
6425 
6426     void target() {
6427       MyClass MyObj;
6428       MyObj.Outer();
6429       bool Foo = MyObj.MyField;
6430       // [[p]]
6431     }
6432   )";
6433   runDataflow(
6434       Code,
6435       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6436          ASTContext &ASTCtx) {
6437         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6438         ;
6439         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6440 
6441         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6442         ASSERT_THAT(FooDecl, NotNull());
6443 
6444         auto &FooVal = getFormula(*FooDecl, Env);
6445         EXPECT_TRUE(Env.proves(FooVal));
6446       },
6447       {BuiltinOptions{ContextSensitiveOptions{}}});
6448 }
6449 
6450 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
6451   std::string Code = R"(
6452     class MyClass {
6453     public:
6454       bool Inner() { return MyField; }
6455       bool Outer() { return Inner(); }
6456 
6457       bool MyField;
6458     };
6459 
6460     void target() {
6461       MyClass MyObj;
6462       MyObj.MyField = true;
6463       bool Foo = MyObj.Outer();
6464       // [[p]]
6465     }
6466   )";
6467   runDataflow(
6468       Code,
6469       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6470          ASTContext &ASTCtx) {
6471         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6472         ;
6473         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6474 
6475         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6476         ASSERT_THAT(FooDecl, NotNull());
6477 
6478         auto &FooVal = getFormula(*FooDecl, Env);
6479         EXPECT_TRUE(Env.proves(FooVal));
6480       },
6481       {BuiltinOptions{ContextSensitiveOptions{}}});
6482 }
6483 
6484 TEST(TransferTest, ContextSensitiveConstructorBody) {
6485   std::string Code = R"(
6486     class MyClass {
6487     public:
6488       MyClass() { MyField = true; }
6489 
6490       bool MyField;
6491     };
6492 
6493     void target() {
6494       MyClass MyObj;
6495       bool Foo = MyObj.MyField;
6496       // [[p]]
6497     }
6498   )";
6499   runDataflow(
6500       Code,
6501       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6502          ASTContext &ASTCtx) {
6503         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6504         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6505 
6506         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6507         ASSERT_THAT(FooDecl, NotNull());
6508 
6509         auto &FooVal = getFormula(*FooDecl, Env);
6510         EXPECT_TRUE(Env.proves(FooVal));
6511       },
6512       {BuiltinOptions{ContextSensitiveOptions{}}});
6513 }
6514 
6515 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
6516   std::string Code = R"(
6517     class MyClass {
6518     public:
6519       MyClass() : MyField(true) {}
6520 
6521       bool MyField;
6522     };
6523 
6524     void target() {
6525       MyClass MyObj;
6526       bool Foo = MyObj.MyField;
6527       // [[p]]
6528     }
6529   )";
6530   runDataflow(
6531       Code,
6532       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6533          ASTContext &ASTCtx) {
6534         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6535         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6536 
6537         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6538         ASSERT_THAT(FooDecl, NotNull());
6539 
6540         auto &FooVal = getFormula(*FooDecl, Env);
6541         EXPECT_TRUE(Env.proves(FooVal));
6542       },
6543       {BuiltinOptions{ContextSensitiveOptions{}}});
6544 }
6545 
6546 TEST(TransferTest, ContextSensitiveConstructorDefault) {
6547   std::string Code = R"(
6548     class MyClass {
6549     public:
6550       MyClass() = default;
6551 
6552       bool MyField = true;
6553     };
6554 
6555     void target() {
6556       MyClass MyObj;
6557       bool Foo = MyObj.MyField;
6558       // [[p]]
6559     }
6560   )";
6561   runDataflow(
6562       Code,
6563       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6564          ASTContext &ASTCtx) {
6565         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6566         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6567 
6568         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6569         ASSERT_THAT(FooDecl, NotNull());
6570 
6571         auto &FooVal = getFormula(*FooDecl, Env);
6572         EXPECT_TRUE(Env.proves(FooVal));
6573       },
6574       {BuiltinOptions{ContextSensitiveOptions{}}});
6575 }
6576 
6577 TEST(TransferTest, ContextSensitiveSelfReferentialClass) {
6578   // Test that the `this` pointer seen in the constructor has the same value
6579   // as the address of the variable the object is constructed into.
6580   std::string Code = R"(
6581     class MyClass {
6582     public:
6583       MyClass() : Self(this) {}
6584       MyClass *Self;
6585     };
6586 
6587     void target() {
6588       MyClass MyObj;
6589       MyClass *SelfPtr = MyObj.Self;
6590       // [[p]]
6591     }
6592   )";
6593   runDataflow(
6594       Code,
6595       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6596          ASTContext &ASTCtx) {
6597         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6598 
6599         const ValueDecl *MyObjDecl = findValueDecl(ASTCtx, "MyObj");
6600         ASSERT_THAT(MyObjDecl, NotNull());
6601 
6602         const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "SelfPtr");
6603         ASSERT_THAT(SelfDecl, NotNull());
6604 
6605         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6606         auto &SelfVal = *cast<PointerValue>(Env.getValue(*SelfDecl));
6607         EXPECT_EQ(Env.getStorageLocation(*MyObjDecl), &SelfVal.getPointeeLoc());
6608       },
6609       {BuiltinOptions{ContextSensitiveOptions{}}});
6610 }
6611 
6612 TEST(TransferTest, UnnamedBitfieldInitializer) {
6613   std::string Code = R"(
6614     struct B {};
6615     struct A {
6616       unsigned a;
6617       unsigned : 4;
6618       unsigned c;
6619       B b;
6620     };
6621     void target() {
6622       A a = {};
6623       A test = a;
6624       (void)test.c;
6625     }
6626   )";
6627   runDataflow(
6628       Code,
6629       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6630          ASTContext &ASTCtx) {
6631         // This doesn't need a body because this test was crashing the framework
6632         // before handling correctly Unnamed bitfields in `InitListExpr`.
6633       });
6634 }
6635 
6636 // Repro for a crash that used to occur with chained short-circuiting logical
6637 // operators.
6638 TEST(TransferTest, ChainedLogicalOps) {
6639   std::string Code = R"(
6640     bool target() {
6641       bool b = true || false || false || false;
6642       // [[p]]
6643       return b;
6644     }
6645   )";
6646   runDataflow(
6647       Code,
6648       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6649          ASTContext &ASTCtx) {
6650         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6651         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
6652         EXPECT_TRUE(Env.proves(B));
6653       });
6654 }
6655 
6656 // Repro for a crash that used to occur when we call a `noreturn` function
6657 // within one of the operands of a `&&` or `||` operator.
6658 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
6659   std::string Code = R"(
6660     __attribute__((noreturn)) int doesnt_return();
6661     bool some_condition();
6662     void target(bool b1, bool b2) {
6663       // Neither of these should crash. In addition, if we don't terminate the
6664       // program, we know that the operators need to trigger the short-circuit
6665       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
6666       // will be true.
6667       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
6668       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
6669 
6670       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
6671       // entire expression unreachable. So we know that in both of the following
6672       // cases, if `target()` terminates, the `else` branch was taken.
6673       bool NoreturnOnLhsMakesAndUnreachable = false;
6674       if (some_condition())
6675          doesnt_return() > 0 && some_condition();
6676       else
6677          NoreturnOnLhsMakesAndUnreachable = true;
6678 
6679       bool NoreturnOnLhsMakesOrUnreachable = false;
6680       if (some_condition())
6681          doesnt_return() > 0 || some_condition();
6682       else
6683          NoreturnOnLhsMakesOrUnreachable = true;
6684 
6685       // [[p]]
6686     }
6687   )";
6688   runDataflow(
6689       Code,
6690       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6691          ASTContext &ASTCtx) {
6692         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6693         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6694         auto &A = Env.arena();
6695 
6696         // Check that [[p]] is reachable with a non-false flow condition.
6697         EXPECT_FALSE(Env.proves(A.makeLiteral(false)));
6698 
6699         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula();
6700         EXPECT_TRUE(Env.proves(A.makeNot(B1)));
6701 
6702         auto &NoreturnOnRhsOfAnd =
6703             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula();
6704         EXPECT_TRUE(Env.proves(A.makeNot(NoreturnOnRhsOfAnd)));
6705 
6706         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula();
6707         EXPECT_TRUE(Env.proves(B2));
6708 
6709         auto &NoreturnOnRhsOfOr =
6710             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr")
6711                 .formula();
6712         EXPECT_TRUE(Env.proves(NoreturnOnRhsOfOr));
6713 
6714         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
6715             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula();
6716         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesAndUnreachable));
6717 
6718         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
6719             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula();
6720         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesOrUnreachable));
6721       });
6722 }
6723 
6724 TEST(TransferTest, NewExpressions) {
6725   std::string Code = R"(
6726     void target() {
6727       int *p = new int(42);
6728       // [[after_new]]
6729     }
6730   )";
6731   runDataflow(
6732       Code,
6733       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6734          ASTContext &ASTCtx) {
6735         const Environment &Env =
6736             getEnvironmentAtAnnotation(Results, "after_new");
6737 
6738         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
6739 
6740         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
6741       });
6742 }
6743 
6744 TEST(TransferTest, NewExpressions_Structs) {
6745   std::string Code = R"(
6746     struct Inner {
6747       int InnerField;
6748     };
6749 
6750     struct Outer {
6751       Inner OuterField;
6752     };
6753 
6754     void target() {
6755       Outer *p = new Outer;
6756       // Access the fields to make sure the analysis actually generates children
6757       // for them in the `RecordStorageLocation`.
6758       p->OuterField.InnerField;
6759       // [[after_new]]
6760     }
6761   )";
6762   runDataflow(
6763       Code,
6764       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6765          ASTContext &ASTCtx) {
6766         const Environment &Env =
6767             getEnvironmentAtAnnotation(Results, "after_new");
6768 
6769         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
6770         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
6771 
6772         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
6773 
6774         auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
6775         auto &OuterFieldLoc =
6776             *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
6777         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
6778 
6779         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
6780       });
6781 }
6782 
6783 TEST(TransferTest, FunctionToPointerDecayHasValue) {
6784   std::string Code = R"(
6785     struct A { static void static_member_func(); };
6786     void target() {
6787       // To check that we're treating function-to-pointer decay correctly,
6788       // create two pointers, then verify they refer to the same storage
6789       // location.
6790       // We need to do the test this way because even if an initializer (in this
6791       // case, the function-to-pointer decay) does not create a value, we still
6792       // create a value for the variable.
6793       void (*non_member_p1)() = target;
6794       void (*non_member_p2)() = target;
6795 
6796       // Do the same thing but for a static member function.
6797       void (*member_p1)() = A::static_member_func;
6798       void (*member_p2)() = A::static_member_func;
6799       // [[p]]
6800     }
6801   )";
6802   runDataflow(
6803       Code,
6804       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6805          ASTContext &ASTCtx) {
6806         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6807 
6808         auto &NonMemberP1 =
6809             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
6810         auto &NonMemberP2 =
6811             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
6812         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
6813 
6814         auto &MemberP1 =
6815             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
6816         auto &MemberP2 =
6817             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
6818         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
6819       });
6820 }
6821 
6822 // Check that a builtin function is not associated with a value. (It's only
6823 // possible to call builtin functions directly, not take their address.)
6824 TEST(TransferTest, BuiltinFunctionModeled) {
6825   std::string Code = R"(
6826     void target() {
6827       __builtin_expect(0, 0);
6828       // [[p]]
6829     }
6830   )";
6831   runDataflow(
6832       Code,
6833       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6834          ASTContext &ASTCtx) {
6835         using ast_matchers::selectFirst;
6836         using ast_matchers::match;
6837         using ast_matchers::traverse;
6838         using ast_matchers::implicitCastExpr;
6839         using ast_matchers::hasCastKind;
6840 
6841         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6842 
6843         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
6844             "implicit_cast",
6845             match(traverse(TK_AsIs,
6846                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
6847                                .bind("implicit_cast")),
6848                   ASTCtx));
6849 
6850         ASSERT_THAT(ImplicitCast, NotNull());
6851         EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull());
6852       });
6853 }
6854 
6855 // Check that a callee of a member operator call is modeled as a `PointerValue`.
6856 // Member operator calls are unusual in that their callee is a pointer that
6857 // stems from a `FunctionToPointerDecay`. In calls to non-operator non-static
6858 // member functions, the callee is a `MemberExpr` (which does not have pointer
6859 // type).
6860 // We want to make sure that we produce a pointer value for the callee in this
6861 // specific scenario and that its storage location is durable (for convergence).
6862 TEST(TransferTest, MemberOperatorCallModelsPointerForCallee) {
6863   std::string Code = R"(
6864     struct S {
6865       bool operator!=(S s);
6866     };
6867     void target() {
6868       S s;
6869       (void)(s != s);
6870       (void)(s != s);
6871       // [[p]]
6872     }
6873   )";
6874   runDataflow(
6875       Code,
6876       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6877          ASTContext &ASTCtx) {
6878         using ast_matchers::selectFirst;
6879         using ast_matchers::match;
6880         using ast_matchers::traverse;
6881         using ast_matchers::cxxOperatorCallExpr;
6882 
6883         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6884 
6885         auto Matches = match(
6886             traverse(TK_AsIs, cxxOperatorCallExpr().bind("call")), ASTCtx);
6887 
6888         ASSERT_EQ(Matches.size(), 2UL);
6889 
6890         auto *Call1 = Matches[0].getNodeAs<CXXOperatorCallExpr>("call");
6891         auto *Call2 = Matches[1].getNodeAs<CXXOperatorCallExpr>("call");
6892 
6893         ASSERT_THAT(Call1, NotNull());
6894         ASSERT_THAT(Call2, NotNull());
6895 
6896         EXPECT_EQ(cast<ImplicitCastExpr>(Call1->getCallee())->getCastKind(),
6897                   CK_FunctionToPointerDecay);
6898         EXPECT_EQ(cast<ImplicitCastExpr>(Call2->getCallee())->getCastKind(),
6899                   CK_FunctionToPointerDecay);
6900 
6901         auto *Ptr1 = cast<PointerValue>(Env.getValue(*Call1->getCallee()));
6902         auto *Ptr2 = cast<PointerValue>(Env.getValue(*Call2->getCallee()));
6903 
6904         ASSERT_EQ(&Ptr1->getPointeeLoc(), &Ptr2->getPointeeLoc());
6905       });
6906 }
6907 
6908 // Check that fields of anonymous records are modeled.
6909 TEST(TransferTest, AnonymousStruct) {
6910   std::string Code = R"(
6911     struct S {
6912       struct {
6913         bool b;
6914       };
6915     };
6916     void target() {
6917       S s;
6918       s.b = true;
6919       // [[p]]
6920     }
6921   )";
6922   runDataflow(
6923       Code,
6924       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6925          ASTContext &ASTCtx) {
6926         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6927         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
6928         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6929         const IndirectFieldDecl *IndirectField =
6930             findIndirectFieldDecl(ASTCtx, "b");
6931 
6932         auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl));
6933         auto &AnonStruct = *cast<RecordStorageLocation>(
6934             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
6935 
6936         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6937         ASSERT_TRUE(Env.proves(B->formula()));
6938       });
6939 }
6940 
6941 TEST(TransferTest, AnonymousStructWithInitializer) {
6942   std::string Code = R"(
6943     struct target {
6944       target() {
6945         (void)0;
6946         // [[p]]
6947       }
6948       struct {
6949         bool b = true;
6950       };
6951     };
6952   )";
6953   runDataflow(
6954       Code,
6955       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6956          ASTContext &ASTCtx) {
6957         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6958         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
6959         const IndirectFieldDecl *IndirectField =
6960             findIndirectFieldDecl(ASTCtx, "b");
6961 
6962         auto *ThisLoc =
6963             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6964         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6965             *cast<ValueDecl>(IndirectField->chain().front())));
6966 
6967         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
6968         ASSERT_TRUE(Env.proves(B->formula()));
6969       });
6970 }
6971 
6972 TEST(TransferTest, AnonymousStructWithReferenceField) {
6973   std::string Code = R"(
6974     int global_i = 0;
6975     struct target {
6976       target() {
6977         (void)0;
6978         // [[p]]
6979       }
6980       struct {
6981         int &i = global_i;
6982       };
6983     };
6984   )";
6985   runDataflow(
6986       Code,
6987       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6988          ASTContext &ASTCtx) {
6989         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6990         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
6991         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
6992         const IndirectFieldDecl *IndirectField =
6993             findIndirectFieldDecl(ASTCtx, "i");
6994 
6995         auto *ThisLoc =
6996             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6997         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6998             *cast<ValueDecl>(IndirectField->chain().front())));
6999 
7000         ASSERT_EQ(AnonStruct.getChild(*IDecl),
7001                   Env.getStorageLocation(*GlobalIDecl));
7002       });
7003 }
7004 
7005 TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {
7006   // This is a crash repro.
7007   // `false` block may not have been processed when we try to evaluate the `||`
7008   // after visiting `true`, because it is not necessary (and therefore the edge
7009   // is marked unreachable). Trying to get the analysis state via
7010   // `getEnvironment` for the subexpression still should not crash.
7011   std::string Code = R"(
7012     int target(int i) {
7013       if ((i < 0 && true) || false) {
7014         return 0;
7015       }
7016       return 0;
7017     }
7018   )";
7019   runDataflow(
7020       Code,
7021       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7022          ASTContext &ASTCtx) {});
7023 }
7024 
7025 TEST(TransferTest, LambdaCaptureByCopy) {
7026   std::string Code = R"(
7027     void target(int Foo, int Bar) {
7028       [Foo]() {
7029         (void)0;
7030         // [[p]]
7031       }();
7032     }
7033   )";
7034   runDataflowOnLambda(
7035       Code,
7036       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7037          ASTContext &ASTCtx) {
7038         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7039         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7040 
7041         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7042         ASSERT_THAT(FooDecl, NotNull());
7043 
7044         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7045         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7046 
7047         const Value *FooVal = Env.getValue(*FooLoc);
7048         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7049 
7050         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7051         ASSERT_THAT(BarDecl, NotNull());
7052 
7053         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7054         EXPECT_THAT(BarLoc, IsNull());
7055       });
7056 }
7057 
7058 TEST(TransferTest, LambdaCaptureByReference) {
7059   std::string Code = R"(
7060     void target(int Foo, int Bar) {
7061       [&Foo]() {
7062         (void)0;
7063         // [[p]]
7064       }();
7065     }
7066   )";
7067   runDataflowOnLambda(
7068       Code,
7069       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7070          ASTContext &ASTCtx) {
7071         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7072         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7073 
7074         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7075         ASSERT_THAT(FooDecl, NotNull());
7076 
7077         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7078         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7079 
7080         const Value *FooVal = Env.getValue(*FooLoc);
7081         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7082 
7083         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7084         ASSERT_THAT(BarDecl, NotNull());
7085 
7086         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7087         EXPECT_THAT(BarLoc, IsNull());
7088       });
7089 }
7090 
7091 TEST(TransferTest, LambdaCaptureWithInitializer) {
7092   std::string Code = R"(
7093     void target(int Bar) {
7094       [Foo=Bar]() {
7095         (void)0;
7096         // [[p]]
7097       }();
7098     }
7099   )";
7100   runDataflowOnLambda(
7101       Code,
7102       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7103          ASTContext &ASTCtx) {
7104         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7105         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7106 
7107         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7108         ASSERT_THAT(FooDecl, NotNull());
7109 
7110         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7111         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7112 
7113         const Value *FooVal = Env.getValue(*FooLoc);
7114         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7115 
7116         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7117         ASSERT_THAT(BarDecl, NotNull());
7118 
7119         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7120         EXPECT_THAT(BarLoc, IsNull());
7121       });
7122 }
7123 
7124 TEST(TransferTest, LambdaCaptureByCopyImplicit) {
7125   std::string Code = R"(
7126     void target(int Foo, int Bar) {
7127       [=]() {
7128         Foo;
7129         // [[p]]
7130       }();
7131     }
7132   )";
7133   runDataflowOnLambda(
7134       Code,
7135       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7136          ASTContext &ASTCtx) {
7137         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7138         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7139 
7140         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7141         ASSERT_THAT(FooDecl, NotNull());
7142 
7143         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7144         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7145 
7146         const Value *FooVal = Env.getValue(*FooLoc);
7147         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7148 
7149         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7150         ASSERT_THAT(BarDecl, NotNull());
7151 
7152         // There is no storage location for `Bar` because it isn't used in the
7153         // body of the lambda.
7154         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7155         EXPECT_THAT(BarLoc, IsNull());
7156       });
7157 }
7158 
7159 TEST(TransferTest, LambdaCaptureByReferenceImplicit) {
7160   std::string Code = R"(
7161     void target(int Foo, int Bar) {
7162       [&]() {
7163         Foo;
7164         // [[p]]
7165       }();
7166     }
7167   )";
7168   runDataflowOnLambda(
7169       Code,
7170       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7171          ASTContext &ASTCtx) {
7172         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7173         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7174 
7175         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7176         ASSERT_THAT(FooDecl, NotNull());
7177 
7178         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
7179         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7180 
7181         const Value *FooVal = Env.getValue(*FooLoc);
7182         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7183 
7184         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
7185         ASSERT_THAT(BarDecl, NotNull());
7186 
7187         // There is no storage location for `Bar` because it isn't used in the
7188         // body of the lambda.
7189         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
7190         EXPECT_THAT(BarLoc, IsNull());
7191       });
7192 }
7193 
7194 TEST(TransferTest, LambdaCaptureThis) {
7195   std::string Code = R"(
7196     struct Bar {
7197       int Foo;
7198 
7199       void target() {
7200         [this]() {
7201           Foo;
7202           // [[p]]
7203         }();
7204       }
7205     };
7206   )";
7207   runDataflowOnLambda(
7208       Code,
7209       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7210          ASTContext &ASTCtx) {
7211         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
7212         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7213 
7214         const RecordStorageLocation *ThisPointeeLoc =
7215             Env.getThisPointeeStorageLocation();
7216         ASSERT_THAT(ThisPointeeLoc, NotNull());
7217 
7218         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
7219         ASSERT_THAT(FooDecl, NotNull());
7220 
7221         const StorageLocation *FooLoc = ThisPointeeLoc->getChild(*FooDecl);
7222         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
7223 
7224         const Value *FooVal = Env.getValue(*FooLoc);
7225         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
7226       });
7227 }
7228 
7229 // This test verifies correct modeling of a relational dependency that goes
7230 // through unmodeled functions (the simple `cond()` in this case).
7231 TEST(TransferTest, ConditionalRelation) {
7232   std::string Code = R"(
7233     bool cond();
7234     void target() {
7235        bool a = true;
7236        bool b = true;
7237        if (cond()) {
7238          a = false;
7239          if (cond()) {
7240            b = false;
7241          }
7242        }
7243        (void)0;
7244        // [[p]]
7245     }
7246  )";
7247   runDataflow(
7248       Code,
7249       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
7250          ASTContext &ASTCtx) {
7251         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
7252         auto &A = Env.arena();
7253         auto &VarA = getValueForDecl<BoolValue>(ASTCtx, Env, "a").formula();
7254         auto &VarB = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
7255 
7256         EXPECT_FALSE(Env.allows(A.makeAnd(VarA, A.makeNot(VarB))));
7257       });
7258 }
7259 
7260 } // namespace
7261