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