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