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