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