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