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