xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision 264976d98e785fa061ce6ac06db4a9bda2590506)
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/StorageLocation.h"
17 #include "clang/Analysis/FlowSensitive/Value.h"
18 #include "clang/Basic/LangStandard.h"
19 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/Testing/Support/Error.h"
24 #include "gmock/gmock.h"
25 #include "gtest/gtest.h"
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::IsNull;
35 using ::testing::NotNull;
36 using ::testing::UnorderedElementsAre;
37 
38 using BuiltinOptions = DataflowAnalysisContext::Options;
39 
40 template <typename Matcher>
41 void runDataflow(llvm::StringRef Code, Matcher Match,
42                  DataflowAnalysisOptions Options,
43                  LangStandard::Kind Std = LangStandard::lang_cxx17,
44                  llvm::StringRef TargetFun = "target") {
45   using ast_matchers::hasName;
46   llvm::SmallVector<std::string, 3> ASTBuildArgs = {
47       "-fsyntax-only", "-fno-delayed-template-parsing",
48       "-std=" +
49           std::string(LangStandard::getLangStandardForKind(Std).getName())};
50   AnalysisInputs<NoopAnalysis> AI(
51       Code, hasName(TargetFun),
52       [UseBuiltinModel = Options.BuiltinOpts.has_value()](ASTContext &C,
53                                                           Environment &Env) {
54         return NoopAnalysis(
55             C, DataflowAnalysisOptions{UseBuiltinModel
56                                            ? Env.getAnalysisOptions()
57                                            : llvm::Optional<BuiltinOptions>()});
58       });
59   AI.ASTBuildArgs = ASTBuildArgs;
60   if (Options.BuiltinOpts)
61     AI.BuiltinOptions = *Options.BuiltinOpts;
62   ASSERT_THAT_ERROR(
63       checkDataflow<NoopAnalysis>(
64           std::move(AI),
65           /*VerifyResults=*/
66           [&Match](const llvm::StringMap<DataflowAnalysisState<NoopLattice>>
67                        &Results,
68                    const AnalysisOutputs &AO) { Match(Results, AO.ASTCtx); }),
69       llvm::Succeeded());
70 }
71 
72 template <typename Matcher>
73 void runDataflow(llvm::StringRef Code, Matcher Match,
74                  LangStandard::Kind Std = LangStandard::lang_cxx17,
75                  bool ApplyBuiltinTransfer = true,
76                  llvm::StringRef TargetFun = "target") {
77   runDataflow(Code, std::move(Match),
78               {ApplyBuiltinTransfer ? BuiltinOptions{}
79                                     : std::optional<BuiltinOptions>()},
80               Std, TargetFun);
81 }
82 
83 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
84   std::string Code = R"(
85     void target() {
86       int Foo;
87       // [[p]]
88     }
89   )";
90   runDataflow(
91       Code,
92       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
93          ASTContext &ASTCtx) {
94         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
95         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
96 
97         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
98         ASSERT_THAT(FooDecl, NotNull());
99 
100         EXPECT_EQ(Env.getStorageLocation(*FooDecl, SkipPast::None), nullptr);
101       },
102       LangStandard::lang_cxx17,
103       /*ApplyBuiltinTransfer=*/false);
104 }
105 
106 TEST(TransferTest, BoolVarDecl) {
107   std::string Code = R"(
108     void target() {
109       bool Foo;
110       // [[p]]
111     }
112   )";
113   runDataflow(
114       Code,
115       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
116          ASTContext &ASTCtx) {
117         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
118         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
119 
120         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
121         ASSERT_THAT(FooDecl, NotNull());
122 
123         const StorageLocation *FooLoc =
124             Env.getStorageLocation(*FooDecl, SkipPast::None);
125         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
126 
127         const Value *FooVal = Env.getValue(*FooLoc);
128         EXPECT_TRUE(isa_and_nonnull<BoolValue>(FooVal));
129       });
130 }
131 
132 TEST(TransferTest, IntVarDecl) {
133   std::string Code = R"(
134     void target() {
135       int Foo;
136       // [[p]]
137     }
138   )";
139   runDataflow(
140       Code,
141       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
142          ASTContext &ASTCtx) {
143         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
144         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
145 
146         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
147         ASSERT_THAT(FooDecl, NotNull());
148 
149         const StorageLocation *FooLoc =
150             Env.getStorageLocation(*FooDecl, SkipPast::None);
151         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
152 
153         const Value *FooVal = Env.getValue(*FooLoc);
154         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
155       });
156 }
157 
158 TEST(TransferTest, StructVarDecl) {
159   std::string Code = R"(
160     struct A {
161       int Bar;
162     };
163 
164     void target() {
165       A Foo;
166       (void)Foo.Bar;
167       // [[p]]
168     }
169   )";
170   runDataflow(
171       Code,
172       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
173          ASTContext &ASTCtx) {
174         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
175         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
176 
177         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
178         ASSERT_THAT(FooDecl, NotNull());
179 
180         ASSERT_TRUE(FooDecl->getType()->isStructureType());
181         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
182 
183         FieldDecl *BarDecl = nullptr;
184         for (FieldDecl *Field : FooFields) {
185           if (Field->getNameAsString() == "Bar") {
186             BarDecl = Field;
187           } else {
188             FAIL() << "Unexpected field: " << Field->getNameAsString();
189           }
190         }
191         ASSERT_THAT(BarDecl, NotNull());
192 
193         const auto *FooLoc = cast<AggregateStorageLocation>(
194             Env.getStorageLocation(*FooDecl, SkipPast::None));
195         const auto *BarLoc =
196             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
197 
198         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
199         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
200         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
201       });
202 }
203 
204 TEST(TransferTest, StructVarDeclWithInit) {
205   std::string Code = R"(
206     struct A {
207       int Bar;
208     };
209 
210     A Gen();
211 
212     void target() {
213       A Foo = Gen();
214       (void)Foo.Bar;
215       // [[p]]
216     }
217   )";
218   runDataflow(
219       Code,
220       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
221          ASTContext &ASTCtx) {
222         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
223         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
224 
225         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
226         ASSERT_THAT(FooDecl, NotNull());
227 
228         ASSERT_TRUE(FooDecl->getType()->isStructureType());
229         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
230 
231         FieldDecl *BarDecl = nullptr;
232         for (FieldDecl *Field : FooFields) {
233           if (Field->getNameAsString() == "Bar") {
234             BarDecl = Field;
235           } else {
236             FAIL() << "Unexpected field: " << Field->getNameAsString();
237           }
238         }
239         ASSERT_THAT(BarDecl, NotNull());
240 
241         const auto *FooLoc = cast<AggregateStorageLocation>(
242             Env.getStorageLocation(*FooDecl, SkipPast::None));
243         const auto *BarLoc =
244             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
245 
246         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
247         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
248         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
249       });
250 }
251 
252 TEST(TransferTest, ClassVarDecl) {
253   std::string Code = R"(
254     class A {
255      public:
256       int Bar;
257     };
258 
259     void target() {
260       A Foo;
261       (void)Foo.Bar;
262       // [[p]]
263     }
264   )";
265   runDataflow(
266       Code,
267       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
268          ASTContext &ASTCtx) {
269         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
270         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
271 
272         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
273         ASSERT_THAT(FooDecl, NotNull());
274 
275         ASSERT_TRUE(FooDecl->getType()->isClassType());
276         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
277 
278         FieldDecl *BarDecl = nullptr;
279         for (FieldDecl *Field : FooFields) {
280           if (Field->getNameAsString() == "Bar") {
281             BarDecl = Field;
282           } else {
283             FAIL() << "Unexpected field: " << Field->getNameAsString();
284           }
285         }
286         ASSERT_THAT(BarDecl, NotNull());
287 
288         const auto *FooLoc = cast<AggregateStorageLocation>(
289             Env.getStorageLocation(*FooDecl, SkipPast::None));
290         const auto *BarLoc =
291             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
292 
293         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
294         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
295         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
296       });
297 }
298 
299 TEST(TransferTest, ReferenceVarDecl) {
300   std::string Code = R"(
301     struct A {};
302 
303     A &getA();
304 
305     void target() {
306       A &Foo = getA();
307       // [[p]]
308     }
309   )";
310   runDataflow(
311       Code,
312       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
313          ASTContext &ASTCtx) {
314         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
315         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
316 
317         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
318         ASSERT_THAT(FooDecl, NotNull());
319 
320         const StorageLocation *FooLoc =
321             Env.getStorageLocation(*FooDecl, SkipPast::None);
322         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
323 
324         const ReferenceValue *FooVal =
325             cast<ReferenceValue>(Env.getValue(*FooLoc));
326         const StorageLocation &FooReferentLoc = FooVal->getReferentLoc();
327         EXPECT_TRUE(isa<AggregateStorageLocation>(&FooReferentLoc));
328 
329         const Value *FooReferentVal = Env.getValue(FooReferentLoc);
330         EXPECT_TRUE(isa_and_nonnull<StructValue>(FooReferentVal));
331       });
332 }
333 
334 TEST(TransferTest, SelfReferentialReferenceVarDecl) {
335   std::string Code = R"(
336     struct A;
337 
338     struct B {};
339 
340     struct C {
341       A &FooRef;
342       A *FooPtr;
343       B &BazRef;
344       B *BazPtr;
345     };
346 
347     struct A {
348       C &Bar;
349     };
350 
351     A &getA();
352 
353     void target() {
354       A &Foo = getA();
355       (void)Foo.Bar.FooRef;
356       (void)Foo.Bar.FooPtr;
357       (void)Foo.Bar.BazRef;
358       (void)Foo.Bar.BazPtr;
359       // [[p]]
360     }
361   )";
362   runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>>
363                            &Results,
364                        ASTContext &ASTCtx) {
365     ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
366     const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
367 
368     const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
369     ASSERT_THAT(FooDecl, NotNull());
370 
371     ASSERT_TRUE(FooDecl->getType()->isReferenceType());
372     ASSERT_TRUE(FooDecl->getType().getNonReferenceType()->isStructureType());
373     const auto FooFields =
374         FooDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields();
375 
376     FieldDecl *BarDecl = nullptr;
377     for (FieldDecl *Field : FooFields) {
378       if (Field->getNameAsString() == "Bar") {
379         BarDecl = Field;
380       } else {
381         FAIL() << "Unexpected field: " << Field->getNameAsString();
382       }
383     }
384     ASSERT_THAT(BarDecl, NotNull());
385 
386     ASSERT_TRUE(BarDecl->getType()->isReferenceType());
387     ASSERT_TRUE(BarDecl->getType().getNonReferenceType()->isStructureType());
388     const auto BarFields =
389         BarDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields();
390 
391     FieldDecl *FooRefDecl = nullptr;
392     FieldDecl *FooPtrDecl = nullptr;
393     FieldDecl *BazRefDecl = nullptr;
394     FieldDecl *BazPtrDecl = nullptr;
395     for (FieldDecl *Field : BarFields) {
396       if (Field->getNameAsString() == "FooRef") {
397         FooRefDecl = Field;
398       } else if (Field->getNameAsString() == "FooPtr") {
399         FooPtrDecl = Field;
400       } else if (Field->getNameAsString() == "BazRef") {
401         BazRefDecl = Field;
402       } else if (Field->getNameAsString() == "BazPtr") {
403         BazPtrDecl = Field;
404       } else {
405         FAIL() << "Unexpected field: " << Field->getNameAsString();
406       }
407     }
408     ASSERT_THAT(FooRefDecl, NotNull());
409     ASSERT_THAT(FooPtrDecl, NotNull());
410     ASSERT_THAT(BazRefDecl, NotNull());
411     ASSERT_THAT(BazPtrDecl, NotNull());
412 
413     const auto *FooLoc = cast<ScalarStorageLocation>(
414         Env.getStorageLocation(*FooDecl, SkipPast::None));
415     const auto *FooVal = cast<ReferenceValue>(Env.getValue(*FooLoc));
416     const auto *FooReferentVal =
417         cast<StructValue>(Env.getValue(FooVal->getReferentLoc()));
418 
419     const auto *BarVal =
420         cast<ReferenceValue>(FooReferentVal->getChild(*BarDecl));
421     const auto *BarReferentVal =
422         cast<StructValue>(Env.getValue(BarVal->getReferentLoc()));
423 
424     const auto *FooRefVal =
425         cast<ReferenceValue>(BarReferentVal->getChild(*FooRefDecl));
426     const StorageLocation &FooReferentLoc = FooRefVal->getReferentLoc();
427     EXPECT_THAT(Env.getValue(FooReferentLoc), IsNull());
428 
429     const auto *FooPtrVal =
430         cast<PointerValue>(BarReferentVal->getChild(*FooPtrDecl));
431     const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc();
432     EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull());
433 
434     const auto *BazRefVal =
435         cast<ReferenceValue>(BarReferentVal->getChild(*BazRefDecl));
436     const StorageLocation &BazReferentLoc = BazRefVal->getReferentLoc();
437     EXPECT_THAT(Env.getValue(BazReferentLoc), NotNull());
438 
439     const auto *BazPtrVal =
440         cast<PointerValue>(BarReferentVal->getChild(*BazPtrDecl));
441     const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc();
442     EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull());
443   });
444 }
445 
446 TEST(TransferTest, PointerVarDecl) {
447   std::string Code = R"(
448     struct A {};
449 
450     A *getA();
451 
452     void target() {
453       A *Foo = getA();
454       // [[p]]
455     }
456   )";
457   runDataflow(
458       Code,
459       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
460          ASTContext &ASTCtx) {
461         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
462         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
463 
464         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
465         ASSERT_THAT(FooDecl, NotNull());
466 
467         const StorageLocation *FooLoc =
468             Env.getStorageLocation(*FooDecl, SkipPast::None);
469         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
470 
471         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
472         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
473         EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc));
474 
475         const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
476         EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal));
477       });
478 }
479 
480 TEST(TransferTest, SelfReferentialPointerVarDecl) {
481   std::string Code = R"(
482     struct A;
483 
484     struct B {};
485 
486     struct C {
487       A &FooRef;
488       A *FooPtr;
489       B &BazRef;
490       B *BazPtr;
491     };
492 
493     struct A {
494       C *Bar;
495     };
496 
497     A *getA();
498 
499     void target() {
500       A *Foo = getA();
501       (void)Foo->Bar->FooRef;
502       (void)Foo->Bar->FooPtr;
503       (void)Foo->Bar->BazRef;
504       (void)Foo->Bar->BazPtr;
505       // [[p]]
506     }
507   )";
508   runDataflow(
509       Code,
510       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
511          ASTContext &ASTCtx) {
512         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
513         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
514 
515         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
516         ASSERT_THAT(FooDecl, NotNull());
517 
518         ASSERT_TRUE(FooDecl->getType()->isPointerType());
519         ASSERT_TRUE(FooDecl->getType()
520                         ->getAs<PointerType>()
521                         ->getPointeeType()
522                         ->isStructureType());
523         const auto FooFields = FooDecl->getType()
524                                    ->getAs<PointerType>()
525                                    ->getPointeeType()
526                                    ->getAsRecordDecl()
527                                    ->fields();
528 
529         FieldDecl *BarDecl = nullptr;
530         for (FieldDecl *Field : FooFields) {
531           if (Field->getNameAsString() == "Bar") {
532             BarDecl = Field;
533           } else {
534             FAIL() << "Unexpected field: " << Field->getNameAsString();
535           }
536         }
537         ASSERT_THAT(BarDecl, NotNull());
538 
539         ASSERT_TRUE(BarDecl->getType()->isPointerType());
540         ASSERT_TRUE(BarDecl->getType()
541                         ->getAs<PointerType>()
542                         ->getPointeeType()
543                         ->isStructureType());
544         const auto BarFields = BarDecl->getType()
545                                    ->getAs<PointerType>()
546                                    ->getPointeeType()
547                                    ->getAsRecordDecl()
548                                    ->fields();
549 
550         FieldDecl *FooRefDecl = nullptr;
551         FieldDecl *FooPtrDecl = nullptr;
552         FieldDecl *BazRefDecl = nullptr;
553         FieldDecl *BazPtrDecl = nullptr;
554         for (FieldDecl *Field : BarFields) {
555           if (Field->getNameAsString() == "FooRef") {
556             FooRefDecl = Field;
557           } else if (Field->getNameAsString() == "FooPtr") {
558             FooPtrDecl = Field;
559           } else if (Field->getNameAsString() == "BazRef") {
560             BazRefDecl = Field;
561           } else if (Field->getNameAsString() == "BazPtr") {
562             BazPtrDecl = Field;
563           } else {
564             FAIL() << "Unexpected field: " << Field->getNameAsString();
565           }
566         }
567         ASSERT_THAT(FooRefDecl, NotNull());
568         ASSERT_THAT(FooPtrDecl, NotNull());
569         ASSERT_THAT(BazRefDecl, NotNull());
570         ASSERT_THAT(BazPtrDecl, NotNull());
571 
572         const auto *FooLoc = cast<ScalarStorageLocation>(
573             Env.getStorageLocation(*FooDecl, SkipPast::None));
574         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
575         const auto *FooPointeeVal =
576             cast<StructValue>(Env.getValue(FooVal->getPointeeLoc()));
577 
578         const auto *BarVal =
579             cast<PointerValue>(FooPointeeVal->getChild(*BarDecl));
580         const auto *BarPointeeVal =
581             cast<StructValue>(Env.getValue(BarVal->getPointeeLoc()));
582 
583         const auto *FooRefVal =
584             cast<ReferenceValue>(BarPointeeVal->getChild(*FooRefDecl));
585         const StorageLocation &FooReferentLoc = FooRefVal->getReferentLoc();
586         EXPECT_THAT(Env.getValue(FooReferentLoc), IsNull());
587 
588         const auto *FooPtrVal =
589             cast<PointerValue>(BarPointeeVal->getChild(*FooPtrDecl));
590         const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc();
591         EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull());
592 
593         const auto *BazRefVal =
594             cast<ReferenceValue>(BarPointeeVal->getChild(*BazRefDecl));
595         const StorageLocation &BazReferentLoc = BazRefVal->getReferentLoc();
596         EXPECT_THAT(Env.getValue(BazReferentLoc), NotNull());
597 
598         const auto *BazPtrVal =
599             cast<PointerValue>(BarPointeeVal->getChild(*BazPtrDecl));
600         const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc();
601         EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull());
602       });
603 }
604 
605 TEST(TransferTest, MultipleVarsDecl) {
606   std::string Code = R"(
607     void target() {
608       int Foo, Bar;
609       (void)0;
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         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
624         ASSERT_THAT(BarDecl, NotNull());
625 
626         const StorageLocation *FooLoc =
627             Env.getStorageLocation(*FooDecl, SkipPast::None);
628         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
629 
630         const StorageLocation *BarLoc =
631             Env.getStorageLocation(*BarDecl, SkipPast::None);
632         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
633 
634         const Value *FooVal = Env.getValue(*FooLoc);
635         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
636 
637         const Value *BarVal = Env.getValue(*BarLoc);
638         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
639       });
640 }
641 
642 TEST(TransferTest, JoinVarDecl) {
643   std::string Code = R"(
644     void target(bool B) {
645       int Foo;
646       // [[p1]]
647       if (B) {
648         int Bar;
649         // [[p2]]
650       } else {
651         int Baz;
652         // [[p3]]
653       }
654       (void)0;
655       // [[p4]]
656     }
657   )";
658   runDataflow(Code, [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>>
659                            &Results,
660                        ASTContext &ASTCtx) {
661     ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2", "p3", "p4"));
662 
663     const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
664     ASSERT_THAT(FooDecl, NotNull());
665 
666     const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
667     ASSERT_THAT(BarDecl, NotNull());
668 
669     const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
670     ASSERT_THAT(BazDecl, NotNull());
671 
672     const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
673 
674     const StorageLocation *FooLoc =
675         Env1.getStorageLocation(*FooDecl, SkipPast::None);
676     EXPECT_THAT(FooLoc, NotNull());
677     EXPECT_THAT(Env1.getStorageLocation(*BarDecl, SkipPast::None), IsNull());
678     EXPECT_THAT(Env1.getStorageLocation(*BazDecl, SkipPast::None), IsNull());
679 
680     const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
681     EXPECT_EQ(Env2.getStorageLocation(*FooDecl, SkipPast::None), FooLoc);
682     EXPECT_THAT(Env2.getStorageLocation(*BarDecl, SkipPast::None), NotNull());
683     EXPECT_THAT(Env2.getStorageLocation(*BazDecl, SkipPast::None), IsNull());
684 
685     const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
686     EXPECT_EQ(Env3.getStorageLocation(*FooDecl, SkipPast::None), FooLoc);
687     EXPECT_THAT(Env3.getStorageLocation(*BarDecl, SkipPast::None), IsNull());
688     EXPECT_THAT(Env3.getStorageLocation(*BazDecl, SkipPast::None), NotNull());
689 
690     const Environment &Env4 = getEnvironmentAtAnnotation(Results, "p4");
691     EXPECT_EQ(Env4.getStorageLocation(*FooDecl, SkipPast::None), FooLoc);
692     EXPECT_THAT(Env4.getStorageLocation(*BarDecl, SkipPast::None), IsNull());
693     EXPECT_THAT(Env4.getStorageLocation(*BazDecl, SkipPast::None), IsNull());
694   });
695 }
696 
697 TEST(TransferTest, BinaryOperatorAssign) {
698   std::string Code = R"(
699     void target() {
700       int Foo;
701       int Bar;
702       (Bar) = (Foo);
703       // [[p]]
704     }
705   )";
706   runDataflow(
707       Code,
708       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
709          ASTContext &ASTCtx) {
710         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
711         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
712 
713         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
714         ASSERT_THAT(FooDecl, NotNull());
715 
716         const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None);
717         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
718 
719         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
720         ASSERT_THAT(BarDecl, NotNull());
721 
722         EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal);
723       });
724 }
725 
726 TEST(TransferTest, VarDeclInitAssign) {
727   std::string Code = R"(
728     void target() {
729       int Foo;
730       int Bar = Foo;
731       // [[p]]
732     }
733   )";
734   runDataflow(
735       Code,
736       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
737          ASTContext &ASTCtx) {
738         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
739         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
740 
741         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
742         ASSERT_THAT(FooDecl, NotNull());
743 
744         const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None);
745         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
746 
747         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
748         ASSERT_THAT(BarDecl, NotNull());
749 
750         EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal);
751       });
752 }
753 
754 TEST(TransferTest, VarDeclInitAssignChained) {
755   std::string Code = R"(
756     void target() {
757       int Foo;
758       int Bar;
759       int Baz = (Bar = Foo);
760       // [[p]]
761     }
762   )";
763   runDataflow(
764       Code,
765       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
766          ASTContext &ASTCtx) {
767         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
768         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
769 
770         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
771         ASSERT_THAT(FooDecl, NotNull());
772 
773         const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None);
774         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
775 
776         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
777         ASSERT_THAT(BarDecl, NotNull());
778 
779         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
780         ASSERT_THAT(BazDecl, NotNull());
781 
782         EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal);
783         EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), FooVal);
784       });
785 }
786 
787 TEST(TransferTest, VarDeclInitAssignPtrDeref) {
788   std::string Code = R"(
789     void target() {
790       int Foo;
791       int *Bar;
792       *(Bar) = Foo;
793       int Baz = *(Bar);
794       // [[p]]
795     }
796   )";
797   runDataflow(
798       Code,
799       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
800          ASTContext &ASTCtx) {
801         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
802         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
803 
804         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
805         ASSERT_THAT(FooDecl, NotNull());
806 
807         const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None);
808         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
809 
810         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
811         ASSERT_THAT(BarDecl, NotNull());
812 
813         const auto *BarVal =
814             cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
815         EXPECT_EQ(Env.getValue(BarVal->getPointeeLoc()), FooVal);
816 
817         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
818         ASSERT_THAT(BazDecl, NotNull());
819 
820         EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), FooVal);
821       });
822 }
823 
824 TEST(TransferTest, AssignToAndFromReference) {
825   std::string Code = R"(
826     void target() {
827       int Foo;
828       int Bar;
829       int &Baz = Foo;
830       // [[p1]]
831       Baz = Bar;
832       int Qux = Baz;
833       int &Quux = Baz;
834       // [[p2]]
835     }
836   )";
837   runDataflow(
838       Code,
839       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
840          ASTContext &ASTCtx) {
841         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
842         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
843         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
844 
845         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
846         ASSERT_THAT(FooDecl, NotNull());
847 
848         const Value *FooVal = Env1.getValue(*FooDecl, SkipPast::None);
849         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
850 
851         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
852         ASSERT_THAT(BarDecl, NotNull());
853 
854         const Value *BarVal = Env1.getValue(*BarDecl, SkipPast::None);
855         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
856 
857         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
858         ASSERT_THAT(BazDecl, NotNull());
859 
860         EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), FooVal);
861 
862         EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BarVal);
863         EXPECT_EQ(Env2.getValue(*FooDecl, SkipPast::None), BarVal);
864 
865         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
866         ASSERT_THAT(QuxDecl, NotNull());
867         EXPECT_EQ(Env2.getValue(*QuxDecl, SkipPast::None), BarVal);
868 
869         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
870         ASSERT_THAT(QuuxDecl, NotNull());
871         EXPECT_EQ(Env2.getValue(*QuuxDecl, SkipPast::Reference), BarVal);
872       });
873 }
874 
875 TEST(TransferTest, MultipleParamDecls) {
876   std::string Code = R"(
877     void target(int Foo, int Bar) {
878       (void)0;
879       // [[p]]
880     }
881   )";
882   runDataflow(
883       Code,
884       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
885          ASTContext &ASTCtx) {
886         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
887         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
888 
889         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
890         ASSERT_THAT(FooDecl, NotNull());
891 
892         const StorageLocation *FooLoc =
893             Env.getStorageLocation(*FooDecl, SkipPast::None);
894         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
895 
896         const Value *FooVal = Env.getValue(*FooLoc);
897         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
898 
899         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
900         ASSERT_THAT(BarDecl, NotNull());
901 
902         const StorageLocation *BarLoc =
903             Env.getStorageLocation(*BarDecl, SkipPast::None);
904         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
905 
906         const Value *BarVal = Env.getValue(*BarLoc);
907         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
908       });
909 }
910 
911 TEST(TransferTest, StructParamDecl) {
912   std::string Code = R"(
913     struct A {
914       int Bar;
915     };
916 
917     void target(A Foo) {
918       (void)Foo.Bar;
919       // [[p]]
920     }
921   )";
922   runDataflow(
923       Code,
924       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
925          ASTContext &ASTCtx) {
926         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
927         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
928 
929         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
930         ASSERT_THAT(FooDecl, NotNull());
931 
932         ASSERT_TRUE(FooDecl->getType()->isStructureType());
933         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
934 
935         FieldDecl *BarDecl = nullptr;
936         for (FieldDecl *Field : FooFields) {
937           if (Field->getNameAsString() == "Bar") {
938             BarDecl = Field;
939           } else {
940             FAIL() << "Unexpected field: " << Field->getNameAsString();
941           }
942         }
943         ASSERT_THAT(BarDecl, NotNull());
944 
945         const auto *FooLoc = cast<AggregateStorageLocation>(
946             Env.getStorageLocation(*FooDecl, SkipPast::None));
947         const auto *BarLoc =
948             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
949 
950         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
951         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
952         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
953       });
954 }
955 
956 TEST(TransferTest, ReferenceParamDecl) {
957   std::string Code = R"(
958     struct A {};
959 
960     void target(A &Foo) {
961       (void)0;
962       // [[p]]
963     }
964   )";
965   runDataflow(
966       Code,
967       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
968          ASTContext &ASTCtx) {
969         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
970         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
971 
972         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
973         ASSERT_THAT(FooDecl, NotNull());
974 
975         const StorageLocation *FooLoc =
976             Env.getStorageLocation(*FooDecl, SkipPast::None);
977         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
978 
979         const ReferenceValue *FooVal =
980             dyn_cast<ReferenceValue>(Env.getValue(*FooLoc));
981         ASSERT_THAT(FooVal, NotNull());
982 
983         const StorageLocation &FooReferentLoc = FooVal->getReferentLoc();
984         EXPECT_TRUE(isa<AggregateStorageLocation>(&FooReferentLoc));
985 
986         const Value *FooReferentVal = Env.getValue(FooReferentLoc);
987         EXPECT_TRUE(isa_and_nonnull<StructValue>(FooReferentVal));
988       });
989 }
990 
991 TEST(TransferTest, PointerParamDecl) {
992   std::string Code = R"(
993     struct A {};
994 
995     void target(A *Foo) {
996       (void)0;
997       // [[p]]
998     }
999   )";
1000   runDataflow(
1001       Code,
1002       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1003          ASTContext &ASTCtx) {
1004         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1005         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1006 
1007         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1008         ASSERT_THAT(FooDecl, NotNull());
1009 
1010         const StorageLocation *FooLoc =
1011             Env.getStorageLocation(*FooDecl, SkipPast::None);
1012         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1013 
1014         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
1015         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
1016         EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc));
1017 
1018         const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
1019         EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal));
1020       });
1021 }
1022 
1023 TEST(TransferTest, StructMember) {
1024   std::string Code = R"(
1025     struct A {
1026       int Bar;
1027     };
1028 
1029     void target(A Foo) {
1030       int Baz = Foo.Bar;
1031       // [[p]]
1032     }
1033   )";
1034   runDataflow(
1035       Code,
1036       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1037          ASTContext &ASTCtx) {
1038         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1039         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1040 
1041         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1042         ASSERT_THAT(FooDecl, NotNull());
1043 
1044         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1045         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1046 
1047         FieldDecl *BarDecl = nullptr;
1048         for (FieldDecl *Field : FooFields) {
1049           if (Field->getNameAsString() == "Bar") {
1050             BarDecl = Field;
1051           } else {
1052             FAIL() << "Unexpected field: " << Field->getNameAsString();
1053           }
1054         }
1055         ASSERT_THAT(BarDecl, NotNull());
1056 
1057         const auto *FooLoc = cast<AggregateStorageLocation>(
1058             Env.getStorageLocation(*FooDecl, SkipPast::None));
1059         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1060         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1061 
1062         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1063         ASSERT_THAT(BazDecl, NotNull());
1064 
1065         EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal);
1066       });
1067 }
1068 
1069 TEST(TransferTest, DerivedBaseMemberClass) {
1070   std::string Code = R"(
1071     class A {
1072       int ADefault;
1073     protected:
1074       int AProtected;
1075     private:
1076       int APrivate;
1077     public:
1078       int APublic;
1079 
1080     private:
1081       friend void target();
1082     };
1083 
1084     class B : public A {
1085       int BDefault;
1086     protected:
1087       int BProtected;
1088     private:
1089       int BPrivate;
1090 
1091     private:
1092       friend void target();
1093     };
1094 
1095     void target() {
1096       B Foo;
1097       (void)Foo.ADefault;
1098       (void)Foo.AProtected;
1099       (void)Foo.APrivate;
1100       (void)Foo.APublic;
1101       (void)Foo.BDefault;
1102       (void)Foo.BProtected;
1103       (void)Foo.BPrivate;
1104       // [[p]]
1105     }
1106   )";
1107   runDataflow(
1108       Code,
1109       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1110          ASTContext &ASTCtx) {
1111         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1112         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1113 
1114         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1115         ASSERT_THAT(FooDecl, NotNull());
1116         ASSERT_TRUE(FooDecl->getType()->isRecordType());
1117 
1118         // Derived-class fields.
1119         const FieldDecl *BDefaultDecl = nullptr;
1120         const FieldDecl *BProtectedDecl = nullptr;
1121         const FieldDecl *BPrivateDecl = nullptr;
1122         for (const FieldDecl *Field :
1123              FooDecl->getType()->getAsRecordDecl()->fields()) {
1124           if (Field->getNameAsString() == "BDefault") {
1125             BDefaultDecl = Field;
1126           } else if (Field->getNameAsString() == "BProtected") {
1127             BProtectedDecl = Field;
1128           } else if (Field->getNameAsString() == "BPrivate") {
1129             BPrivateDecl = Field;
1130           } else {
1131             FAIL() << "Unexpected field: " << Field->getNameAsString();
1132           }
1133         }
1134         ASSERT_THAT(BDefaultDecl, NotNull());
1135         ASSERT_THAT(BProtectedDecl, NotNull());
1136         ASSERT_THAT(BPrivateDecl, NotNull());
1137 
1138         // Base-class fields.
1139         const FieldDecl *ADefaultDecl = nullptr;
1140         const FieldDecl *APrivateDecl = nullptr;
1141         const FieldDecl *AProtectedDecl = nullptr;
1142         const FieldDecl *APublicDecl = nullptr;
1143         for (const clang::CXXBaseSpecifier &Base :
1144              FooDecl->getType()->getAsCXXRecordDecl()->bases()) {
1145           QualType BaseType = Base.getType();
1146           ASSERT_TRUE(BaseType->isRecordType());
1147           for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) {
1148             if (Field->getNameAsString() == "ADefault") {
1149               ADefaultDecl = Field;
1150             } else if (Field->getNameAsString() == "AProtected") {
1151               AProtectedDecl = Field;
1152             } else if (Field->getNameAsString() == "APrivate") {
1153               APrivateDecl = Field;
1154             } else if (Field->getNameAsString() == "APublic") {
1155               APublicDecl = Field;
1156             } else {
1157               FAIL() << "Unexpected field: " << Field->getNameAsString();
1158             }
1159           }
1160         }
1161         ASSERT_THAT(ADefaultDecl, NotNull());
1162         ASSERT_THAT(AProtectedDecl, NotNull());
1163         ASSERT_THAT(APrivateDecl, NotNull());
1164         ASSERT_THAT(APublicDecl, NotNull());
1165 
1166         const auto &FooLoc = *cast<AggregateStorageLocation>(
1167             Env.getStorageLocation(*FooDecl, SkipPast::None));
1168         const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc));
1169 
1170         // Note: we can't test presence of children in `FooLoc`, because
1171         // `getChild` requires its argument be present (or fails an assert). So,
1172         // we limit to testing presence in `FooVal` and coherence between the
1173         // two.
1174 
1175         // Base-class fields.
1176         EXPECT_THAT(FooVal.getChild(*ADefaultDecl), NotNull());
1177         EXPECT_THAT(FooVal.getChild(*APrivateDecl), NotNull());
1178 
1179         EXPECT_THAT(FooVal.getChild(*AProtectedDecl), NotNull());
1180         EXPECT_EQ(Env.getValue(FooLoc.getChild(*APublicDecl)),
1181                   FooVal.getChild(*APublicDecl));
1182         EXPECT_THAT(FooVal.getChild(*APublicDecl), NotNull());
1183         EXPECT_EQ(Env.getValue(FooLoc.getChild(*AProtectedDecl)),
1184                   FooVal.getChild(*AProtectedDecl));
1185 
1186         // Derived-class fields.
1187         EXPECT_THAT(FooVal.getChild(*BDefaultDecl), NotNull());
1188         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BDefaultDecl)),
1189                   FooVal.getChild(*BDefaultDecl));
1190         EXPECT_THAT(FooVal.getChild(*BProtectedDecl), NotNull());
1191         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BProtectedDecl)),
1192                   FooVal.getChild(*BProtectedDecl));
1193         EXPECT_THAT(FooVal.getChild(*BPrivateDecl), NotNull());
1194         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BPrivateDecl)),
1195                   FooVal.getChild(*BPrivateDecl));
1196       });
1197 }
1198 
1199 static void derivedBaseMemberExpectations(
1200     const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1201     ASTContext &ASTCtx) {
1202   ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1203   const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1204 
1205   const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1206   ASSERT_THAT(FooDecl, NotNull());
1207 
1208   ASSERT_TRUE(FooDecl->getType()->isRecordType());
1209   const FieldDecl *BarDecl = nullptr;
1210   for (const clang::CXXBaseSpecifier &Base :
1211        FooDecl->getType()->getAsCXXRecordDecl()->bases()) {
1212     QualType BaseType = Base.getType();
1213     ASSERT_TRUE(BaseType->isStructureType());
1214 
1215     for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) {
1216       if (Field->getNameAsString() == "Bar") {
1217         BarDecl = Field;
1218       } else {
1219         FAIL() << "Unexpected field: " << Field->getNameAsString();
1220       }
1221     }
1222   }
1223   ASSERT_THAT(BarDecl, NotNull());
1224 
1225   const auto &FooLoc = *cast<AggregateStorageLocation>(
1226       Env.getStorageLocation(*FooDecl, SkipPast::None));
1227   const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc));
1228   EXPECT_THAT(FooVal.getChild(*BarDecl), NotNull());
1229   EXPECT_EQ(Env.getValue(FooLoc.getChild(*BarDecl)), FooVal.getChild(*BarDecl));
1230 }
1231 
1232 TEST(TransferTest, DerivedBaseMemberStructDefault) {
1233   std::string Code = R"(
1234     struct A {
1235       int Bar;
1236     };
1237     struct B : public A {
1238     };
1239 
1240     void target() {
1241       B Foo;
1242       (void)Foo.Bar;
1243       // [[p]]
1244     }
1245   )";
1246   runDataflow(Code, derivedBaseMemberExpectations);
1247 }
1248 
1249 TEST(TransferTest, DerivedBaseMemberPrivateFriend) {
1250   // Include an access to `Foo.Bar` to verify the analysis doesn't crash on that
1251   // access.
1252   std::string Code = R"(
1253     struct A {
1254     private:
1255       friend void target();
1256       int Bar;
1257     };
1258     struct B : public A {
1259     };
1260 
1261     void target() {
1262       B Foo;
1263       (void)Foo.Bar;
1264       // [[p]]
1265     }
1266   )";
1267   runDataflow(Code, derivedBaseMemberExpectations);
1268 }
1269 
1270 TEST(TransferTest, ClassMember) {
1271   std::string Code = R"(
1272     class A {
1273     public:
1274       int Bar;
1275     };
1276 
1277     void target(A Foo) {
1278       int Baz = Foo.Bar;
1279       // [[p]]
1280     }
1281   )";
1282   runDataflow(
1283       Code,
1284       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1285          ASTContext &ASTCtx) {
1286         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1287         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1288 
1289         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1290         ASSERT_THAT(FooDecl, NotNull());
1291 
1292         ASSERT_TRUE(FooDecl->getType()->isClassType());
1293         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1294 
1295         FieldDecl *BarDecl = nullptr;
1296         for (FieldDecl *Field : FooFields) {
1297           if (Field->getNameAsString() == "Bar") {
1298             BarDecl = Field;
1299           } else {
1300             FAIL() << "Unexpected field: " << Field->getNameAsString();
1301           }
1302         }
1303         ASSERT_THAT(BarDecl, NotNull());
1304 
1305         const auto *FooLoc = cast<AggregateStorageLocation>(
1306             Env.getStorageLocation(*FooDecl, SkipPast::None));
1307         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1308         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1309 
1310         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1311         ASSERT_THAT(BazDecl, NotNull());
1312 
1313         EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal);
1314       });
1315 }
1316 
1317 TEST(TransferTest, BaseClassInitializer) {
1318   using ast_matchers::cxxConstructorDecl;
1319   using ast_matchers::hasName;
1320   using ast_matchers::ofClass;
1321 
1322   std::string Code = R"(
1323     class A {
1324     public:
1325       A(int I) : Bar(I) {}
1326       int Bar;
1327     };
1328 
1329     class B : public A {
1330     public:
1331       B(int I) : A(I) {
1332         (void)0;
1333         // [[p]]
1334       }
1335     };
1336   )";
1337   ASSERT_THAT_ERROR(
1338       checkDataflow<NoopAnalysis>(
1339           AnalysisInputs<NoopAnalysis>(
1340               Code, cxxConstructorDecl(ofClass(hasName("B"))),
1341               [](ASTContext &C, Environment &) {
1342                 return NoopAnalysis(C, /*ApplyBuiltinTransfer=*/true);
1343               })
1344               .withASTBuildArgs(
1345                   {"-fsyntax-only", "-fno-delayed-template-parsing",
1346                    "-std=" + std::string(LangStandard::getLangStandardForKind(
1347                                              LangStandard::lang_cxx17)
1348                                              .getName())}),
1349           /*VerifyResults=*/
1350           [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1351              const AnalysisOutputs &) {
1352             // Regression test to verify that base-class initializers do not
1353             // trigger an assertion. If we add support for such initializers in
1354             // the future, we can expand this test to check more specific
1355             // properties.
1356             EXPECT_THAT(Results.keys(), UnorderedElementsAre("p"));
1357           }),
1358       llvm::Succeeded());
1359 }
1360 
1361 TEST(TransferTest, ReferenceMember) {
1362   std::string Code = R"(
1363     struct A {
1364       int &Bar;
1365     };
1366 
1367     void target(A Foo) {
1368       int Baz = Foo.Bar;
1369       // [[p]]
1370     }
1371   )";
1372   runDataflow(
1373       Code,
1374       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1375          ASTContext &ASTCtx) {
1376         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1377         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1378 
1379         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1380         ASSERT_THAT(FooDecl, NotNull());
1381 
1382         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1383         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1384 
1385         FieldDecl *BarDecl = nullptr;
1386         for (FieldDecl *Field : FooFields) {
1387           if (Field->getNameAsString() == "Bar") {
1388             BarDecl = Field;
1389           } else {
1390             FAIL() << "Unexpected field: " << Field->getNameAsString();
1391           }
1392         }
1393         ASSERT_THAT(BarDecl, NotNull());
1394 
1395         const auto *FooLoc = cast<AggregateStorageLocation>(
1396             Env.getStorageLocation(*FooDecl, SkipPast::None));
1397         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1398         const auto *BarVal = cast<ReferenceValue>(FooVal->getChild(*BarDecl));
1399         const auto *BarReferentVal =
1400             cast<IntegerValue>(Env.getValue(BarVal->getReferentLoc()));
1401 
1402         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1403         ASSERT_THAT(BazDecl, NotNull());
1404 
1405         EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarReferentVal);
1406       });
1407 }
1408 
1409 TEST(TransferTest, StructThisMember) {
1410   std::string Code = R"(
1411     struct A {
1412       int Bar;
1413 
1414       struct B {
1415         int Baz;
1416       };
1417 
1418       B Qux;
1419 
1420       void target() {
1421         int Foo = Bar;
1422         int Quux = Qux.Baz;
1423         // [[p]]
1424       }
1425     };
1426   )";
1427   runDataflow(
1428       Code,
1429       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1430          ASTContext &ASTCtx) {
1431         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1432         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1433 
1434         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1435             Env.getThisPointeeStorageLocation());
1436         ASSERT_THAT(ThisLoc, NotNull());
1437 
1438         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1439         ASSERT_THAT(BarDecl, NotNull());
1440 
1441         const auto *BarLoc =
1442             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1443         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1444 
1445         const Value *BarVal = Env.getValue(*BarLoc);
1446         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1447 
1448         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1449         ASSERT_THAT(FooDecl, NotNull());
1450         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1451 
1452         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1453         ASSERT_THAT(QuxDecl, NotNull());
1454 
1455         ASSERT_TRUE(QuxDecl->getType()->isStructureType());
1456         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1457 
1458         FieldDecl *BazDecl = nullptr;
1459         for (FieldDecl *Field : QuxFields) {
1460           if (Field->getNameAsString() == "Baz") {
1461             BazDecl = Field;
1462           } else {
1463             FAIL() << "Unexpected field: " << Field->getNameAsString();
1464           }
1465         }
1466         ASSERT_THAT(BazDecl, NotNull());
1467 
1468         const auto *QuxLoc =
1469             cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl));
1470         const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc));
1471         ASSERT_THAT(QuxVal, NotNull());
1472 
1473         const auto *BazLoc =
1474             cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl));
1475         const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl));
1476         EXPECT_EQ(Env.getValue(*BazLoc), BazVal);
1477 
1478         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1479         ASSERT_THAT(QuuxDecl, NotNull());
1480         EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal);
1481       });
1482 }
1483 
1484 TEST(TransferTest, ClassThisMember) {
1485   std::string Code = R"(
1486     class A {
1487       int Bar;
1488 
1489       class B {
1490       public:
1491         int Baz;
1492       };
1493 
1494       B Qux;
1495 
1496       void target() {
1497         int Foo = Bar;
1498         int Quux = Qux.Baz;
1499         // [[p]]
1500       }
1501     };
1502   )";
1503   runDataflow(
1504       Code,
1505       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1506          ASTContext &ASTCtx) {
1507         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1508         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1509 
1510         const auto *ThisLoc =
1511             cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation());
1512 
1513         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1514         ASSERT_THAT(BarDecl, NotNull());
1515 
1516         const auto *BarLoc =
1517             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1518         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1519 
1520         const Value *BarVal = Env.getValue(*BarLoc);
1521         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1522 
1523         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1524         ASSERT_THAT(FooDecl, NotNull());
1525         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1526 
1527         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1528         ASSERT_THAT(QuxDecl, NotNull());
1529 
1530         ASSERT_TRUE(QuxDecl->getType()->isClassType());
1531         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1532 
1533         FieldDecl *BazDecl = nullptr;
1534         for (FieldDecl *Field : QuxFields) {
1535           if (Field->getNameAsString() == "Baz") {
1536             BazDecl = Field;
1537           } else {
1538             FAIL() << "Unexpected field: " << Field->getNameAsString();
1539           }
1540         }
1541         ASSERT_THAT(BazDecl, NotNull());
1542 
1543         const auto *QuxLoc =
1544             cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl));
1545         const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc));
1546         ASSERT_THAT(QuxVal, NotNull());
1547 
1548         const auto *BazLoc =
1549             cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl));
1550         const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl));
1551         EXPECT_EQ(Env.getValue(*BazLoc), BazVal);
1552 
1553         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1554         ASSERT_THAT(QuuxDecl, NotNull());
1555         EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal);
1556       });
1557 }
1558 
1559 TEST(TransferTest, UnionThisMember) {
1560   std::string Code = R"(
1561     union A {
1562       int Foo;
1563       int Bar;
1564 
1565       void target() {
1566         A a;
1567         // Mention the fields to ensure they're included in the analysis.
1568         (void)a.Foo;
1569         (void)a.Bar;
1570         // [[p]]
1571       }
1572     };
1573   )";
1574   runDataflow(
1575       Code,
1576       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1577          ASTContext &ASTCtx) {
1578         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1579         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1580 
1581         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1582             Env.getThisPointeeStorageLocation());
1583         ASSERT_THAT(ThisLoc, NotNull());
1584 
1585         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1586         ASSERT_THAT(FooDecl, NotNull());
1587 
1588         const auto *FooLoc =
1589             cast<ScalarStorageLocation>(&ThisLoc->getChild(*FooDecl));
1590         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1591 
1592         const Value *FooVal = Env.getValue(*FooLoc);
1593         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
1594 
1595         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1596         ASSERT_THAT(BarDecl, NotNull());
1597 
1598         const auto *BarLoc =
1599             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1600         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1601 
1602         const Value *BarVal = Env.getValue(*BarLoc);
1603         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1604       });
1605 }
1606 
1607 TEST(TransferTest, StructThisInLambda) {
1608   std::string ThisCaptureCode = R"(
1609     struct A {
1610       void frob() {
1611         [this]() {
1612           int Foo = Bar;
1613           // [[p1]]
1614         }();
1615       }
1616 
1617       int Bar;
1618     };
1619   )";
1620   runDataflow(
1621       ThisCaptureCode,
1622       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1623          ASTContext &ASTCtx) {
1624         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1"));
1625         const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
1626 
1627         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1628             Env.getThisPointeeStorageLocation());
1629         ASSERT_THAT(ThisLoc, NotNull());
1630 
1631         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1632         ASSERT_THAT(BarDecl, NotNull());
1633 
1634         const auto *BarLoc =
1635             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1636         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1637 
1638         const Value *BarVal = Env.getValue(*BarLoc);
1639         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1640 
1641         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1642         ASSERT_THAT(FooDecl, NotNull());
1643         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1644       },
1645       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1646 
1647   std::string RefCaptureDefaultCode = R"(
1648     struct A {
1649       void frob() {
1650         [&]() {
1651           int Foo = Bar;
1652           // [[p2]]
1653         }();
1654       }
1655 
1656       int Bar;
1657     };
1658   )";
1659   runDataflow(
1660       RefCaptureDefaultCode,
1661       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1662          ASTContext &ASTCtx) {
1663         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p2"));
1664         const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
1665 
1666         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1667             Env.getThisPointeeStorageLocation());
1668         ASSERT_THAT(ThisLoc, NotNull());
1669 
1670         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1671         ASSERT_THAT(BarDecl, NotNull());
1672 
1673         const auto *BarLoc =
1674             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1675         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1676 
1677         const Value *BarVal = Env.getValue(*BarLoc);
1678         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1679 
1680         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1681         ASSERT_THAT(FooDecl, NotNull());
1682         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1683       },
1684       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1685 
1686   std::string FreeFunctionLambdaCode = R"(
1687     void foo() {
1688       int Bar;
1689       [&]() {
1690         int Foo = Bar;
1691         // [[p3]]
1692       }();
1693     }
1694   )";
1695   runDataflow(
1696       FreeFunctionLambdaCode,
1697       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1698          ASTContext &ASTCtx) {
1699         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p3"));
1700         const Environment &Env = getEnvironmentAtAnnotation(Results, "p3");
1701 
1702         EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull());
1703       },
1704       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1705 }
1706 
1707 TEST(TransferTest, ConstructorInitializer) {
1708   std::string Code = R"(
1709     struct target {
1710       int Bar;
1711 
1712       target(int Foo) : Bar(Foo) {
1713         int Qux = Bar;
1714         // [[p]]
1715       }
1716     };
1717   )";
1718   runDataflow(
1719       Code,
1720       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1721          ASTContext &ASTCtx) {
1722         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1723         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1724 
1725         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1726             Env.getThisPointeeStorageLocation());
1727         ASSERT_THAT(ThisLoc, NotNull());
1728 
1729         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1730         ASSERT_THAT(FooDecl, NotNull());
1731 
1732         const auto *FooVal =
1733             cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None));
1734 
1735         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1736         ASSERT_THAT(QuxDecl, NotNull());
1737         EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal);
1738       });
1739 }
1740 
1741 TEST(TransferTest, DefaultInitializer) {
1742   std::string Code = R"(
1743     struct target {
1744       int Bar;
1745       int Baz = Bar;
1746 
1747       target(int Foo) : Bar(Foo) {
1748         int Qux = Baz;
1749         // [[p]]
1750       }
1751     };
1752   )";
1753   runDataflow(
1754       Code,
1755       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1756          ASTContext &ASTCtx) {
1757         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1758         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1759 
1760         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1761             Env.getThisPointeeStorageLocation());
1762         ASSERT_THAT(ThisLoc, NotNull());
1763 
1764         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1765         ASSERT_THAT(FooDecl, NotNull());
1766 
1767         const auto *FooVal =
1768             cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None));
1769 
1770         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1771         ASSERT_THAT(QuxDecl, NotNull());
1772         EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal);
1773       });
1774 }
1775 
1776 TEST(TransferTest, DefaultInitializerReference) {
1777   std::string Code = R"(
1778     struct target {
1779       int &Bar;
1780       int &Baz = Bar;
1781 
1782       target(int &Foo) : Bar(Foo) {
1783         int &Qux = Baz;
1784         // [[p]]
1785       }
1786     };
1787   )";
1788   runDataflow(
1789       Code,
1790       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1791          ASTContext &ASTCtx) {
1792         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1793         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1794 
1795         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1796             Env.getThisPointeeStorageLocation());
1797         ASSERT_THAT(ThisLoc, NotNull());
1798 
1799         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1800         ASSERT_THAT(FooDecl, NotNull());
1801 
1802         const auto *FooVal =
1803             cast<ReferenceValue>(Env.getValue(*FooDecl, SkipPast::None));
1804 
1805         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1806         ASSERT_THAT(QuxDecl, NotNull());
1807 
1808         const auto *QuxVal =
1809             cast<ReferenceValue>(Env.getValue(*QuxDecl, SkipPast::None));
1810         EXPECT_EQ(&QuxVal->getReferentLoc(), &FooVal->getReferentLoc());
1811       });
1812 }
1813 
1814 TEST(TransferTest, TemporaryObject) {
1815   std::string Code = R"(
1816     struct A {
1817       int Bar;
1818     };
1819 
1820     void target() {
1821       A Foo = A();
1822       (void)Foo.Bar;
1823       // [[p]]
1824     }
1825   )";
1826   runDataflow(
1827       Code,
1828       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1829          ASTContext &ASTCtx) {
1830         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1831         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1832 
1833         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1834         ASSERT_THAT(FooDecl, NotNull());
1835 
1836         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1837         ASSERT_THAT(BarDecl, NotNull());
1838 
1839         const auto *FooLoc = cast<AggregateStorageLocation>(
1840             Env.getStorageLocation(*FooDecl, SkipPast::None));
1841         const auto *BarLoc =
1842             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
1843 
1844         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1845         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1846         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
1847       });
1848 }
1849 
1850 TEST(TransferTest, ElidableConstructor) {
1851   // This test is effectively the same as TransferTest.TemporaryObject, but
1852   // the code is compiled as C++ 14.
1853   std::string Code = R"(
1854     struct A {
1855       int Bar;
1856     };
1857 
1858     void target() {
1859       A Foo = A();
1860       (void)Foo.Bar;
1861       // [[p]]
1862     }
1863   )";
1864   runDataflow(
1865       Code,
1866       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1867          ASTContext &ASTCtx) {
1868         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1869         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1870 
1871         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1872         ASSERT_THAT(FooDecl, NotNull());
1873 
1874         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1875         ASSERT_THAT(BarDecl, NotNull());
1876 
1877         const auto *FooLoc = cast<AggregateStorageLocation>(
1878             Env.getStorageLocation(*FooDecl, SkipPast::None));
1879         const auto *BarLoc =
1880             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
1881 
1882         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1883         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1884         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
1885       },
1886       LangStandard::lang_cxx14);
1887 }
1888 
1889 TEST(TransferTest, AssignmentOperator) {
1890   std::string Code = R"(
1891     struct A {
1892       int Baz;
1893     };
1894 
1895     void target() {
1896       A Foo;
1897       A Bar;
1898       (void)Foo.Baz;
1899       // [[p1]]
1900       Foo = Bar;
1901       // [[p2]]
1902     }
1903   )";
1904   runDataflow(
1905       Code,
1906       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1907          ASTContext &ASTCtx) {
1908         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
1909         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
1910         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
1911 
1912         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1913         ASSERT_THAT(FooDecl, NotNull());
1914 
1915         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1916         ASSERT_THAT(BarDecl, NotNull());
1917 
1918         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1919         ASSERT_THAT(BazDecl, NotNull());
1920 
1921         const auto *FooLoc1 = cast<AggregateStorageLocation>(
1922             Env1.getStorageLocation(*FooDecl, SkipPast::None));
1923         const auto *BarLoc1 = cast<AggregateStorageLocation>(
1924             Env1.getStorageLocation(*BarDecl, SkipPast::None));
1925 
1926         const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1));
1927         const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1));
1928         EXPECT_NE(FooVal1, BarVal1);
1929 
1930         const auto *FooBazVal1 =
1931             cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl)));
1932         const auto *BarBazVal1 =
1933             cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl)));
1934         EXPECT_NE(FooBazVal1, BarBazVal1);
1935 
1936         const auto *FooLoc2 = cast<AggregateStorageLocation>(
1937             Env2.getStorageLocation(*FooDecl, SkipPast::None));
1938         const auto *BarLoc2 = cast<AggregateStorageLocation>(
1939             Env2.getStorageLocation(*BarDecl, SkipPast::None));
1940 
1941         const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2));
1942         const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2));
1943         EXPECT_EQ(FooVal2, BarVal2);
1944 
1945         const auto *FooBazVal2 =
1946             cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl)));
1947         const auto *BarBazVal2 =
1948             cast<IntegerValue>(Env2.getValue(BarLoc1->getChild(*BazDecl)));
1949         EXPECT_EQ(FooBazVal2, BarBazVal2);
1950       });
1951 }
1952 
1953 TEST(TransferTest, CopyConstructor) {
1954   std::string Code = R"(
1955     struct A {
1956       int Baz;
1957     };
1958 
1959     void target() {
1960       A Foo;
1961       (void)Foo.Baz;
1962       A Bar = Foo;
1963       // [[p]]
1964     }
1965   )";
1966   runDataflow(
1967       Code,
1968       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1969          ASTContext &ASTCtx) {
1970         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1971         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1972 
1973         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1974         ASSERT_THAT(FooDecl, NotNull());
1975 
1976         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1977         ASSERT_THAT(BarDecl, NotNull());
1978 
1979         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1980         ASSERT_THAT(BazDecl, NotNull());
1981 
1982         const auto *FooLoc = cast<AggregateStorageLocation>(
1983             Env.getStorageLocation(*FooDecl, SkipPast::None));
1984         const auto *BarLoc = cast<AggregateStorageLocation>(
1985             Env.getStorageLocation(*BarDecl, SkipPast::None));
1986 
1987         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1988         const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc));
1989         EXPECT_EQ(FooVal, BarVal);
1990 
1991         const auto *FooBazVal =
1992             cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl)));
1993         const auto *BarBazVal =
1994             cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl)));
1995         EXPECT_EQ(FooBazVal, BarBazVal);
1996       });
1997 }
1998 
1999 TEST(TransferTest, CopyConstructorWithParens) {
2000   std::string Code = R"(
2001     struct A {
2002       int Baz;
2003     };
2004 
2005     void target() {
2006       A Foo;
2007       (void)Foo.Baz;
2008       A Bar((A(Foo)));
2009       // [[p]]
2010     }
2011   )";
2012   runDataflow(
2013       Code,
2014       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2015          ASTContext &ASTCtx) {
2016         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2017         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2018 
2019         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2020         ASSERT_THAT(FooDecl, NotNull());
2021 
2022         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2023         ASSERT_THAT(BarDecl, NotNull());
2024 
2025         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2026         ASSERT_THAT(BazDecl, NotNull());
2027 
2028         const auto *FooLoc = cast<AggregateStorageLocation>(
2029             Env.getStorageLocation(*FooDecl, SkipPast::None));
2030         const auto *BarLoc = cast<AggregateStorageLocation>(
2031             Env.getStorageLocation(*BarDecl, SkipPast::None));
2032 
2033         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
2034         const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc));
2035         EXPECT_EQ(FooVal, BarVal);
2036 
2037         const auto *FooBazVal =
2038             cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl)));
2039         const auto *BarBazVal =
2040             cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl)));
2041         EXPECT_EQ(FooBazVal, BarBazVal);
2042       });
2043 }
2044 
2045 TEST(TransferTest, MoveConstructor) {
2046   std::string Code = R"(
2047     namespace std {
2048 
2049     template <typename T> struct remove_reference      { using type = T; };
2050     template <typename T> struct remove_reference<T&>  { using type = T; };
2051     template <typename T> struct remove_reference<T&&> { using type = T; };
2052 
2053     template <typename T>
2054     using remove_reference_t = typename remove_reference<T>::type;
2055 
2056     template <typename T>
2057     std::remove_reference_t<T>&& move(T&& x);
2058 
2059     } // namespace std
2060 
2061     struct A {
2062       int Baz;
2063     };
2064 
2065     void target() {
2066       A Foo;
2067       A Bar;
2068       (void)Foo.Baz;
2069       // [[p1]]
2070       Foo = std::move(Bar);
2071       // [[p2]]
2072     }
2073   )";
2074   runDataflow(
2075       Code,
2076       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2077          ASTContext &ASTCtx) {
2078         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
2079         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2080         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
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 ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2089         ASSERT_THAT(BazDecl, NotNull());
2090 
2091         const auto *FooLoc1 = cast<AggregateStorageLocation>(
2092             Env1.getStorageLocation(*FooDecl, SkipPast::None));
2093         const auto *BarLoc1 = cast<AggregateStorageLocation>(
2094             Env1.getStorageLocation(*BarDecl, SkipPast::None));
2095 
2096         const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1));
2097         const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1));
2098         EXPECT_NE(FooVal1, BarVal1);
2099 
2100         const auto *FooBazVal1 =
2101             cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl)));
2102         const auto *BarBazVal1 =
2103             cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl)));
2104         EXPECT_NE(FooBazVal1, BarBazVal1);
2105 
2106         const auto *FooLoc2 = cast<AggregateStorageLocation>(
2107             Env2.getStorageLocation(*FooDecl, SkipPast::None));
2108         const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2));
2109         EXPECT_EQ(FooVal2, BarVal1);
2110 
2111         const auto *FooBazVal2 =
2112             cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl)));
2113         EXPECT_EQ(FooBazVal2, BarBazVal1);
2114       });
2115 }
2116 
2117 TEST(TransferTest, BindTemporary) {
2118   std::string Code = R"(
2119     struct A {
2120       virtual ~A() = default;
2121 
2122       int Baz;
2123     };
2124 
2125     void target(A Foo) {
2126       int Bar = A(Foo).Baz;
2127       // [[p]]
2128     }
2129   )";
2130   runDataflow(
2131       Code,
2132       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2133          ASTContext &ASTCtx) {
2134         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2135         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2136 
2137         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2138         ASSERT_THAT(FooDecl, NotNull());
2139 
2140         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2141         ASSERT_THAT(BarDecl, NotNull());
2142 
2143         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2144         ASSERT_THAT(BazDecl, NotNull());
2145 
2146         const auto &FooVal =
2147             *cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None));
2148         const auto *BarVal =
2149             cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2150         EXPECT_EQ(BarVal, FooVal.getChild(*BazDecl));
2151       });
2152 }
2153 
2154 TEST(TransferTest, StaticCast) {
2155   std::string Code = R"(
2156     void target(int Foo) {
2157       int Bar = static_cast<int>(Foo);
2158       // [[p]]
2159     }
2160   )";
2161   runDataflow(
2162       Code,
2163       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2164          ASTContext &ASTCtx) {
2165         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2166         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2167 
2168         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2169         ASSERT_THAT(FooDecl, NotNull());
2170 
2171         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2172         ASSERT_THAT(BarDecl, NotNull());
2173 
2174         const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2175         const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2176         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2177         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2178         EXPECT_EQ(FooVal, BarVal);
2179       });
2180 }
2181 
2182 TEST(TransferTest, IntegralCast) {
2183   std::string Code = R"(
2184     void target(int Foo) {
2185       long Bar = Foo;
2186       // [[p]]
2187     }
2188   )";
2189   runDataflow(
2190       Code,
2191       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2192          ASTContext &ASTCtx) {
2193         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2194         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2195 
2196         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2197         ASSERT_THAT(FooDecl, NotNull());
2198 
2199         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2200         ASSERT_THAT(BarDecl, NotNull());
2201 
2202         const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2203         const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2204         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2205         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2206         EXPECT_EQ(FooVal, BarVal);
2207       });
2208 }
2209 
2210 TEST(TransferTest, IntegraltoBooleanCast) {
2211   std::string Code = R"(
2212     void target(int Foo) {
2213       bool Bar = Foo;
2214       // [[p]]
2215     }
2216   )";
2217   runDataflow(
2218       Code,
2219       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2220          ASTContext &ASTCtx) {
2221         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2222         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2223 
2224         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2225         ASSERT_THAT(FooDecl, NotNull());
2226 
2227         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2228         ASSERT_THAT(BarDecl, NotNull());
2229 
2230         const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2231         const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2232         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2233         EXPECT_TRUE(isa<BoolValue>(BarVal));
2234       });
2235 }
2236 
2237 TEST(TransferTest, IntegralToBooleanCastFromBool) {
2238   std::string Code = R"(
2239     void target(bool Foo) {
2240       int Zab = Foo;
2241       bool Bar = Zab;
2242       // [[p]]
2243     }
2244   )";
2245   runDataflow(
2246       Code,
2247       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2248          ASTContext &ASTCtx) {
2249         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2250         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2251 
2252         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2253         ASSERT_THAT(FooDecl, NotNull());
2254 
2255         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2256         ASSERT_THAT(BarDecl, NotNull());
2257 
2258         const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2259         const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2260         EXPECT_TRUE(isa<BoolValue>(FooVal));
2261         EXPECT_TRUE(isa<BoolValue>(BarVal));
2262         EXPECT_EQ(FooVal, BarVal);
2263       });
2264 }
2265 
2266 TEST(TransferTest, NullToPointerCast) {
2267   std::string Code = R"(
2268     using my_nullptr_t = decltype(nullptr);
2269     struct Baz {};
2270     void target() {
2271       int *FooX = nullptr;
2272       int *FooY = nullptr;
2273       bool **Bar = nullptr;
2274       Baz *Baz = nullptr;
2275       my_nullptr_t Null = 0;
2276       // [[p]]
2277     }
2278   )";
2279   runDataflow(
2280       Code,
2281       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2282          ASTContext &ASTCtx) {
2283         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2284         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2285 
2286         const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
2287         ASSERT_THAT(FooXDecl, NotNull());
2288 
2289         const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
2290         ASSERT_THAT(FooYDecl, NotNull());
2291 
2292         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2293         ASSERT_THAT(BarDecl, NotNull());
2294 
2295         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2296         ASSERT_THAT(BazDecl, NotNull());
2297 
2298         const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
2299         ASSERT_THAT(NullDecl, NotNull());
2300 
2301         const auto *FooXVal =
2302             cast<PointerValue>(Env.getValue(*FooXDecl, SkipPast::None));
2303         const auto *FooYVal =
2304             cast<PointerValue>(Env.getValue(*FooYDecl, SkipPast::None));
2305         const auto *BarVal =
2306             cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
2307         const auto *BazVal =
2308             cast<PointerValue>(Env.getValue(*BazDecl, SkipPast::None));
2309         const auto *NullVal =
2310             cast<PointerValue>(Env.getValue(*NullDecl, SkipPast::None));
2311 
2312         EXPECT_EQ(FooXVal, FooYVal);
2313         EXPECT_NE(FooXVal, BarVal);
2314         EXPECT_NE(FooXVal, BazVal);
2315         EXPECT_NE(BarVal, BazVal);
2316 
2317         const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
2318         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
2319         EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
2320 
2321         const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
2322         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
2323         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
2324 
2325         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
2326         EXPECT_TRUE(isa<AggregateStorageLocation>(BazPointeeLoc));
2327         EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull());
2328 
2329         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
2330         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
2331         EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
2332       });
2333 }
2334 
2335 TEST(TransferTest, NullToMemberPointerCast) {
2336   std::string Code = R"(
2337     struct Foo {};
2338     void target(Foo *Foo) {
2339       int Foo::*MemberPointer = nullptr;
2340       // [[p]]
2341     }
2342   )";
2343   runDataflow(
2344       Code,
2345       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2346          ASTContext &ASTCtx) {
2347         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2348         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2349 
2350         const ValueDecl *MemberPointerDecl =
2351             findValueDecl(ASTCtx, "MemberPointer");
2352         ASSERT_THAT(MemberPointerDecl, NotNull());
2353 
2354         const auto *MemberPointerVal = cast<PointerValue>(
2355             Env.getValue(*MemberPointerDecl, SkipPast::None));
2356 
2357         const StorageLocation &MemberLoc = MemberPointerVal->getPointeeLoc();
2358         EXPECT_THAT(Env.getValue(MemberLoc), IsNull());
2359       });
2360 }
2361 
2362 TEST(TransferTest, AddrOfValue) {
2363   std::string Code = R"(
2364     void target() {
2365       int Foo;
2366       int *Bar = &Foo;
2367       // [[p]]
2368     }
2369   )";
2370   runDataflow(
2371       Code,
2372       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2373          ASTContext &ASTCtx) {
2374         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2375         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2376 
2377         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2378         ASSERT_THAT(FooDecl, NotNull());
2379 
2380         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2381         ASSERT_THAT(BarDecl, NotNull());
2382 
2383         const auto *FooLoc = cast<ScalarStorageLocation>(
2384             Env.getStorageLocation(*FooDecl, SkipPast::None));
2385         const auto *BarVal =
2386             cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
2387         EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
2388       });
2389 }
2390 
2391 TEST(TransferTest, AddrOfReference) {
2392   std::string Code = R"(
2393     void target(int *Foo) {
2394       int *Bar = &(*Foo);
2395       // [[p]]
2396     }
2397   )";
2398   runDataflow(
2399       Code,
2400       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2401          ASTContext &ASTCtx) {
2402         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2403         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2404 
2405         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2406         ASSERT_THAT(FooDecl, NotNull());
2407 
2408         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2409         ASSERT_THAT(BarDecl, NotNull());
2410 
2411         const auto *FooVal =
2412             cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2413         const auto *BarVal =
2414             cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
2415         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
2416       });
2417 }
2418 
2419 TEST(TransferTest, DerefDependentPtr) {
2420   std::string Code = R"(
2421     template <typename T>
2422     void target(T *Foo) {
2423       T &Bar = *Foo;
2424       /*[[p]]*/
2425     }
2426   )";
2427   runDataflow(
2428       Code,
2429       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2430          ASTContext &ASTCtx) {
2431         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2432         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2433 
2434         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2435         ASSERT_THAT(FooDecl, NotNull());
2436 
2437         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2438         ASSERT_THAT(BarDecl, NotNull());
2439 
2440         const auto *FooVal =
2441             cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2442         const auto *BarVal =
2443             cast<ReferenceValue>(Env.getValue(*BarDecl, SkipPast::None));
2444         EXPECT_EQ(&BarVal->getReferentLoc(), &FooVal->getPointeeLoc());
2445       });
2446 }
2447 
2448 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
2449   std::string Code = R"(
2450     struct A {};
2451 
2452     void target(A Foo, A Bar, bool Cond) {
2453       A Baz = Cond ?  Foo : Bar;
2454       /*[[p]]*/
2455     }
2456   )";
2457   runDataflow(
2458       Code,
2459       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2460          ASTContext &ASTCtx) {
2461         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2462         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2463 
2464         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2465         ASSERT_THAT(FooDecl, NotNull());
2466 
2467         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2468         ASSERT_THAT(BarDecl, NotNull());
2469 
2470         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2471         ASSERT_THAT(BazDecl, NotNull());
2472 
2473         const auto *FooVal =
2474             cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None));
2475         const auto *BarVal =
2476             cast<StructValue>(Env.getValue(*BarDecl, SkipPast::None));
2477 
2478         const auto *BazVal =
2479             dyn_cast<StructValue>(Env.getValue(*BazDecl, SkipPast::None));
2480         ASSERT_THAT(BazVal, NotNull());
2481 
2482         EXPECT_NE(BazVal, FooVal);
2483         EXPECT_NE(BazVal, BarVal);
2484       });
2485 }
2486 
2487 TEST(TransferTest, VarDeclInDoWhile) {
2488   std::string Code = R"(
2489     void target(int *Foo) {
2490       do {
2491         int Bar = *Foo;
2492       } while (true);
2493       (void)0;
2494       /*[[p]]*/
2495     }
2496   )";
2497   runDataflow(
2498       Code,
2499       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2500          ASTContext &ASTCtx) {
2501         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2502         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2503 
2504         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2505         ASSERT_THAT(FooDecl, NotNull());
2506 
2507         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2508         ASSERT_THAT(BarDecl, NotNull());
2509 
2510         const auto *FooVal =
2511             cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2512         const auto *FooPointeeVal =
2513             cast<IntegerValue>(Env.getValue(FooVal->getPointeeLoc()));
2514 
2515         const auto *BarVal = dyn_cast_or_null<IntegerValue>(
2516             Env.getValue(*BarDecl, SkipPast::None));
2517         ASSERT_THAT(BarVal, NotNull());
2518 
2519         EXPECT_EQ(BarVal, FooPointeeVal);
2520       });
2521 }
2522 
2523 TEST(TransferTest, AggregateInitialization) {
2524   std::string BracesCode = R"(
2525     struct A {
2526       int Foo;
2527     };
2528 
2529     struct B {
2530       int Bar;
2531       A Baz;
2532       int Qux;
2533     };
2534 
2535     void target(int BarArg, int FooArg, int QuxArg) {
2536       B Quux{BarArg, {FooArg}, QuxArg};
2537       /*[[p]]*/
2538     }
2539   )";
2540   std::string BraceEllisionCode = R"(
2541     struct A {
2542       int Foo;
2543     };
2544 
2545     struct B {
2546       int Bar;
2547       A Baz;
2548       int Qux;
2549     };
2550 
2551     void target(int BarArg, int FooArg, int QuxArg) {
2552       B Quux = {BarArg, FooArg, QuxArg};
2553       /*[[p]]*/
2554     }
2555   )";
2556   for (const std::string &Code : {BracesCode, BraceEllisionCode}) {
2557     runDataflow(
2558         Code,
2559         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2560            ASTContext &ASTCtx) {
2561           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2562           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2563 
2564           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2565           ASSERT_THAT(FooDecl, NotNull());
2566 
2567           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2568           ASSERT_THAT(BarDecl, NotNull());
2569 
2570           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2571           ASSERT_THAT(BazDecl, NotNull());
2572 
2573           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2574           ASSERT_THAT(QuxDecl, NotNull());
2575 
2576           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
2577           ASSERT_THAT(FooArgDecl, NotNull());
2578 
2579           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
2580           ASSERT_THAT(BarArgDecl, NotNull());
2581 
2582           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
2583           ASSERT_THAT(QuxArgDecl, NotNull());
2584 
2585           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
2586           ASSERT_THAT(QuuxDecl, NotNull());
2587 
2588           const auto *FooArgVal =
2589               cast<IntegerValue>(Env.getValue(*FooArgDecl, SkipPast::None));
2590           const auto *BarArgVal =
2591               cast<IntegerValue>(Env.getValue(*BarArgDecl, SkipPast::None));
2592           const auto *QuxArgVal =
2593               cast<IntegerValue>(Env.getValue(*QuxArgDecl, SkipPast::None));
2594 
2595           const auto *QuuxVal =
2596               cast<StructValue>(Env.getValue(*QuuxDecl, SkipPast::None));
2597           ASSERT_THAT(QuuxVal, NotNull());
2598 
2599           const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl));
2600           ASSERT_THAT(BazVal, NotNull());
2601 
2602           EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal);
2603           EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal);
2604           EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal);
2605         });
2606   }
2607 }
2608 
2609 TEST(TransferTest, AssignToUnionMember) {
2610   std::string Code = R"(
2611     union A {
2612       int Foo;
2613     };
2614 
2615     void target(int Bar) {
2616       A Baz;
2617       Baz.Foo = Bar;
2618       // [[p]]
2619     }
2620   )";
2621   runDataflow(
2622       Code,
2623       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2624          ASTContext &ASTCtx) {
2625         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2626         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2627 
2628         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2629         ASSERT_THAT(BazDecl, NotNull());
2630         ASSERT_TRUE(BazDecl->getType()->isUnionType());
2631 
2632         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
2633         FieldDecl *FooDecl = nullptr;
2634         for (FieldDecl *Field : BazFields) {
2635           if (Field->getNameAsString() == "Foo") {
2636             FooDecl = Field;
2637           } else {
2638             FAIL() << "Unexpected field: " << Field->getNameAsString();
2639           }
2640         }
2641         ASSERT_THAT(FooDecl, NotNull());
2642 
2643         const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>(
2644             Env.getStorageLocation(*BazDecl, SkipPast::None));
2645         ASSERT_THAT(BazLoc, NotNull());
2646         ASSERT_THAT(Env.getValue(*BazLoc), NotNull());
2647 
2648         const auto *BazVal = cast<StructValue>(Env.getValue(*BazLoc));
2649         const auto *FooValFromBazVal = cast<IntegerValue>(BazVal->getChild(*FooDecl));
2650         const auto *FooValFromBazLoc = cast<IntegerValue>(Env.getValue(BazLoc->getChild(*FooDecl)));
2651         EXPECT_EQ(FooValFromBazLoc, FooValFromBazVal);
2652 
2653         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2654         ASSERT_THAT(BarDecl, NotNull());
2655         const auto *BarLoc = Env.getStorageLocation(*BarDecl, SkipPast::None);
2656         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2657 
2658         EXPECT_EQ(Env.getValue(*BarLoc), FooValFromBazVal);
2659         EXPECT_EQ(Env.getValue(*BarLoc), FooValFromBazLoc);
2660       });
2661 }
2662 
2663 TEST(TransferTest, AssignFromBoolLiteral) {
2664   std::string Code = R"(
2665     void target() {
2666       bool Foo = true;
2667       bool Bar = false;
2668       // [[p]]
2669     }
2670   )";
2671   runDataflow(
2672       Code,
2673       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2674          ASTContext &ASTCtx) {
2675         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2676         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2677 
2678         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2679         ASSERT_THAT(FooDecl, NotNull());
2680 
2681         const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>(
2682             Env.getValue(*FooDecl, SkipPast::None));
2683         ASSERT_THAT(FooVal, NotNull());
2684 
2685         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2686         ASSERT_THAT(BarDecl, NotNull());
2687 
2688         const auto *BarVal = dyn_cast_or_null<AtomicBoolValue>(
2689             Env.getValue(*BarDecl, SkipPast::None));
2690         ASSERT_THAT(BarVal, NotNull());
2691 
2692         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
2693         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
2694       });
2695 }
2696 
2697 TEST(TransferTest, AssignFromCompositeBoolExpression) {
2698   {
2699     std::string Code = R"(
2700     void target(bool Foo, bool Bar, bool Qux) {
2701       bool Baz = (Foo) && (Bar || Qux);
2702       // [[p]]
2703     }
2704   )";
2705     runDataflow(
2706         Code,
2707         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2708            ASTContext &ASTCtx) {
2709           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2710           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2711 
2712           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2713           ASSERT_THAT(FooDecl, NotNull());
2714 
2715           const auto *FooVal = dyn_cast_or_null<BoolValue>(
2716               Env.getValue(*FooDecl, SkipPast::None));
2717           ASSERT_THAT(FooVal, NotNull());
2718 
2719           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2720           ASSERT_THAT(BarDecl, NotNull());
2721 
2722           const auto *BarVal = dyn_cast_or_null<BoolValue>(
2723               Env.getValue(*BarDecl, SkipPast::None));
2724           ASSERT_THAT(BarVal, NotNull());
2725 
2726           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2727           ASSERT_THAT(QuxDecl, NotNull());
2728 
2729           const auto *QuxVal = dyn_cast_or_null<BoolValue>(
2730               Env.getValue(*QuxDecl, SkipPast::None));
2731           ASSERT_THAT(QuxVal, NotNull());
2732 
2733           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2734           ASSERT_THAT(BazDecl, NotNull());
2735 
2736           const auto *BazVal = dyn_cast_or_null<ConjunctionValue>(
2737               Env.getValue(*BazDecl, SkipPast::None));
2738           ASSERT_THAT(BazVal, NotNull());
2739           EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
2740 
2741           const auto *BazRightSubValVal =
2742               cast<DisjunctionValue>(&BazVal->getRightSubValue());
2743           EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal);
2744           EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal);
2745         });
2746   }
2747 
2748   {
2749     std::string Code = R"(
2750     void target(bool Foo, bool Bar, bool Qux) {
2751       bool Baz = (Foo && Qux) || (Bar);
2752       // [[p]]
2753     }
2754   )";
2755     runDataflow(
2756         Code,
2757         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2758            ASTContext &ASTCtx) {
2759           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2760           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2761 
2762           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2763           ASSERT_THAT(FooDecl, NotNull());
2764 
2765           const auto *FooVal = dyn_cast_or_null<BoolValue>(
2766               Env.getValue(*FooDecl, SkipPast::None));
2767           ASSERT_THAT(FooVal, NotNull());
2768 
2769           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2770           ASSERT_THAT(BarDecl, NotNull());
2771 
2772           const auto *BarVal = dyn_cast_or_null<BoolValue>(
2773               Env.getValue(*BarDecl, SkipPast::None));
2774           ASSERT_THAT(BarVal, NotNull());
2775 
2776           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2777           ASSERT_THAT(QuxDecl, NotNull());
2778 
2779           const auto *QuxVal = dyn_cast_or_null<BoolValue>(
2780               Env.getValue(*QuxDecl, SkipPast::None));
2781           ASSERT_THAT(QuxVal, NotNull());
2782 
2783           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2784           ASSERT_THAT(BazDecl, NotNull());
2785 
2786           const auto *BazVal = dyn_cast_or_null<DisjunctionValue>(
2787               Env.getValue(*BazDecl, SkipPast::None));
2788           ASSERT_THAT(BazVal, NotNull());
2789 
2790           const auto *BazLeftSubValVal =
2791               cast<ConjunctionValue>(&BazVal->getLeftSubValue());
2792           EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal);
2793           EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal);
2794 
2795           EXPECT_EQ(&BazVal->getRightSubValue(), BarVal);
2796         });
2797   }
2798 
2799   {
2800     std::string Code = R"(
2801       void target(bool A, bool B, bool C, bool D) {
2802         bool Foo = ((A && B) && C) && D;
2803         // [[p]]
2804       }
2805     )";
2806     runDataflow(
2807         Code,
2808         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2809            ASTContext &ASTCtx) {
2810           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2811           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2812 
2813           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
2814           ASSERT_THAT(ADecl, NotNull());
2815 
2816           const auto *AVal =
2817               dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl, SkipPast::None));
2818           ASSERT_THAT(AVal, NotNull());
2819 
2820           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
2821           ASSERT_THAT(BDecl, NotNull());
2822 
2823           const auto *BVal =
2824               dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl, SkipPast::None));
2825           ASSERT_THAT(BVal, NotNull());
2826 
2827           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
2828           ASSERT_THAT(CDecl, NotNull());
2829 
2830           const auto *CVal =
2831               dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
2832           ASSERT_THAT(CVal, NotNull());
2833 
2834           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
2835           ASSERT_THAT(DDecl, NotNull());
2836 
2837           const auto *DVal =
2838               dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl, SkipPast::None));
2839           ASSERT_THAT(DVal, NotNull());
2840 
2841           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2842           ASSERT_THAT(FooDecl, NotNull());
2843 
2844           const auto *FooVal = dyn_cast_or_null<ConjunctionValue>(
2845               Env.getValue(*FooDecl, SkipPast::None));
2846           ASSERT_THAT(FooVal, NotNull());
2847 
2848           const auto &FooLeftSubVal =
2849               cast<ConjunctionValue>(FooVal->getLeftSubValue());
2850           const auto &FooLeftLeftSubVal =
2851               cast<ConjunctionValue>(FooLeftSubVal.getLeftSubValue());
2852           EXPECT_EQ(&FooLeftLeftSubVal.getLeftSubValue(), AVal);
2853           EXPECT_EQ(&FooLeftLeftSubVal.getRightSubValue(), BVal);
2854           EXPECT_EQ(&FooLeftSubVal.getRightSubValue(), CVal);
2855           EXPECT_EQ(&FooVal->getRightSubValue(), DVal);
2856         });
2857   }
2858 }
2859 
2860 TEST(TransferTest, AssignFromBoolNegation) {
2861   std::string Code = R"(
2862     void target() {
2863       bool Foo = true;
2864       bool Bar = !(Foo);
2865       // [[p]]
2866     }
2867   )";
2868   runDataflow(
2869       Code,
2870       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2871          ASTContext &ASTCtx) {
2872         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2873         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2874 
2875         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2876         ASSERT_THAT(FooDecl, NotNull());
2877 
2878         const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>(
2879             Env.getValue(*FooDecl, SkipPast::None));
2880         ASSERT_THAT(FooVal, NotNull());
2881 
2882         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2883         ASSERT_THAT(BarDecl, NotNull());
2884 
2885         const auto *BarVal = dyn_cast_or_null<NegationValue>(
2886             Env.getValue(*BarDecl, SkipPast::None));
2887         ASSERT_THAT(BarVal, NotNull());
2888 
2889         EXPECT_EQ(&BarVal->getSubVal(), FooVal);
2890       });
2891 }
2892 
2893 TEST(TransferTest, BuiltinExpect) {
2894   std::string Code = R"(
2895     void target(long Foo) {
2896       long Bar = __builtin_expect(Foo, true);
2897       /*[[p]]*/
2898     }
2899   )";
2900   runDataflow(
2901       Code,
2902       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2903          ASTContext &ASTCtx) {
2904         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2905         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2906 
2907         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2908         ASSERT_THAT(FooDecl, NotNull());
2909 
2910         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2911         ASSERT_THAT(BarDecl, NotNull());
2912 
2913         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2914                   Env.getValue(*BarDecl, SkipPast::None));
2915       });
2916 }
2917 
2918 // `__builtin_expect` takes and returns a `long` argument, so other types
2919 // involve casts. This verifies that we identify the input and output in that
2920 // case.
2921 TEST(TransferTest, BuiltinExpectBoolArg) {
2922   std::string Code = R"(
2923     void target(bool Foo) {
2924       bool Bar = __builtin_expect(Foo, true);
2925       /*[[p]]*/
2926     }
2927   )";
2928   runDataflow(
2929       Code,
2930       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2931          ASTContext &ASTCtx) {
2932         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2933         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2934 
2935         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2936         ASSERT_THAT(FooDecl, NotNull());
2937 
2938         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2939         ASSERT_THAT(BarDecl, NotNull());
2940 
2941         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2942                   Env.getValue(*BarDecl, SkipPast::None));
2943       });
2944 }
2945 
2946 TEST(TransferTest, BuiltinUnreachable) {
2947   std::string Code = R"(
2948     void target(bool Foo) {
2949       bool Bar = false;
2950       if (Foo)
2951         Bar = Foo;
2952       else
2953         __builtin_unreachable();
2954       (void)0;
2955       /*[[p]]*/
2956     }
2957   )";
2958   runDataflow(
2959       Code,
2960       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2961          ASTContext &ASTCtx) {
2962         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2963         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2964 
2965         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2966         ASSERT_THAT(FooDecl, NotNull());
2967 
2968         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2969         ASSERT_THAT(BarDecl, NotNull());
2970 
2971         // `__builtin_unreachable` promises that the code is
2972         // unreachable, so the compiler treats the "then" branch as the
2973         // only possible predecessor of this statement.
2974         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2975                   Env.getValue(*BarDecl, SkipPast::None));
2976       });
2977 }
2978 
2979 TEST(TransferTest, BuiltinTrap) {
2980   std::string Code = R"(
2981     void target(bool Foo) {
2982       bool Bar = false;
2983       if (Foo)
2984         Bar = Foo;
2985       else
2986         __builtin_trap();
2987       (void)0;
2988       /*[[p]]*/
2989     }
2990   )";
2991   runDataflow(
2992       Code,
2993       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2994          ASTContext &ASTCtx) {
2995         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2996         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2997 
2998         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2999         ASSERT_THAT(FooDecl, NotNull());
3000 
3001         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3002         ASSERT_THAT(BarDecl, NotNull());
3003 
3004         // `__builtin_trap` ensures program termination, so only the
3005         // "then" branch is a predecessor of this statement.
3006         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
3007                   Env.getValue(*BarDecl, SkipPast::None));
3008       });
3009 }
3010 
3011 TEST(TransferTest, BuiltinDebugTrap) {
3012   std::string Code = R"(
3013     void target(bool Foo) {
3014       bool Bar = false;
3015       if (Foo)
3016         Bar = Foo;
3017       else
3018         __builtin_debugtrap();
3019       (void)0;
3020       /*[[p]]*/
3021     }
3022   )";
3023   runDataflow(
3024       Code,
3025       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3026          ASTContext &ASTCtx) {
3027         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3028         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3029 
3030         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3031         ASSERT_THAT(FooDecl, NotNull());
3032 
3033         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3034         ASSERT_THAT(BarDecl, NotNull());
3035 
3036         // `__builtin_debugtrap` doesn't ensure program termination.
3037         EXPECT_NE(Env.getValue(*FooDecl, SkipPast::None),
3038                   Env.getValue(*BarDecl, SkipPast::None));
3039       });
3040 }
3041 
3042 TEST(TransferTest, StaticIntSingleVarDecl) {
3043   std::string Code = R"(
3044     void target() {
3045       static int Foo;
3046       // [[p]]
3047     }
3048   )";
3049   runDataflow(
3050       Code,
3051       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3052          ASTContext &ASTCtx) {
3053         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3054         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3055 
3056         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3057         ASSERT_THAT(FooDecl, NotNull());
3058 
3059         const StorageLocation *FooLoc =
3060             Env.getStorageLocation(*FooDecl, SkipPast::None);
3061         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3062 
3063         const Value *FooVal = Env.getValue(*FooLoc);
3064         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3065       });
3066 }
3067 
3068 TEST(TransferTest, StaticIntGroupVarDecl) {
3069   std::string Code = R"(
3070     void target() {
3071       static int Foo, Bar;
3072       (void)0;
3073       // [[p]]
3074     }
3075   )";
3076   runDataflow(
3077       Code,
3078       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3079          ASTContext &ASTCtx) {
3080         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3081         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3082 
3083         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3084         ASSERT_THAT(FooDecl, NotNull());
3085 
3086         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3087         ASSERT_THAT(BarDecl, NotNull());
3088 
3089         const StorageLocation *FooLoc =
3090             Env.getStorageLocation(*FooDecl, SkipPast::None);
3091         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3092 
3093         const StorageLocation *BarLoc =
3094             Env.getStorageLocation(*BarDecl, SkipPast::None);
3095         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3096 
3097         const Value *FooVal = Env.getValue(*FooLoc);
3098         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3099 
3100         const Value *BarVal = Env.getValue(*BarLoc);
3101         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
3102 
3103         EXPECT_NE(FooVal, BarVal);
3104       });
3105 }
3106 
3107 TEST(TransferTest, GlobalIntVarDecl) {
3108   std::string Code = R"(
3109     static int Foo;
3110 
3111     void target() {
3112       int Bar = Foo;
3113       int Baz = Foo;
3114       // [[p]]
3115     }
3116   )";
3117   runDataflow(
3118       Code,
3119       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3120          ASTContext &ASTCtx) {
3121         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3122         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3123 
3124         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3125         ASSERT_THAT(BarDecl, NotNull());
3126 
3127         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3128         ASSERT_THAT(BazDecl, NotNull());
3129 
3130         const Value *BarVal =
3131             cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3132         const Value *BazVal =
3133             cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
3134         EXPECT_EQ(BarVal, BazVal);
3135       });
3136 }
3137 
3138 TEST(TransferTest, StaticMemberIntVarDecl) {
3139   std::string Code = R"(
3140     struct A {
3141       static int Foo;
3142     };
3143 
3144     void target(A a) {
3145       int Bar = a.Foo;
3146       int Baz = a.Foo;
3147       // [[p]]
3148     }
3149   )";
3150   runDataflow(
3151       Code,
3152       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3153          ASTContext &ASTCtx) {
3154         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3155         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3156 
3157         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3158         ASSERT_THAT(BarDecl, NotNull());
3159 
3160         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3161         ASSERT_THAT(BazDecl, NotNull());
3162 
3163         const Value *BarVal =
3164             cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3165         const Value *BazVal =
3166             cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
3167         EXPECT_EQ(BarVal, BazVal);
3168       });
3169 }
3170 
3171 TEST(TransferTest, StaticMemberRefVarDecl) {
3172   std::string Code = R"(
3173     struct A {
3174       static int &Foo;
3175     };
3176 
3177     void target(A a) {
3178       int Bar = a.Foo;
3179       int Baz = a.Foo;
3180       // [[p]]
3181     }
3182   )";
3183   runDataflow(
3184       Code,
3185       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3186          ASTContext &ASTCtx) {
3187         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3188         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3189 
3190         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3191         ASSERT_THAT(BarDecl, NotNull());
3192 
3193         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3194         ASSERT_THAT(BazDecl, NotNull());
3195 
3196         const Value *BarVal =
3197             cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3198         const Value *BazVal =
3199             cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
3200         EXPECT_EQ(BarVal, BazVal);
3201       });
3202 }
3203 
3204 TEST(TransferTest, AssignMemberBeforeCopy) {
3205   std::string Code = R"(
3206     struct A {
3207       int Foo;
3208     };
3209 
3210     void target() {
3211       A A1;
3212       A A2;
3213       int Bar;
3214       A1.Foo = Bar;
3215       A2 = A1;
3216       // [[p]]
3217     }
3218   )";
3219   runDataflow(
3220       Code,
3221       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3222          ASTContext &ASTCtx) {
3223         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3224         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3225 
3226         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3227         ASSERT_THAT(FooDecl, NotNull());
3228 
3229         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3230         ASSERT_THAT(BarDecl, NotNull());
3231 
3232         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
3233         ASSERT_THAT(A1Decl, NotNull());
3234 
3235         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
3236         ASSERT_THAT(A2Decl, NotNull());
3237 
3238         const auto *BarVal =
3239             cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3240 
3241         const auto *A2Val =
3242             cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None));
3243         EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal);
3244       });
3245 }
3246 
3247 TEST(TransferTest, BooleanEquality) {
3248   std::string Code = R"(
3249     void target(bool Bar) {
3250       bool Foo = true;
3251       if (Bar == Foo) {
3252         (void)0;
3253         /*[[p-then]]*/
3254       } else {
3255         (void)0;
3256         /*[[p-else]]*/
3257       }
3258     }
3259   )";
3260   runDataflow(
3261       Code,
3262       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3263          ASTContext &ASTCtx) {
3264         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3265         const Environment &EnvThen =
3266             getEnvironmentAtAnnotation(Results, "p-then");
3267         const Environment &EnvElse =
3268             getEnvironmentAtAnnotation(Results, "p-else");
3269 
3270         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3271         ASSERT_THAT(BarDecl, NotNull());
3272 
3273         auto &BarValThen =
3274             *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None));
3275         EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen));
3276 
3277         auto &BarValElse =
3278             *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None));
3279         EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse));
3280       });
3281 }
3282 
3283 TEST(TransferTest, BooleanInequality) {
3284   std::string Code = R"(
3285     void target(bool Bar) {
3286       bool Foo = true;
3287       if (Bar != Foo) {
3288         (void)0;
3289         /*[[p-then]]*/
3290       } else {
3291         (void)0;
3292         /*[[p-else]]*/
3293       }
3294     }
3295   )";
3296   runDataflow(
3297       Code,
3298       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3299          ASTContext &ASTCtx) {
3300         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3301         const Environment &EnvThen =
3302             getEnvironmentAtAnnotation(Results, "p-then");
3303         const Environment &EnvElse =
3304             getEnvironmentAtAnnotation(Results, "p-else");
3305 
3306         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3307         ASSERT_THAT(BarDecl, NotNull());
3308 
3309         auto &BarValThen =
3310             *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None));
3311         EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen));
3312 
3313         auto &BarValElse =
3314             *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None));
3315         EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse));
3316       });
3317 }
3318 
3319 TEST(TransferTest, CorrelatedBranches) {
3320   std::string Code = R"(
3321     void target(bool B, bool C) {
3322       if (B) {
3323         return;
3324       }
3325       (void)0;
3326       /*[[p0]]*/
3327       if (C) {
3328         B = true;
3329         /*[[p1]]*/
3330       }
3331       if (B) {
3332         (void)0;
3333         /*[[p2]]*/
3334       }
3335     }
3336   )";
3337   runDataflow(
3338       Code,
3339       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3340          ASTContext &ASTCtx) {
3341         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
3342 
3343         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3344         ASSERT_THAT(CDecl, NotNull());
3345 
3346         {
3347           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
3348           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3349           ASSERT_THAT(BDecl, NotNull());
3350           auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl, SkipPast::None));
3351 
3352           EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal)));
3353         }
3354 
3355         {
3356           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
3357           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
3358           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3359         }
3360 
3361         {
3362           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
3363           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
3364           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3365         }
3366       });
3367 }
3368 
3369 TEST(TransferTest, LoopWithAssignmentConverges) {
3370   std::string Code = R"(
3371     bool foo();
3372 
3373     void target() {
3374        do {
3375         bool Bar = foo();
3376         if (Bar) break;
3377         (void)Bar;
3378         /*[[p]]*/
3379       } while (true);
3380     }
3381   )";
3382   // The key property that we are verifying is implicit in `runDataflow` --
3383   // namely, that the analysis succeeds, rather than hitting the maximum number
3384   // of iterations.
3385   runDataflow(
3386       Code,
3387       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3388          ASTContext &ASTCtx) {
3389         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3390         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3391 
3392         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3393         ASSERT_THAT(BarDecl, NotNull());
3394 
3395         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
3396         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3397       });
3398 }
3399 
3400 TEST(TransferTest, LoopWithStagedAssignments) {
3401   std::string Code = R"(
3402     bool foo();
3403 
3404     void target() {
3405       bool Bar = false;
3406       bool Err = false;
3407       while (foo()) {
3408         if (Bar)
3409           Err = true;
3410         Bar = true;
3411         /*[[p]]*/
3412       }
3413     }
3414   )";
3415   runDataflow(
3416       Code,
3417       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3418          ASTContext &ASTCtx) {
3419         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3420         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3421 
3422         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3423         ASSERT_THAT(BarDecl, NotNull());
3424         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
3425         ASSERT_THAT(ErrDecl, NotNull());
3426 
3427         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
3428         auto &ErrVal = *cast<BoolValue>(Env.getValue(*ErrDecl, SkipPast::None));
3429         EXPECT_TRUE(Env.flowConditionImplies(BarVal));
3430         // An unsound analysis, for example only evaluating the loop once, can
3431         // conclude that `Err` is false. So, we test that this conclusion is not
3432         // reached.
3433         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(ErrVal)));
3434       });
3435 }
3436 
3437 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
3438   std::string Code = R"(
3439     bool &foo();
3440 
3441     void target() {
3442        do {
3443         bool& Bar = foo();
3444         if (Bar) break;
3445         (void)Bar;
3446         /*[[p]]*/
3447       } while (true);
3448     }
3449   )";
3450   // The key property that we are verifying is that the analysis succeeds,
3451   // rather than hitting the maximum number of iterations.
3452   runDataflow(
3453       Code,
3454       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3455          ASTContext &ASTCtx) {
3456         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3457         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3458 
3459         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3460         ASSERT_THAT(BarDecl, NotNull());
3461 
3462         auto &BarVal =
3463             *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::Reference));
3464         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3465       });
3466 }
3467 
3468 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
3469   std::string Code = R"(
3470     struct Lookup {
3471       int x;
3472     };
3473 
3474     void target(Lookup val, bool b) {
3475       const Lookup* l = nullptr;
3476       while (b) {
3477         l = &val;
3478         /*[[p-inner]]*/
3479       }
3480       (void)0;
3481       /*[[p-outer]]*/
3482     }
3483   )";
3484   // The key property that we are verifying is implicit in `runDataflow` --
3485   // namely, that the analysis succeeds, rather than hitting the maximum number
3486   // of iterations.
3487   runDataflow(
3488       Code,
3489       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3490          ASTContext &ASTCtx) {
3491         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
3492         const Environment &InnerEnv =
3493             getEnvironmentAtAnnotation(Results, "p-inner");
3494         const Environment &OuterEnv =
3495             getEnvironmentAtAnnotation(Results, "p-outer");
3496 
3497         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
3498         ASSERT_THAT(ValDecl, NotNull());
3499 
3500         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
3501         ASSERT_THAT(LDecl, NotNull());
3502 
3503         // Inner.
3504         auto *LVal =
3505             dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl, SkipPast::None));
3506         ASSERT_THAT(LVal, NotNull());
3507 
3508         EXPECT_EQ(&LVal->getPointeeLoc(),
3509                   InnerEnv.getStorageLocation(*ValDecl, SkipPast::Reference));
3510 
3511         // Outer.
3512         LVal =
3513             dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl, SkipPast::None));
3514         ASSERT_THAT(LVal, NotNull());
3515 
3516         // The loop body may not have been executed, so we should not conclude
3517         // that `l` points to `val`.
3518         EXPECT_NE(&LVal->getPointeeLoc(),
3519                   OuterEnv.getStorageLocation(*ValDecl, SkipPast::Reference));
3520       });
3521 }
3522 
3523 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
3524   std::string Code = R"(
3525     union Union {
3526       int A;
3527       float B;
3528     };
3529 
3530     void foo() {
3531       Union A;
3532       Union B;
3533       A = B;
3534     }
3535   )";
3536   // This is a crash regression test when calling the transfer function on a
3537   // `CXXThisExpr` that refers to a union.
3538   runDataflow(
3539       Code,
3540       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
3541          ASTContext &) {},
3542       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
3543 }
3544 
3545 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
3546   std::string Code = R"(
3547     struct A {
3548       int Foo;
3549       int Bar;
3550     };
3551 
3552     void target() {
3553       int Qux;
3554       A Baz;
3555       Baz.Foo = Qux;
3556       auto &FooRef = Baz.Foo;
3557       auto &BarRef = Baz.Bar;
3558       auto &[BoundFooRef, BoundBarRef] = Baz;
3559       // [[p]]
3560     }
3561   )";
3562   runDataflow(
3563       Code,
3564       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3565          ASTContext &ASTCtx) {
3566         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3567         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3568 
3569         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3570         ASSERT_THAT(FooRefDecl, NotNull());
3571 
3572         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3573         ASSERT_THAT(BarRefDecl, NotNull());
3574 
3575         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3576         ASSERT_THAT(QuxDecl, NotNull());
3577 
3578         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3579         ASSERT_THAT(BoundFooRefDecl, NotNull());
3580 
3581         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3582         ASSERT_THAT(BoundBarRefDecl, NotNull());
3583 
3584         const StorageLocation *FooRefLoc =
3585             Env.getStorageLocation(*FooRefDecl, SkipPast::Reference);
3586         ASSERT_THAT(FooRefLoc, NotNull());
3587 
3588         const StorageLocation *BarRefLoc =
3589             Env.getStorageLocation(*BarRefDecl, SkipPast::Reference);
3590         ASSERT_THAT(BarRefLoc, NotNull());
3591 
3592         const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None);
3593         ASSERT_THAT(QuxVal, NotNull());
3594 
3595         const StorageLocation *BoundFooRefLoc =
3596             Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference);
3597         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3598 
3599         const StorageLocation *BoundBarRefLoc =
3600             Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference);
3601         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3602 
3603         EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal);
3604       });
3605 }
3606 
3607 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
3608   std::string Code = R"(
3609     struct A {
3610       int &Foo;
3611       int &Bar;
3612     };
3613 
3614     void target(A Baz) {
3615       int Qux;
3616       Baz.Foo = Qux;
3617       auto &FooRef = Baz.Foo;
3618       auto &BarRef = Baz.Bar;
3619       auto &[BoundFooRef, BoundBarRef] = Baz;
3620       // [[p]]
3621     }
3622   )";
3623   runDataflow(
3624       Code,
3625       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3626          ASTContext &ASTCtx) {
3627         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3628         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3629 
3630         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3631         ASSERT_THAT(FooRefDecl, NotNull());
3632 
3633         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3634         ASSERT_THAT(BarRefDecl, NotNull());
3635 
3636         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3637         ASSERT_THAT(QuxDecl, NotNull());
3638 
3639         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3640         ASSERT_THAT(BoundFooRefDecl, NotNull());
3641 
3642         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3643         ASSERT_THAT(BoundBarRefDecl, NotNull());
3644 
3645         const StorageLocation *FooRefLoc =
3646             Env.getStorageLocation(*FooRefDecl, SkipPast::Reference);
3647         ASSERT_THAT(FooRefLoc, NotNull());
3648 
3649         const StorageLocation *BarRefLoc =
3650             Env.getStorageLocation(*BarRefDecl, SkipPast::Reference);
3651         ASSERT_THAT(BarRefLoc, NotNull());
3652 
3653         const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None);
3654         ASSERT_THAT(QuxVal, NotNull());
3655 
3656         const StorageLocation *BoundFooRefLoc =
3657             Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference);
3658         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3659 
3660         const StorageLocation *BoundBarRefLoc =
3661             Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference);
3662         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3663 
3664         EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal);
3665       });
3666 }
3667 
3668 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
3669   std::string Code = R"(
3670     struct A {
3671       int Foo;
3672       int Bar;
3673     };
3674 
3675     void target() {
3676       int Qux;
3677       A Baz;
3678       Baz.Foo = Qux;
3679       auto &FooRef = Baz.Foo;
3680       auto &BarRef = Baz.Bar;
3681       auto [BoundFoo, BoundBar] = Baz;
3682       // [[p]]
3683     }
3684   )";
3685   runDataflow(
3686       Code,
3687       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3688          ASTContext &ASTCtx) {
3689         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3690         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3691 
3692         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3693         ASSERT_THAT(FooRefDecl, NotNull());
3694 
3695         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3696         ASSERT_THAT(BarRefDecl, NotNull());
3697 
3698         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
3699         ASSERT_THAT(BoundFooDecl, NotNull());
3700 
3701         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
3702         ASSERT_THAT(BoundBarDecl, NotNull());
3703 
3704         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3705         ASSERT_THAT(QuxDecl, NotNull());
3706 
3707         const StorageLocation *FooRefLoc =
3708             Env.getStorageLocation(*FooRefDecl, SkipPast::Reference);
3709         ASSERT_THAT(FooRefLoc, NotNull());
3710 
3711         const StorageLocation *BarRefLoc =
3712             Env.getStorageLocation(*BarRefDecl, SkipPast::Reference);
3713         ASSERT_THAT(BarRefLoc, NotNull());
3714 
3715         const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None);
3716         ASSERT_THAT(QuxVal, NotNull());
3717 
3718         const StorageLocation *BoundFooLoc =
3719             Env.getStorageLocation(*BoundFooDecl, SkipPast::Reference);
3720         EXPECT_NE(BoundFooLoc, FooRefLoc);
3721 
3722         const StorageLocation *BoundBarLoc =
3723             Env.getStorageLocation(*BoundBarDecl, SkipPast::Reference);
3724         EXPECT_NE(BoundBarLoc, BarRefLoc);
3725 
3726         EXPECT_EQ(Env.getValue(*BoundFooDecl, SkipPast::Reference), QuxVal);
3727       });
3728 }
3729 
3730 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
3731   std::string Code = R"(
3732     namespace std {
3733     using size_t = int;
3734     template <class> struct tuple_size;
3735     template <std::size_t, class> struct tuple_element;
3736     template <class...> class tuple;
3737 
3738     namespace {
3739     template <class T, T v>
3740     struct size_helper { static const T value = v; };
3741     } // namespace
3742 
3743     template <class... T>
3744     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
3745 
3746     template <std::size_t I, class... T>
3747     struct tuple_element<I, tuple<T...>> {
3748       using type =  __type_pack_element<I, T...>;
3749     };
3750 
3751     template <class...> class tuple {};
3752 
3753     template <std::size_t I, class... T>
3754     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
3755     } // namespace std
3756 
3757     std::tuple<bool, int> makeTuple();
3758 
3759     void target(bool B) {
3760       auto [BoundFoo, BoundBar] = makeTuple();
3761       bool Baz;
3762       // Include if-then-else to test interaction of `BindingDecl` with join.
3763       if (B) {
3764         Baz = BoundFoo;
3765         (void)BoundBar;
3766         // [[p1]]
3767       } else {
3768         Baz = BoundFoo;
3769       }
3770       (void)0;
3771       // [[p2]]
3772     }
3773   )";
3774   runDataflow(
3775       Code,
3776       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3777          ASTContext &ASTCtx) {
3778         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
3779         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
3780 
3781         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
3782         ASSERT_THAT(BoundFooDecl, NotNull());
3783 
3784         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
3785         ASSERT_THAT(BoundBarDecl, NotNull());
3786 
3787         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3788         ASSERT_THAT(BazDecl, NotNull());
3789 
3790         const Value *BoundFooValue =
3791             Env1.getValue(*BoundFooDecl, SkipPast::Reference);
3792         ASSERT_THAT(BoundFooValue, NotNull());
3793         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
3794 
3795         const Value *BoundBarValue =
3796             Env1.getValue(*BoundBarDecl, SkipPast::Reference);
3797         ASSERT_THAT(BoundBarValue, NotNull());
3798         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
3799 
3800         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
3801         EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), BoundFooValue);
3802 
3803         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
3804 
3805         // Test that `BoundFooDecl` retains the value we expect, after the join.
3806         BoundFooValue = Env2.getValue(*BoundFooDecl, SkipPast::Reference);
3807         EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BoundFooValue);
3808       });
3809 }
3810 
3811 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
3812   std::string Code = R"(
3813     namespace std {
3814     using size_t = int;
3815     template <class> struct tuple_size;
3816     template <std::size_t, class> struct tuple_element;
3817     template <class...> class tuple;
3818 
3819     namespace {
3820     template <class T, T v>
3821     struct size_helper { static const T value = v; };
3822     } // namespace
3823 
3824     template <class... T>
3825     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
3826 
3827     template <std::size_t I, class... T>
3828     struct tuple_element<I, tuple<T...>> {
3829       using type =  __type_pack_element<I, T...>;
3830     };
3831 
3832     template <class...> class tuple {};
3833 
3834     template <std::size_t I, class... T>
3835     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
3836     } // namespace std
3837 
3838     std::tuple<bool, int> &getTuple();
3839 
3840     void target(bool B) {
3841       auto &[BoundFoo, BoundBar] = getTuple();
3842       bool Baz;
3843       // Include if-then-else to test interaction of `BindingDecl` with join.
3844       if (B) {
3845         Baz = BoundFoo;
3846         (void)BoundBar;
3847         // [[p1]]
3848       } else {
3849         Baz = BoundFoo;
3850       }
3851       (void)0;
3852       // [[p2]]
3853     }
3854   )";
3855   runDataflow(
3856       Code,
3857       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3858          ASTContext &ASTCtx) {
3859         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
3860         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
3861 
3862         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
3863         ASSERT_THAT(BoundFooDecl, NotNull());
3864 
3865         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
3866         ASSERT_THAT(BoundBarDecl, NotNull());
3867 
3868         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3869         ASSERT_THAT(BazDecl, NotNull());
3870 
3871         const Value *BoundFooValue =
3872             Env1.getValue(*BoundFooDecl, SkipPast::Reference);
3873         ASSERT_THAT(BoundFooValue, NotNull());
3874         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
3875 
3876         const Value *BoundBarValue =
3877             Env1.getValue(*BoundBarDecl, SkipPast::Reference);
3878         ASSERT_THAT(BoundBarValue, NotNull());
3879         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
3880 
3881         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
3882         // works as expected. We don't test aliasing properties of the
3883         // reference, because we don't model `std::get` and so have no way to
3884         // equate separate references into the tuple.
3885         EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), BoundFooValue);
3886 
3887         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
3888 
3889         // Test that `BoundFooDecl` retains the value we expect, after the join.
3890         BoundFooValue = Env2.getValue(*BoundFooDecl, SkipPast::Reference);
3891         EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BoundFooValue);
3892       });
3893 }
3894 // TODO: ref binding
3895 
3896 TEST(TransferTest, BinaryOperatorComma) {
3897   std::string Code = R"(
3898     void target(int Foo, int Bar) {
3899       int &Baz = (Foo, Bar);
3900       // [[p]]
3901     }
3902   )";
3903   runDataflow(
3904       Code,
3905       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3906          ASTContext &ASTCtx) {
3907         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3908         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3909 
3910         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3911         ASSERT_THAT(BarDecl, NotNull());
3912 
3913         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3914         ASSERT_THAT(BazDecl, NotNull());
3915 
3916         const StorageLocation *BarLoc =
3917             Env.getStorageLocation(*BarDecl, SkipPast::Reference);
3918         ASSERT_THAT(BarLoc, NotNull());
3919 
3920         const StorageLocation *BazLoc =
3921             Env.getStorageLocation(*BazDecl, SkipPast::Reference);
3922         EXPECT_EQ(BazLoc, BarLoc);
3923       });
3924 }
3925 
3926 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
3927   std::string Code = R"(
3928     void target(bool Foo) {
3929       if (Foo) {
3930         (void)0;
3931         // [[if_then]]
3932       } else {
3933         (void)0;
3934         // [[if_else]]
3935       }
3936     }
3937   )";
3938   runDataflow(
3939       Code,
3940       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3941          ASTContext &ASTCtx) {
3942         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
3943         const Environment &ThenEnv =
3944             getEnvironmentAtAnnotation(Results, "if_then");
3945         const Environment &ElseEnv =
3946             getEnvironmentAtAnnotation(Results, "if_else");
3947 
3948         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3949         ASSERT_THAT(FooDecl, NotNull());
3950 
3951         BoolValue &ThenFooVal =
3952             *cast<BoolValue>(ThenEnv.getValue(*FooDecl, SkipPast::None));
3953         EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal));
3954 
3955         BoolValue &ElseFooVal =
3956             *cast<BoolValue>(ElseEnv.getValue(*FooDecl, SkipPast::None));
3957         EXPECT_TRUE(ElseEnv.flowConditionImplies(ElseEnv.makeNot(ElseFooVal)));
3958       });
3959 }
3960 
3961 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
3962   std::string Code = R"(
3963     void target(bool Foo) {
3964       while (Foo) {
3965         (void)0;
3966         // [[loop_body]]
3967       }
3968       (void)0;
3969       // [[after_loop]]
3970     }
3971   )";
3972   runDataflow(
3973       Code,
3974       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3975          ASTContext &ASTCtx) {
3976         ASSERT_THAT(Results.keys(),
3977                     UnorderedElementsAre("loop_body", "after_loop"));
3978         const Environment &LoopBodyEnv =
3979             getEnvironmentAtAnnotation(Results, "loop_body");
3980         const Environment &AfterLoopEnv =
3981             getEnvironmentAtAnnotation(Results, "after_loop");
3982 
3983         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3984         ASSERT_THAT(FooDecl, NotNull());
3985 
3986         BoolValue &LoopBodyFooVal =
3987             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
3988         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
3989 
3990         BoolValue &AfterLoopFooVal =
3991             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
3992         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
3993             AfterLoopEnv.makeNot(AfterLoopFooVal)));
3994       });
3995 }
3996 
3997 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
3998   std::string Code = R"(
3999     void target(bool Foo) {
4000       bool Bar = true;
4001       do {
4002         (void)0;
4003         // [[loop_body]]
4004         Bar = false;
4005       } while (Foo);
4006       (void)0;
4007       // [[after_loop]]
4008     }
4009   )";
4010   runDataflow(
4011       Code,
4012       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4013          ASTContext &ASTCtx) {
4014         ASSERT_THAT(Results.keys(),
4015                     UnorderedElementsAre("loop_body", "after_loop"));
4016         const Environment &LoopBodyEnv =
4017             getEnvironmentAtAnnotation(Results, "loop_body");
4018         const Environment &AfterLoopEnv =
4019             getEnvironmentAtAnnotation(Results, "after_loop");
4020 
4021         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4022         ASSERT_THAT(FooDecl, NotNull());
4023 
4024         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4025         ASSERT_THAT(BarDecl, NotNull());
4026 
4027         BoolValue &LoopBodyFooVal =
4028             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
4029         BoolValue &LoopBodyBarVal =
4030             *cast<BoolValue>(LoopBodyEnv.getValue(*BarDecl, SkipPast::None));
4031         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(
4032             LoopBodyEnv.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
4033 
4034         BoolValue &AfterLoopFooVal =
4035             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
4036         BoolValue &AfterLoopBarVal =
4037             *cast<BoolValue>(AfterLoopEnv.getValue(*BarDecl, SkipPast::None));
4038         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4039             AfterLoopEnv.makeNot(AfterLoopFooVal)));
4040         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4041             AfterLoopEnv.makeNot(AfterLoopBarVal)));
4042       });
4043 }
4044 
4045 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
4046   std::string Code = R"(
4047     void target(bool Foo) {
4048       for (; Foo;) {
4049         (void)0;
4050         // [[loop_body]]
4051       }
4052       (void)0;
4053       // [[after_loop]]
4054     }
4055   )";
4056   runDataflow(
4057       Code,
4058       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4059          ASTContext &ASTCtx) {
4060         ASSERT_THAT(Results.keys(),
4061                     UnorderedElementsAre("loop_body", "after_loop"));
4062         const Environment &LoopBodyEnv =
4063             getEnvironmentAtAnnotation(Results, "loop_body");
4064         const Environment &AfterLoopEnv =
4065             getEnvironmentAtAnnotation(Results, "after_loop");
4066 
4067         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4068         ASSERT_THAT(FooDecl, NotNull());
4069 
4070         BoolValue &LoopBodyFooVal =
4071             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
4072         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4073 
4074         BoolValue &AfterLoopFooVal =
4075             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
4076         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4077             AfterLoopEnv.makeNot(AfterLoopFooVal)));
4078       });
4079 }
4080 
4081 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
4082   std::string Code = R"(
4083     void target(bool Foo) {
4084       for (;;) {
4085         (void)0;
4086         // [[loop_body]]
4087       }
4088     }
4089   )";
4090   runDataflow(
4091       Code,
4092       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4093          ASTContext &ASTCtx) {
4094         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
4095         const Environment &LoopBodyEnv =
4096             getEnvironmentAtAnnotation(Results, "loop_body");
4097 
4098         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4099         ASSERT_THAT(FooDecl, NotNull());
4100 
4101         BoolValue &LoopBodyFooVal =
4102             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
4103         EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4104       });
4105 }
4106 
4107 TEST(TransferTest, ContextSensitiveOptionDisabled) {
4108   std::string Code = R"(
4109     bool GiveBool();
4110     void SetBool(bool &Var) { Var = true; }
4111 
4112     void target() {
4113       bool Foo = GiveBool();
4114       SetBool(Foo);
4115       // [[p]]
4116     }
4117   )";
4118   runDataflow(
4119       Code,
4120       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4121          ASTContext &ASTCtx) {
4122         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4123         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4124 
4125         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4126         ASSERT_THAT(FooDecl, NotNull());
4127 
4128         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4129         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4130         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4131       },
4132       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
4133 }
4134 
4135 // This test is a regression test, based on a real crash.
4136 TEST(TransferTest, ContextSensitiveReturnReferenceFromNonReferenceLvalue) {
4137   // This code exercises an unusual code path. If we return an lvalue directly,
4138   // the code will catch that it's an l-value based on the `Value`'s kind. If we
4139   // pass through a dummy function, the framework won't populate a value at
4140   // all. In contrast, this code results in a (fresh) value, but it is not
4141   // `ReferenceValue`. This test verifies that we catch this case as well.
4142   std::string Code = R"(
4143     class S {};
4144     S& target(bool b, S &s) {
4145       return b ? s : s;
4146       // [[p]]
4147     }
4148   )";
4149   runDataflow(
4150       Code,
4151       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4152          ASTContext &ASTCtx) {
4153         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4154         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4155 
4156         auto *Loc = Env.getReturnStorageLocation();
4157         ASSERT_THAT(Loc, NotNull());
4158 
4159         EXPECT_THAT(Env.getValue(*Loc), IsNull());
4160       },
4161       {BuiltinOptions{ContextSensitiveOptions{}}});
4162 }
4163 
4164 TEST(TransferTest, ContextSensitiveDepthZero) {
4165   std::string Code = R"(
4166     bool GiveBool();
4167     void SetBool(bool &Var) { Var = true; }
4168 
4169     void target() {
4170       bool Foo = GiveBool();
4171       SetBool(Foo);
4172       // [[p]]
4173     }
4174   )";
4175   runDataflow(
4176       Code,
4177       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4178          ASTContext &ASTCtx) {
4179         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4180         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4181 
4182         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4183         ASSERT_THAT(FooDecl, NotNull());
4184 
4185         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4186         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4187         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4188       },
4189       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
4190 }
4191 
4192 TEST(TransferTest, ContextSensitiveSetTrue) {
4193   std::string Code = R"(
4194     bool GiveBool();
4195     void SetBool(bool &Var) { Var = true; }
4196 
4197     void target() {
4198       bool Foo = GiveBool();
4199       SetBool(Foo);
4200       // [[p]]
4201     }
4202   )";
4203   runDataflow(
4204       Code,
4205       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4206          ASTContext &ASTCtx) {
4207         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4208         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4209 
4210         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4211         ASSERT_THAT(FooDecl, NotNull());
4212 
4213         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4214         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4215       },
4216       {BuiltinOptions{ContextSensitiveOptions{}}});
4217 }
4218 
4219 TEST(TransferTest, ContextSensitiveSetFalse) {
4220   std::string Code = R"(
4221     bool GiveBool();
4222     void SetBool(bool &Var) { Var = false; }
4223 
4224     void target() {
4225       bool Foo = GiveBool();
4226       SetBool(Foo);
4227       // [[p]]
4228     }
4229   )";
4230   runDataflow(
4231       Code,
4232       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4233          ASTContext &ASTCtx) {
4234         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4235         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4236 
4237         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4238         ASSERT_THAT(FooDecl, NotNull());
4239 
4240         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4241         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4242       },
4243       {BuiltinOptions{ContextSensitiveOptions{}}});
4244 }
4245 
4246 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
4247   std::string Code = R"(
4248     bool GiveBool();
4249     void SetBool(bool &Var, bool Val) { Var = Val; }
4250 
4251     void target() {
4252       bool Foo = GiveBool();
4253       bool Bar = GiveBool();
4254       SetBool(Foo, true);
4255       SetBool(Bar, false);
4256       // [[p]]
4257     }
4258   )";
4259   runDataflow(
4260       Code,
4261       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4262          ASTContext &ASTCtx) {
4263         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4264         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4265 
4266         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4267         ASSERT_THAT(FooDecl, NotNull());
4268 
4269         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4270         ASSERT_THAT(BarDecl, NotNull());
4271 
4272         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4273         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4274         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4275 
4276         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
4277         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4278         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4279       },
4280       {BuiltinOptions{ContextSensitiveOptions{}}});
4281 }
4282 
4283 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
4284   std::string Code = R"(
4285     bool GiveBool();
4286     void SetBool1(bool &Var) { Var = true; }
4287     void SetBool2(bool &Var) { SetBool1(Var); }
4288 
4289     void target() {
4290       bool Foo = GiveBool();
4291       SetBool2(Foo);
4292       // [[p]]
4293     }
4294   )";
4295   runDataflow(
4296       Code,
4297       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4298          ASTContext &ASTCtx) {
4299         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4300         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4301 
4302         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4303         ASSERT_THAT(FooDecl, NotNull());
4304 
4305         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4306         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4307         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4308       },
4309       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
4310 }
4311 
4312 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
4313   std::string Code = R"(
4314     bool GiveBool();
4315     void SetBool1(bool &Var) { Var = true; }
4316     void SetBool2(bool &Var) { SetBool1(Var); }
4317 
4318     void target() {
4319       bool Foo = GiveBool();
4320       SetBool2(Foo);
4321       // [[p]]
4322     }
4323   )";
4324   runDataflow(
4325       Code,
4326       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4327          ASTContext &ASTCtx) {
4328         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4329         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4330 
4331         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4332         ASSERT_THAT(FooDecl, NotNull());
4333 
4334         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4335         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4336       },
4337       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4338 }
4339 
4340 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
4341   std::string Code = R"(
4342     bool GiveBool();
4343     void SetBool1(bool &Var) { Var = true; }
4344     void SetBool2(bool &Var) { SetBool1(Var); }
4345     void SetBool3(bool &Var) { SetBool2(Var); }
4346 
4347     void target() {
4348       bool Foo = GiveBool();
4349       SetBool3(Foo);
4350       // [[p]]
4351     }
4352   )";
4353   runDataflow(
4354       Code,
4355       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4356          ASTContext &ASTCtx) {
4357         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4358         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4359 
4360         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4361         ASSERT_THAT(FooDecl, NotNull());
4362 
4363         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4364         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4365         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4366       },
4367       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4368 }
4369 
4370 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
4371   std::string Code = R"(
4372     bool GiveBool();
4373     void SetBool1(bool &Var) { Var = true; }
4374     void SetBool2(bool &Var) { SetBool1(Var); }
4375     void SetBool3(bool &Var) { SetBool2(Var); }
4376 
4377     void target() {
4378       bool Foo = GiveBool();
4379       SetBool3(Foo);
4380       // [[p]]
4381     }
4382   )";
4383   runDataflow(
4384       Code,
4385       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4386          ASTContext &ASTCtx) {
4387         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4388         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4389 
4390         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4391         ASSERT_THAT(FooDecl, NotNull());
4392 
4393         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4394         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4395       },
4396       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
4397 }
4398 
4399 TEST(TransferTest, ContextSensitiveMutualRecursion) {
4400   std::string Code = R"(
4401     bool Pong(bool X, bool Y);
4402 
4403     bool Ping(bool X, bool Y) {
4404       if (X) {
4405         return Y;
4406       } else {
4407         return Pong(!X, Y);
4408       }
4409     }
4410 
4411     bool Pong(bool X, bool Y) {
4412       if (Y) {
4413         return X;
4414       } else {
4415         return Ping(X, !Y);
4416       }
4417     }
4418 
4419     void target() {
4420       bool Foo = Ping(false, false);
4421       // [[p]]
4422     }
4423   )";
4424   runDataflow(
4425       Code,
4426       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4427          ASTContext &ASTCtx) {
4428         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4429         // The analysis doesn't crash...
4430         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4431 
4432         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4433         ASSERT_THAT(FooDecl, NotNull());
4434 
4435         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4436         // ... but it also can't prove anything here.
4437         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4438         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4439       },
4440       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
4441 }
4442 
4443 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
4444   std::string Code = R"(
4445     void SetBools(bool &Var1, bool &Var2) {
4446       Var1 = true;
4447       Var2 = false;
4448     }
4449 
4450     void target() {
4451       bool Foo = false;
4452       bool Bar = true;
4453       SetBools(Foo, Bar);
4454       // [[p]]
4455     }
4456   )";
4457   runDataflow(
4458       Code,
4459       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4460          ASTContext &ASTCtx) {
4461         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4462         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4463 
4464         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4465         ASSERT_THAT(FooDecl, NotNull());
4466 
4467         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4468         ASSERT_THAT(BarDecl, NotNull());
4469 
4470         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4471         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4472         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4473 
4474         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
4475         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4476         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4477       },
4478       {BuiltinOptions{ContextSensitiveOptions{}}});
4479 }
4480 
4481 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
4482   std::string Code = R"(
4483     void IfCond(bool Cond, bool &Then, bool &Else) {
4484       if (Cond) {
4485         Then = true;
4486       } else {
4487         Else = true;
4488       }
4489     }
4490 
4491     void target() {
4492       bool Foo = false;
4493       bool Bar = false;
4494       bool Baz = false;
4495       IfCond(Foo, Bar, Baz);
4496       // [[p]]
4497     }
4498   )";
4499   runDataflow(
4500       Code,
4501       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4502          ASTContext &ASTCtx) {
4503         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4504         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4505 
4506         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4507         ASSERT_THAT(BarDecl, NotNull());
4508 
4509         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4510         ASSERT_THAT(BazDecl, NotNull());
4511 
4512         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
4513         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4514         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4515 
4516         auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl, SkipPast::None));
4517         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
4518         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(BazVal)));
4519       },
4520       {BuiltinOptions{ContextSensitiveOptions{}}});
4521 }
4522 
4523 TEST(TransferTest, ContextSensitiveReturnVoid) {
4524   std::string Code = R"(
4525     void Noop() { return; }
4526 
4527     void target() {
4528       Noop();
4529       // [[p]]
4530     }
4531   )";
4532   runDataflow(
4533       Code,
4534       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4535          ASTContext &ASTCtx) {
4536         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4537         // This just tests that the analysis doesn't crash.
4538       },
4539       {BuiltinOptions{ContextSensitiveOptions{}}});
4540 }
4541 
4542 TEST(TransferTest, ContextSensitiveReturnTrue) {
4543   std::string Code = R"(
4544     bool GiveBool() { return true; }
4545 
4546     void target() {
4547       bool Foo = GiveBool();
4548       // [[p]]
4549     }
4550   )";
4551   runDataflow(
4552       Code,
4553       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4554          ASTContext &ASTCtx) {
4555         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4556         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4557 
4558         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4559         ASSERT_THAT(FooDecl, NotNull());
4560 
4561         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4562         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4563       },
4564       {BuiltinOptions{ContextSensitiveOptions{}}});
4565 }
4566 
4567 TEST(TransferTest, ContextSensitiveReturnFalse) {
4568   std::string Code = R"(
4569     bool GiveBool() { return false; }
4570 
4571     void target() {
4572       bool Foo = GiveBool();
4573       // [[p]]
4574     }
4575   )";
4576   runDataflow(
4577       Code,
4578       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4579          ASTContext &ASTCtx) {
4580         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4581         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4582 
4583         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4584         ASSERT_THAT(FooDecl, NotNull());
4585 
4586         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4587         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4588       },
4589       {BuiltinOptions{ContextSensitiveOptions{}}});
4590 }
4591 
4592 TEST(TransferTest, ContextSensitiveReturnArg) {
4593   std::string Code = R"(
4594     bool GiveBool();
4595     bool GiveBack(bool Arg) { return Arg; }
4596 
4597     void target() {
4598       bool Foo = GiveBool();
4599       bool Bar = GiveBack(Foo);
4600       bool Baz = Foo == Bar;
4601       // [[p]]
4602     }
4603   )";
4604   runDataflow(
4605       Code,
4606       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4607          ASTContext &ASTCtx) {
4608         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4609         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4610 
4611         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4612         ASSERT_THAT(BazDecl, NotNull());
4613 
4614         auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl, SkipPast::None));
4615         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
4616       },
4617       {BuiltinOptions{ContextSensitiveOptions{}}});
4618 }
4619 
4620 TEST(TransferTest, ContextSensitiveReturnInt) {
4621   std::string Code = R"(
4622     int identity(int x) { return x; }
4623 
4624     void target() {
4625       int y = identity(42);
4626       // [[p]]
4627     }
4628   )";
4629   runDataflow(
4630       Code,
4631       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4632          ASTContext &ASTCtx) {
4633         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4634         // This just tests that the analysis doesn't crash.
4635       },
4636       {BuiltinOptions{ContextSensitiveOptions{}}});
4637 }
4638 
4639 TEST(TransferTest, ContextSensitiveMethodLiteral) {
4640   std::string Code = R"(
4641     class MyClass {
4642     public:
4643       bool giveBool() { return true; }
4644     };
4645 
4646     void target() {
4647       MyClass MyObj;
4648       bool Foo = MyObj.giveBool();
4649       // [[p]]
4650     }
4651   )";
4652   runDataflow(
4653       Code,
4654       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4655          ASTContext &ASTCtx) {
4656         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4657         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4658 
4659         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4660         ASSERT_THAT(FooDecl, NotNull());
4661 
4662         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4663         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4664       },
4665       {BuiltinOptions{ContextSensitiveOptions{}}});
4666 }
4667 
4668 TEST(TransferTest, ContextSensitiveMethodGetter) {
4669   std::string Code = R"(
4670     class MyClass {
4671     public:
4672       bool getField() { return Field; }
4673 
4674       bool Field;
4675     };
4676 
4677     void target() {
4678       MyClass MyObj;
4679       MyObj.Field = true;
4680       bool Foo = MyObj.getField();
4681       // [[p]]
4682     }
4683   )";
4684   runDataflow(
4685       Code,
4686       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4687          ASTContext &ASTCtx) {
4688         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4689         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4690 
4691         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4692         ASSERT_THAT(FooDecl, NotNull());
4693 
4694         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4695         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4696       },
4697       {BuiltinOptions{ContextSensitiveOptions{}}});
4698 }
4699 
4700 TEST(TransferTest, ContextSensitiveMethodSetter) {
4701   std::string Code = R"(
4702     class MyClass {
4703     public:
4704       void setField(bool Val) { Field = Val; }
4705 
4706       bool Field;
4707     };
4708 
4709     void target() {
4710       MyClass MyObj;
4711       MyObj.setField(true);
4712       bool Foo = MyObj.Field;
4713       // [[p]]
4714     }
4715   )";
4716   runDataflow(
4717       Code,
4718       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4719          ASTContext &ASTCtx) {
4720         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4721         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4722 
4723         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4724         ASSERT_THAT(FooDecl, NotNull());
4725 
4726         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4727         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4728       },
4729       {BuiltinOptions{ContextSensitiveOptions{}}});
4730 }
4731 
4732 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
4733   std::string Code = R"(
4734     class MyClass {
4735     public:
4736       bool getField() { return Field; }
4737       void setField(bool Val) { Field = Val; }
4738 
4739     private:
4740       bool Field;
4741     };
4742 
4743     void target() {
4744       MyClass MyObj;
4745       MyObj.setField(true);
4746       bool Foo = MyObj.getField();
4747       // [[p]]
4748     }
4749   )";
4750   runDataflow(
4751       Code,
4752       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4753          ASTContext &ASTCtx) {
4754         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4755         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4756 
4757         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4758         ASSERT_THAT(FooDecl, NotNull());
4759 
4760         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4761         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4762       },
4763       {BuiltinOptions{ContextSensitiveOptions{}}});
4764 }
4765 
4766 
4767 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
4768   std::string Code = R"(
4769     class MyClass {
4770     public:
4771       void Inner() { MyField = true; }
4772       void Outer() { Inner(); }
4773 
4774       bool MyField;
4775     };
4776 
4777     void target() {
4778       MyClass MyObj;
4779       MyObj.Outer();
4780       bool Foo = MyObj.MyField;
4781       // [[p]]
4782     }
4783   )";
4784   runDataflow(
4785       Code,
4786       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4787          ASTContext &ASTCtx) {
4788         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4789         ;
4790         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4791 
4792         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4793         ASSERT_THAT(FooDecl, NotNull());
4794 
4795         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4796         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4797       },
4798       {BuiltinOptions{ContextSensitiveOptions{}}});
4799 }
4800 
4801 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
4802   std::string Code = R"(
4803     class MyClass {
4804     public:
4805       bool Inner() { return MyField; }
4806       bool Outer() { return Inner(); }
4807 
4808       bool MyField;
4809     };
4810 
4811     void target() {
4812       MyClass MyObj;
4813       MyObj.MyField = true;
4814       bool Foo = MyObj.Outer();
4815       // [[p]]
4816     }
4817   )";
4818   runDataflow(
4819       Code,
4820       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4821          ASTContext &ASTCtx) {
4822         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4823         ;
4824         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4825 
4826         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4827         ASSERT_THAT(FooDecl, NotNull());
4828 
4829         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4830         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4831       },
4832       {BuiltinOptions{ContextSensitiveOptions{}}});
4833 }
4834 
4835 TEST(TransferTest, ContextSensitiveConstructorBody) {
4836   std::string Code = R"(
4837     class MyClass {
4838     public:
4839       MyClass() { MyField = true; }
4840 
4841       bool MyField;
4842     };
4843 
4844     void target() {
4845       MyClass MyObj;
4846       bool Foo = MyObj.MyField;
4847       // [[p]]
4848     }
4849   )";
4850   runDataflow(
4851       Code,
4852       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4853          ASTContext &ASTCtx) {
4854         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4855         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4856 
4857         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4858         ASSERT_THAT(FooDecl, NotNull());
4859 
4860         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4861         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4862       },
4863       {BuiltinOptions{ContextSensitiveOptions{}}});
4864 }
4865 
4866 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
4867   std::string Code = R"(
4868     class MyClass {
4869     public:
4870       MyClass() : MyField(true) {}
4871 
4872       bool MyField;
4873     };
4874 
4875     void target() {
4876       MyClass MyObj;
4877       bool Foo = MyObj.MyField;
4878       // [[p]]
4879     }
4880   )";
4881   runDataflow(
4882       Code,
4883       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4884          ASTContext &ASTCtx) {
4885         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4886         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4887 
4888         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4889         ASSERT_THAT(FooDecl, NotNull());
4890 
4891         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4892         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4893       },
4894       {BuiltinOptions{ContextSensitiveOptions{}}});
4895 }
4896 
4897 TEST(TransferTest, ContextSensitiveConstructorDefault) {
4898   std::string Code = R"(
4899     class MyClass {
4900     public:
4901       MyClass() = default;
4902 
4903       bool MyField = true;
4904     };
4905 
4906     void target() {
4907       MyClass MyObj;
4908       bool Foo = MyObj.MyField;
4909       // [[p]]
4910     }
4911   )";
4912   runDataflow(
4913       Code,
4914       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4915          ASTContext &ASTCtx) {
4916         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4917         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4918 
4919         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4920         ASSERT_THAT(FooDecl, NotNull());
4921 
4922         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4923         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4924       },
4925       {BuiltinOptions{ContextSensitiveOptions{}}});
4926 }
4927 
4928 } // namespace
4929