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