xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision 3ce03c42dbb46531968c527d80c0243c2db7bc0e)
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, StructMemberEnum) {
1070   std::string Code = R"(
1071     struct A {
1072       int Bar;
1073       enum E { ONE, TWO };
1074     };
1075 
1076     void target(A Foo) {
1077       A::E Baz = Foo.ONE;
1078       // [[p]]
1079     }
1080   )";
1081   // Minimal expectations -- we're just testing that it doesn't crash, since
1082   // enums aren't interpreted.
1083   runDataflow(
1084       Code,
1085       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1086          ASTContext &ASTCtx) {
1087         EXPECT_THAT(Results.keys(), UnorderedElementsAre("p"));
1088       });
1089 }
1090 
1091 TEST(TransferTest, DerivedBaseMemberClass) {
1092   std::string Code = R"(
1093     class A {
1094       int ADefault;
1095     protected:
1096       int AProtected;
1097     private:
1098       int APrivate;
1099     public:
1100       int APublic;
1101 
1102     private:
1103       friend void target();
1104     };
1105 
1106     class B : public A {
1107       int BDefault;
1108     protected:
1109       int BProtected;
1110     private:
1111       int BPrivate;
1112 
1113     private:
1114       friend void target();
1115     };
1116 
1117     void target() {
1118       B Foo;
1119       (void)Foo.ADefault;
1120       (void)Foo.AProtected;
1121       (void)Foo.APrivate;
1122       (void)Foo.APublic;
1123       (void)Foo.BDefault;
1124       (void)Foo.BProtected;
1125       (void)Foo.BPrivate;
1126       // [[p]]
1127     }
1128   )";
1129   runDataflow(
1130       Code,
1131       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1132          ASTContext &ASTCtx) {
1133         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1134         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1135 
1136         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1137         ASSERT_THAT(FooDecl, NotNull());
1138         ASSERT_TRUE(FooDecl->getType()->isRecordType());
1139 
1140         // Derived-class fields.
1141         const FieldDecl *BDefaultDecl = nullptr;
1142         const FieldDecl *BProtectedDecl = nullptr;
1143         const FieldDecl *BPrivateDecl = nullptr;
1144         for (const FieldDecl *Field :
1145              FooDecl->getType()->getAsRecordDecl()->fields()) {
1146           if (Field->getNameAsString() == "BDefault") {
1147             BDefaultDecl = Field;
1148           } else if (Field->getNameAsString() == "BProtected") {
1149             BProtectedDecl = Field;
1150           } else if (Field->getNameAsString() == "BPrivate") {
1151             BPrivateDecl = Field;
1152           } else {
1153             FAIL() << "Unexpected field: " << Field->getNameAsString();
1154           }
1155         }
1156         ASSERT_THAT(BDefaultDecl, NotNull());
1157         ASSERT_THAT(BProtectedDecl, NotNull());
1158         ASSERT_THAT(BPrivateDecl, NotNull());
1159 
1160         // Base-class fields.
1161         const FieldDecl *ADefaultDecl = nullptr;
1162         const FieldDecl *APrivateDecl = nullptr;
1163         const FieldDecl *AProtectedDecl = nullptr;
1164         const FieldDecl *APublicDecl = nullptr;
1165         for (const clang::CXXBaseSpecifier &Base :
1166              FooDecl->getType()->getAsCXXRecordDecl()->bases()) {
1167           QualType BaseType = Base.getType();
1168           ASSERT_TRUE(BaseType->isRecordType());
1169           for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) {
1170             if (Field->getNameAsString() == "ADefault") {
1171               ADefaultDecl = Field;
1172             } else if (Field->getNameAsString() == "AProtected") {
1173               AProtectedDecl = Field;
1174             } else if (Field->getNameAsString() == "APrivate") {
1175               APrivateDecl = Field;
1176             } else if (Field->getNameAsString() == "APublic") {
1177               APublicDecl = Field;
1178             } else {
1179               FAIL() << "Unexpected field: " << Field->getNameAsString();
1180             }
1181           }
1182         }
1183         ASSERT_THAT(ADefaultDecl, NotNull());
1184         ASSERT_THAT(AProtectedDecl, NotNull());
1185         ASSERT_THAT(APrivateDecl, NotNull());
1186         ASSERT_THAT(APublicDecl, NotNull());
1187 
1188         const auto &FooLoc = *cast<AggregateStorageLocation>(
1189             Env.getStorageLocation(*FooDecl, SkipPast::None));
1190         const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc));
1191 
1192         // Note: we can't test presence of children in `FooLoc`, because
1193         // `getChild` requires its argument be present (or fails an assert). So,
1194         // we limit to testing presence in `FooVal` and coherence between the
1195         // two.
1196 
1197         // Base-class fields.
1198         EXPECT_THAT(FooVal.getChild(*ADefaultDecl), NotNull());
1199         EXPECT_THAT(FooVal.getChild(*APrivateDecl), NotNull());
1200 
1201         EXPECT_THAT(FooVal.getChild(*AProtectedDecl), NotNull());
1202         EXPECT_EQ(Env.getValue(FooLoc.getChild(*APublicDecl)),
1203                   FooVal.getChild(*APublicDecl));
1204         EXPECT_THAT(FooVal.getChild(*APublicDecl), NotNull());
1205         EXPECT_EQ(Env.getValue(FooLoc.getChild(*AProtectedDecl)),
1206                   FooVal.getChild(*AProtectedDecl));
1207 
1208         // Derived-class fields.
1209         EXPECT_THAT(FooVal.getChild(*BDefaultDecl), NotNull());
1210         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BDefaultDecl)),
1211                   FooVal.getChild(*BDefaultDecl));
1212         EXPECT_THAT(FooVal.getChild(*BProtectedDecl), NotNull());
1213         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BProtectedDecl)),
1214                   FooVal.getChild(*BProtectedDecl));
1215         EXPECT_THAT(FooVal.getChild(*BPrivateDecl), NotNull());
1216         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BPrivateDecl)),
1217                   FooVal.getChild(*BPrivateDecl));
1218       });
1219 }
1220 
1221 static void derivedBaseMemberExpectations(
1222     const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1223     ASTContext &ASTCtx) {
1224   ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1225   const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1226 
1227   const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1228   ASSERT_THAT(FooDecl, NotNull());
1229 
1230   ASSERT_TRUE(FooDecl->getType()->isRecordType());
1231   const FieldDecl *BarDecl = nullptr;
1232   for (const clang::CXXBaseSpecifier &Base :
1233        FooDecl->getType()->getAsCXXRecordDecl()->bases()) {
1234     QualType BaseType = Base.getType();
1235     ASSERT_TRUE(BaseType->isStructureType());
1236 
1237     for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) {
1238       if (Field->getNameAsString() == "Bar") {
1239         BarDecl = Field;
1240       } else {
1241         FAIL() << "Unexpected field: " << Field->getNameAsString();
1242       }
1243     }
1244   }
1245   ASSERT_THAT(BarDecl, NotNull());
1246 
1247   const auto &FooLoc = *cast<AggregateStorageLocation>(
1248       Env.getStorageLocation(*FooDecl, SkipPast::None));
1249   const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc));
1250   EXPECT_THAT(FooVal.getChild(*BarDecl), NotNull());
1251   EXPECT_EQ(Env.getValue(FooLoc.getChild(*BarDecl)), FooVal.getChild(*BarDecl));
1252 }
1253 
1254 TEST(TransferTest, DerivedBaseMemberStructDefault) {
1255   std::string Code = R"(
1256     struct A {
1257       int Bar;
1258     };
1259     struct B : public A {
1260     };
1261 
1262     void target() {
1263       B Foo;
1264       (void)Foo.Bar;
1265       // [[p]]
1266     }
1267   )";
1268   runDataflow(Code, derivedBaseMemberExpectations);
1269 }
1270 
1271 TEST(TransferTest, DerivedBaseMemberPrivateFriend) {
1272   // Include an access to `Foo.Bar` to verify the analysis doesn't crash on that
1273   // access.
1274   std::string Code = R"(
1275     struct A {
1276     private:
1277       friend void target();
1278       int Bar;
1279     };
1280     struct B : public A {
1281     };
1282 
1283     void target() {
1284       B Foo;
1285       (void)Foo.Bar;
1286       // [[p]]
1287     }
1288   )";
1289   runDataflow(Code, derivedBaseMemberExpectations);
1290 }
1291 
1292 TEST(TransferTest, ClassMember) {
1293   std::string Code = R"(
1294     class A {
1295     public:
1296       int Bar;
1297     };
1298 
1299     void target(A Foo) {
1300       int Baz = Foo.Bar;
1301       // [[p]]
1302     }
1303   )";
1304   runDataflow(
1305       Code,
1306       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1307          ASTContext &ASTCtx) {
1308         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1309         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1310 
1311         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1312         ASSERT_THAT(FooDecl, NotNull());
1313 
1314         ASSERT_TRUE(FooDecl->getType()->isClassType());
1315         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1316 
1317         FieldDecl *BarDecl = nullptr;
1318         for (FieldDecl *Field : FooFields) {
1319           if (Field->getNameAsString() == "Bar") {
1320             BarDecl = Field;
1321           } else {
1322             FAIL() << "Unexpected field: " << Field->getNameAsString();
1323           }
1324         }
1325         ASSERT_THAT(BarDecl, NotNull());
1326 
1327         const auto *FooLoc = cast<AggregateStorageLocation>(
1328             Env.getStorageLocation(*FooDecl, SkipPast::None));
1329         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1330         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1331 
1332         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1333         ASSERT_THAT(BazDecl, NotNull());
1334 
1335         EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal);
1336       });
1337 }
1338 
1339 TEST(TransferTest, BaseClassInitializer) {
1340   using ast_matchers::cxxConstructorDecl;
1341   using ast_matchers::hasName;
1342   using ast_matchers::ofClass;
1343 
1344   std::string Code = R"(
1345     class A {
1346     public:
1347       A(int I) : Bar(I) {}
1348       int Bar;
1349     };
1350 
1351     class B : public A {
1352     public:
1353       B(int I) : A(I) {
1354         (void)0;
1355         // [[p]]
1356       }
1357     };
1358   )";
1359   ASSERT_THAT_ERROR(
1360       checkDataflow<NoopAnalysis>(
1361           AnalysisInputs<NoopAnalysis>(
1362               Code, cxxConstructorDecl(ofClass(hasName("B"))),
1363               [](ASTContext &C, Environment &) {
1364                 return NoopAnalysis(C, /*ApplyBuiltinTransfer=*/true);
1365               })
1366               .withASTBuildArgs(
1367                   {"-fsyntax-only", "-fno-delayed-template-parsing",
1368                    "-std=" + std::string(LangStandard::getLangStandardForKind(
1369                                              LangStandard::lang_cxx17)
1370                                              .getName())}),
1371           /*VerifyResults=*/
1372           [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1373              const AnalysisOutputs &) {
1374             // Regression test to verify that base-class initializers do not
1375             // trigger an assertion. If we add support for such initializers in
1376             // the future, we can expand this test to check more specific
1377             // properties.
1378             EXPECT_THAT(Results.keys(), UnorderedElementsAre("p"));
1379           }),
1380       llvm::Succeeded());
1381 }
1382 
1383 TEST(TransferTest, ReferenceMember) {
1384   std::string Code = R"(
1385     struct A {
1386       int &Bar;
1387     };
1388 
1389     void target(A Foo) {
1390       int Baz = Foo.Bar;
1391       // [[p]]
1392     }
1393   )";
1394   runDataflow(
1395       Code,
1396       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1397          ASTContext &ASTCtx) {
1398         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1399         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1400 
1401         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1402         ASSERT_THAT(FooDecl, NotNull());
1403 
1404         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1405         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1406 
1407         FieldDecl *BarDecl = nullptr;
1408         for (FieldDecl *Field : FooFields) {
1409           if (Field->getNameAsString() == "Bar") {
1410             BarDecl = Field;
1411           } else {
1412             FAIL() << "Unexpected field: " << Field->getNameAsString();
1413           }
1414         }
1415         ASSERT_THAT(BarDecl, NotNull());
1416 
1417         const auto *FooLoc = cast<AggregateStorageLocation>(
1418             Env.getStorageLocation(*FooDecl, SkipPast::None));
1419         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1420         const auto *BarVal = cast<ReferenceValue>(FooVal->getChild(*BarDecl));
1421         const auto *BarReferentVal =
1422             cast<IntegerValue>(Env.getValue(BarVal->getReferentLoc()));
1423 
1424         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1425         ASSERT_THAT(BazDecl, NotNull());
1426 
1427         EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarReferentVal);
1428       });
1429 }
1430 
1431 TEST(TransferTest, StructThisMember) {
1432   std::string Code = R"(
1433     struct A {
1434       int Bar;
1435 
1436       struct B {
1437         int Baz;
1438       };
1439 
1440       B Qux;
1441 
1442       void target() {
1443         int Foo = Bar;
1444         int Quux = Qux.Baz;
1445         // [[p]]
1446       }
1447     };
1448   )";
1449   runDataflow(
1450       Code,
1451       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1452          ASTContext &ASTCtx) {
1453         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1454         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1455 
1456         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1457             Env.getThisPointeeStorageLocation());
1458         ASSERT_THAT(ThisLoc, NotNull());
1459 
1460         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1461         ASSERT_THAT(BarDecl, NotNull());
1462 
1463         const auto *BarLoc =
1464             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1465         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1466 
1467         const Value *BarVal = Env.getValue(*BarLoc);
1468         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1469 
1470         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1471         ASSERT_THAT(FooDecl, NotNull());
1472         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1473 
1474         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1475         ASSERT_THAT(QuxDecl, NotNull());
1476 
1477         ASSERT_TRUE(QuxDecl->getType()->isStructureType());
1478         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1479 
1480         FieldDecl *BazDecl = nullptr;
1481         for (FieldDecl *Field : QuxFields) {
1482           if (Field->getNameAsString() == "Baz") {
1483             BazDecl = Field;
1484           } else {
1485             FAIL() << "Unexpected field: " << Field->getNameAsString();
1486           }
1487         }
1488         ASSERT_THAT(BazDecl, NotNull());
1489 
1490         const auto *QuxLoc =
1491             cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl));
1492         const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc));
1493         ASSERT_THAT(QuxVal, NotNull());
1494 
1495         const auto *BazLoc =
1496             cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl));
1497         const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl));
1498         EXPECT_EQ(Env.getValue(*BazLoc), BazVal);
1499 
1500         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1501         ASSERT_THAT(QuuxDecl, NotNull());
1502         EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal);
1503       });
1504 }
1505 
1506 TEST(TransferTest, ClassThisMember) {
1507   std::string Code = R"(
1508     class A {
1509       int Bar;
1510 
1511       class B {
1512       public:
1513         int Baz;
1514       };
1515 
1516       B Qux;
1517 
1518       void target() {
1519         int Foo = Bar;
1520         int Quux = Qux.Baz;
1521         // [[p]]
1522       }
1523     };
1524   )";
1525   runDataflow(
1526       Code,
1527       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1528          ASTContext &ASTCtx) {
1529         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1530         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1531 
1532         const auto *ThisLoc =
1533             cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation());
1534 
1535         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1536         ASSERT_THAT(BarDecl, NotNull());
1537 
1538         const auto *BarLoc =
1539             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1540         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1541 
1542         const Value *BarVal = Env.getValue(*BarLoc);
1543         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1544 
1545         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1546         ASSERT_THAT(FooDecl, NotNull());
1547         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1548 
1549         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1550         ASSERT_THAT(QuxDecl, NotNull());
1551 
1552         ASSERT_TRUE(QuxDecl->getType()->isClassType());
1553         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1554 
1555         FieldDecl *BazDecl = nullptr;
1556         for (FieldDecl *Field : QuxFields) {
1557           if (Field->getNameAsString() == "Baz") {
1558             BazDecl = Field;
1559           } else {
1560             FAIL() << "Unexpected field: " << Field->getNameAsString();
1561           }
1562         }
1563         ASSERT_THAT(BazDecl, NotNull());
1564 
1565         const auto *QuxLoc =
1566             cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl));
1567         const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc));
1568         ASSERT_THAT(QuxVal, NotNull());
1569 
1570         const auto *BazLoc =
1571             cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl));
1572         const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl));
1573         EXPECT_EQ(Env.getValue(*BazLoc), BazVal);
1574 
1575         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1576         ASSERT_THAT(QuuxDecl, NotNull());
1577         EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal);
1578       });
1579 }
1580 
1581 TEST(TransferTest, UnionThisMember) {
1582   std::string Code = R"(
1583     union A {
1584       int Foo;
1585       int Bar;
1586 
1587       void target() {
1588         A a;
1589         // Mention the fields to ensure they're included in the analysis.
1590         (void)a.Foo;
1591         (void)a.Bar;
1592         // [[p]]
1593       }
1594     };
1595   )";
1596   runDataflow(
1597       Code,
1598       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1599          ASTContext &ASTCtx) {
1600         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1601         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1602 
1603         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1604             Env.getThisPointeeStorageLocation());
1605         ASSERT_THAT(ThisLoc, NotNull());
1606 
1607         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1608         ASSERT_THAT(FooDecl, NotNull());
1609 
1610         const auto *FooLoc =
1611             cast<ScalarStorageLocation>(&ThisLoc->getChild(*FooDecl));
1612         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1613 
1614         const Value *FooVal = Env.getValue(*FooLoc);
1615         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
1616 
1617         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1618         ASSERT_THAT(BarDecl, NotNull());
1619 
1620         const auto *BarLoc =
1621             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1622         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1623 
1624         const Value *BarVal = Env.getValue(*BarLoc);
1625         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1626       });
1627 }
1628 
1629 TEST(TransferTest, StructThisInLambda) {
1630   std::string ThisCaptureCode = R"(
1631     struct A {
1632       void frob() {
1633         [this]() {
1634           int Foo = Bar;
1635           // [[p1]]
1636         }();
1637       }
1638 
1639       int Bar;
1640     };
1641   )";
1642   runDataflow(
1643       ThisCaptureCode,
1644       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1645          ASTContext &ASTCtx) {
1646         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1"));
1647         const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
1648 
1649         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1650             Env.getThisPointeeStorageLocation());
1651         ASSERT_THAT(ThisLoc, NotNull());
1652 
1653         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1654         ASSERT_THAT(BarDecl, NotNull());
1655 
1656         const auto *BarLoc =
1657             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1658         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1659 
1660         const Value *BarVal = Env.getValue(*BarLoc);
1661         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1662 
1663         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1664         ASSERT_THAT(FooDecl, NotNull());
1665         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1666       },
1667       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1668 
1669   std::string RefCaptureDefaultCode = R"(
1670     struct A {
1671       void frob() {
1672         [&]() {
1673           int Foo = Bar;
1674           // [[p2]]
1675         }();
1676       }
1677 
1678       int Bar;
1679     };
1680   )";
1681   runDataflow(
1682       RefCaptureDefaultCode,
1683       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1684          ASTContext &ASTCtx) {
1685         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p2"));
1686         const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
1687 
1688         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1689             Env.getThisPointeeStorageLocation());
1690         ASSERT_THAT(ThisLoc, NotNull());
1691 
1692         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1693         ASSERT_THAT(BarDecl, NotNull());
1694 
1695         const auto *BarLoc =
1696             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1697         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1698 
1699         const Value *BarVal = Env.getValue(*BarLoc);
1700         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1701 
1702         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1703         ASSERT_THAT(FooDecl, NotNull());
1704         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1705       },
1706       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1707 
1708   std::string FreeFunctionLambdaCode = R"(
1709     void foo() {
1710       int Bar;
1711       [&]() {
1712         int Foo = Bar;
1713         // [[p3]]
1714       }();
1715     }
1716   )";
1717   runDataflow(
1718       FreeFunctionLambdaCode,
1719       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1720          ASTContext &ASTCtx) {
1721         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p3"));
1722         const Environment &Env = getEnvironmentAtAnnotation(Results, "p3");
1723 
1724         EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull());
1725       },
1726       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1727 }
1728 
1729 TEST(TransferTest, ConstructorInitializer) {
1730   std::string Code = R"(
1731     struct target {
1732       int Bar;
1733 
1734       target(int Foo) : Bar(Foo) {
1735         int Qux = Bar;
1736         // [[p]]
1737       }
1738     };
1739   )";
1740   runDataflow(
1741       Code,
1742       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1743          ASTContext &ASTCtx) {
1744         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1745         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1746 
1747         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1748             Env.getThisPointeeStorageLocation());
1749         ASSERT_THAT(ThisLoc, NotNull());
1750 
1751         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1752         ASSERT_THAT(FooDecl, NotNull());
1753 
1754         const auto *FooVal =
1755             cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None));
1756 
1757         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1758         ASSERT_THAT(QuxDecl, NotNull());
1759         EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal);
1760       });
1761 }
1762 
1763 TEST(TransferTest, DefaultInitializer) {
1764   std::string Code = R"(
1765     struct target {
1766       int Bar;
1767       int Baz = Bar;
1768 
1769       target(int Foo) : Bar(Foo) {
1770         int Qux = Baz;
1771         // [[p]]
1772       }
1773     };
1774   )";
1775   runDataflow(
1776       Code,
1777       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1778          ASTContext &ASTCtx) {
1779         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1780         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1781 
1782         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1783             Env.getThisPointeeStorageLocation());
1784         ASSERT_THAT(ThisLoc, NotNull());
1785 
1786         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1787         ASSERT_THAT(FooDecl, NotNull());
1788 
1789         const auto *FooVal =
1790             cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None));
1791 
1792         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1793         ASSERT_THAT(QuxDecl, NotNull());
1794         EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal);
1795       });
1796 }
1797 
1798 TEST(TransferTest, DefaultInitializerReference) {
1799   std::string Code = R"(
1800     struct target {
1801       int &Bar;
1802       int &Baz = Bar;
1803 
1804       target(int &Foo) : Bar(Foo) {
1805         int &Qux = Baz;
1806         // [[p]]
1807       }
1808     };
1809   )";
1810   runDataflow(
1811       Code,
1812       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1813          ASTContext &ASTCtx) {
1814         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1815         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1816 
1817         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1818             Env.getThisPointeeStorageLocation());
1819         ASSERT_THAT(ThisLoc, NotNull());
1820 
1821         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1822         ASSERT_THAT(FooDecl, NotNull());
1823 
1824         const auto *FooVal =
1825             cast<ReferenceValue>(Env.getValue(*FooDecl, SkipPast::None));
1826 
1827         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1828         ASSERT_THAT(QuxDecl, NotNull());
1829 
1830         const auto *QuxVal =
1831             cast<ReferenceValue>(Env.getValue(*QuxDecl, SkipPast::None));
1832         EXPECT_EQ(&QuxVal->getReferentLoc(), &FooVal->getReferentLoc());
1833       });
1834 }
1835 
1836 TEST(TransferTest, TemporaryObject) {
1837   std::string Code = R"(
1838     struct A {
1839       int Bar;
1840     };
1841 
1842     void target() {
1843       A Foo = A();
1844       (void)Foo.Bar;
1845       // [[p]]
1846     }
1847   )";
1848   runDataflow(
1849       Code,
1850       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1851          ASTContext &ASTCtx) {
1852         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1853         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1854 
1855         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1856         ASSERT_THAT(FooDecl, NotNull());
1857 
1858         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1859         ASSERT_THAT(BarDecl, NotNull());
1860 
1861         const auto *FooLoc = cast<AggregateStorageLocation>(
1862             Env.getStorageLocation(*FooDecl, SkipPast::None));
1863         const auto *BarLoc =
1864             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
1865 
1866         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1867         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1868         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
1869       });
1870 }
1871 
1872 TEST(TransferTest, ElidableConstructor) {
1873   // This test is effectively the same as TransferTest.TemporaryObject, but
1874   // the code is compiled as C++ 14.
1875   std::string Code = R"(
1876     struct A {
1877       int Bar;
1878     };
1879 
1880     void target() {
1881       A Foo = A();
1882       (void)Foo.Bar;
1883       // [[p]]
1884     }
1885   )";
1886   runDataflow(
1887       Code,
1888       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1889          ASTContext &ASTCtx) {
1890         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1891         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1892 
1893         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1894         ASSERT_THAT(FooDecl, NotNull());
1895 
1896         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1897         ASSERT_THAT(BarDecl, NotNull());
1898 
1899         const auto *FooLoc = cast<AggregateStorageLocation>(
1900             Env.getStorageLocation(*FooDecl, SkipPast::None));
1901         const auto *BarLoc =
1902             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
1903 
1904         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1905         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1906         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
1907       },
1908       LangStandard::lang_cxx14);
1909 }
1910 
1911 TEST(TransferTest, AssignmentOperator) {
1912   std::string Code = R"(
1913     struct A {
1914       int Baz;
1915     };
1916 
1917     void target() {
1918       A Foo;
1919       A Bar;
1920       (void)Foo.Baz;
1921       // [[p1]]
1922       Foo = Bar;
1923       // [[p2]]
1924     }
1925   )";
1926   runDataflow(
1927       Code,
1928       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1929          ASTContext &ASTCtx) {
1930         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
1931         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
1932         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
1933 
1934         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1935         ASSERT_THAT(FooDecl, NotNull());
1936 
1937         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1938         ASSERT_THAT(BarDecl, NotNull());
1939 
1940         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1941         ASSERT_THAT(BazDecl, NotNull());
1942 
1943         const auto *FooLoc1 = cast<AggregateStorageLocation>(
1944             Env1.getStorageLocation(*FooDecl, SkipPast::None));
1945         const auto *BarLoc1 = cast<AggregateStorageLocation>(
1946             Env1.getStorageLocation(*BarDecl, SkipPast::None));
1947 
1948         const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1));
1949         const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1));
1950         EXPECT_NE(FooVal1, BarVal1);
1951 
1952         const auto *FooBazVal1 =
1953             cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl)));
1954         const auto *BarBazVal1 =
1955             cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl)));
1956         EXPECT_NE(FooBazVal1, BarBazVal1);
1957 
1958         const auto *FooLoc2 = cast<AggregateStorageLocation>(
1959             Env2.getStorageLocation(*FooDecl, SkipPast::None));
1960         const auto *BarLoc2 = cast<AggregateStorageLocation>(
1961             Env2.getStorageLocation(*BarDecl, SkipPast::None));
1962 
1963         const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2));
1964         const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2));
1965         EXPECT_EQ(FooVal2, BarVal2);
1966 
1967         const auto *FooBazVal2 =
1968             cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl)));
1969         const auto *BarBazVal2 =
1970             cast<IntegerValue>(Env2.getValue(BarLoc1->getChild(*BazDecl)));
1971         EXPECT_EQ(FooBazVal2, BarBazVal2);
1972       });
1973 }
1974 
1975 TEST(TransferTest, CopyConstructor) {
1976   std::string Code = R"(
1977     struct A {
1978       int Baz;
1979     };
1980 
1981     void target() {
1982       A Foo;
1983       (void)Foo.Baz;
1984       A Bar = Foo;
1985       // [[p]]
1986     }
1987   )";
1988   runDataflow(
1989       Code,
1990       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1991          ASTContext &ASTCtx) {
1992         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1993         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1994 
1995         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1996         ASSERT_THAT(FooDecl, NotNull());
1997 
1998         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1999         ASSERT_THAT(BarDecl, NotNull());
2000 
2001         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2002         ASSERT_THAT(BazDecl, NotNull());
2003 
2004         const auto *FooLoc = cast<AggregateStorageLocation>(
2005             Env.getStorageLocation(*FooDecl, SkipPast::None));
2006         const auto *BarLoc = cast<AggregateStorageLocation>(
2007             Env.getStorageLocation(*BarDecl, SkipPast::None));
2008 
2009         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
2010         const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc));
2011         EXPECT_EQ(FooVal, BarVal);
2012 
2013         const auto *FooBazVal =
2014             cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl)));
2015         const auto *BarBazVal =
2016             cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl)));
2017         EXPECT_EQ(FooBazVal, BarBazVal);
2018       });
2019 }
2020 
2021 TEST(TransferTest, CopyConstructorWithParens) {
2022   std::string Code = R"(
2023     struct A {
2024       int Baz;
2025     };
2026 
2027     void target() {
2028       A Foo;
2029       (void)Foo.Baz;
2030       A Bar((A(Foo)));
2031       // [[p]]
2032     }
2033   )";
2034   runDataflow(
2035       Code,
2036       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2037          ASTContext &ASTCtx) {
2038         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2039         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2040 
2041         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2042         ASSERT_THAT(FooDecl, NotNull());
2043 
2044         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2045         ASSERT_THAT(BarDecl, NotNull());
2046 
2047         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2048         ASSERT_THAT(BazDecl, NotNull());
2049 
2050         const auto *FooLoc = cast<AggregateStorageLocation>(
2051             Env.getStorageLocation(*FooDecl, SkipPast::None));
2052         const auto *BarLoc = cast<AggregateStorageLocation>(
2053             Env.getStorageLocation(*BarDecl, SkipPast::None));
2054 
2055         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
2056         const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc));
2057         EXPECT_EQ(FooVal, BarVal);
2058 
2059         const auto *FooBazVal =
2060             cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl)));
2061         const auto *BarBazVal =
2062             cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl)));
2063         EXPECT_EQ(FooBazVal, BarBazVal);
2064       });
2065 }
2066 
2067 TEST(TransferTest, MoveConstructor) {
2068   std::string Code = R"(
2069     namespace std {
2070 
2071     template <typename T> struct remove_reference      { using type = T; };
2072     template <typename T> struct remove_reference<T&>  { using type = T; };
2073     template <typename T> struct remove_reference<T&&> { using type = T; };
2074 
2075     template <typename T>
2076     using remove_reference_t = typename remove_reference<T>::type;
2077 
2078     template <typename T>
2079     std::remove_reference_t<T>&& move(T&& x);
2080 
2081     } // namespace std
2082 
2083     struct A {
2084       int Baz;
2085     };
2086 
2087     void target() {
2088       A Foo;
2089       A Bar;
2090       (void)Foo.Baz;
2091       // [[p1]]
2092       Foo = std::move(Bar);
2093       // [[p2]]
2094     }
2095   )";
2096   runDataflow(
2097       Code,
2098       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2099          ASTContext &ASTCtx) {
2100         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
2101         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2102         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
2103 
2104         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2105         ASSERT_THAT(FooDecl, NotNull());
2106 
2107         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2108         ASSERT_THAT(BarDecl, NotNull());
2109 
2110         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2111         ASSERT_THAT(BazDecl, NotNull());
2112 
2113         const auto *FooLoc1 = cast<AggregateStorageLocation>(
2114             Env1.getStorageLocation(*FooDecl, SkipPast::None));
2115         const auto *BarLoc1 = cast<AggregateStorageLocation>(
2116             Env1.getStorageLocation(*BarDecl, SkipPast::None));
2117 
2118         const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1));
2119         const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1));
2120         EXPECT_NE(FooVal1, BarVal1);
2121 
2122         const auto *FooBazVal1 =
2123             cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl)));
2124         const auto *BarBazVal1 =
2125             cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl)));
2126         EXPECT_NE(FooBazVal1, BarBazVal1);
2127 
2128         const auto *FooLoc2 = cast<AggregateStorageLocation>(
2129             Env2.getStorageLocation(*FooDecl, SkipPast::None));
2130         const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2));
2131         EXPECT_EQ(FooVal2, BarVal1);
2132 
2133         const auto *FooBazVal2 =
2134             cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl)));
2135         EXPECT_EQ(FooBazVal2, BarBazVal1);
2136       });
2137 }
2138 
2139 TEST(TransferTest, BindTemporary) {
2140   std::string Code = R"(
2141     struct A {
2142       virtual ~A() = default;
2143 
2144       int Baz;
2145     };
2146 
2147     void target(A Foo) {
2148       int Bar = A(Foo).Baz;
2149       // [[p]]
2150     }
2151   )";
2152   runDataflow(
2153       Code,
2154       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2155          ASTContext &ASTCtx) {
2156         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2157         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2158 
2159         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2160         ASSERT_THAT(FooDecl, NotNull());
2161 
2162         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2163         ASSERT_THAT(BarDecl, NotNull());
2164 
2165         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2166         ASSERT_THAT(BazDecl, NotNull());
2167 
2168         const auto &FooVal =
2169             *cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None));
2170         const auto *BarVal =
2171             cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2172         EXPECT_EQ(BarVal, FooVal.getChild(*BazDecl));
2173       });
2174 }
2175 
2176 TEST(TransferTest, StaticCast) {
2177   std::string Code = R"(
2178     void target(int Foo) {
2179       int Bar = static_cast<int>(Foo);
2180       // [[p]]
2181     }
2182   )";
2183   runDataflow(
2184       Code,
2185       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2186          ASTContext &ASTCtx) {
2187         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2188         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2189 
2190         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2191         ASSERT_THAT(FooDecl, NotNull());
2192 
2193         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2194         ASSERT_THAT(BarDecl, NotNull());
2195 
2196         const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2197         const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2198         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2199         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2200         EXPECT_EQ(FooVal, BarVal);
2201       });
2202 }
2203 
2204 TEST(TransferTest, IntegralCast) {
2205   std::string Code = R"(
2206     void target(int Foo) {
2207       long Bar = Foo;
2208       // [[p]]
2209     }
2210   )";
2211   runDataflow(
2212       Code,
2213       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2214          ASTContext &ASTCtx) {
2215         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2216         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2217 
2218         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2219         ASSERT_THAT(FooDecl, NotNull());
2220 
2221         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2222         ASSERT_THAT(BarDecl, NotNull());
2223 
2224         const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2225         const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2226         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2227         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2228         EXPECT_EQ(FooVal, BarVal);
2229       });
2230 }
2231 
2232 TEST(TransferTest, IntegraltoBooleanCast) {
2233   std::string Code = R"(
2234     void target(int Foo) {
2235       bool Bar = Foo;
2236       // [[p]]
2237     }
2238   )";
2239   runDataflow(
2240       Code,
2241       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2242          ASTContext &ASTCtx) {
2243         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2244         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2245 
2246         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2247         ASSERT_THAT(FooDecl, NotNull());
2248 
2249         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2250         ASSERT_THAT(BarDecl, NotNull());
2251 
2252         const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2253         const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2254         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2255         EXPECT_TRUE(isa<BoolValue>(BarVal));
2256       });
2257 }
2258 
2259 TEST(TransferTest, IntegralToBooleanCastFromBool) {
2260   std::string Code = R"(
2261     void target(bool Foo) {
2262       int Zab = Foo;
2263       bool Bar = Zab;
2264       // [[p]]
2265     }
2266   )";
2267   runDataflow(
2268       Code,
2269       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2270          ASTContext &ASTCtx) {
2271         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2272         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2273 
2274         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2275         ASSERT_THAT(FooDecl, NotNull());
2276 
2277         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2278         ASSERT_THAT(BarDecl, NotNull());
2279 
2280         const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2281         const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2282         EXPECT_TRUE(isa<BoolValue>(FooVal));
2283         EXPECT_TRUE(isa<BoolValue>(BarVal));
2284         EXPECT_EQ(FooVal, BarVal);
2285       });
2286 }
2287 
2288 TEST(TransferTest, NullToPointerCast) {
2289   std::string Code = R"(
2290     using my_nullptr_t = decltype(nullptr);
2291     struct Baz {};
2292     void target() {
2293       int *FooX = nullptr;
2294       int *FooY = nullptr;
2295       bool **Bar = nullptr;
2296       Baz *Baz = nullptr;
2297       my_nullptr_t Null = 0;
2298       // [[p]]
2299     }
2300   )";
2301   runDataflow(
2302       Code,
2303       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2304          ASTContext &ASTCtx) {
2305         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2306         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2307 
2308         const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
2309         ASSERT_THAT(FooXDecl, NotNull());
2310 
2311         const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
2312         ASSERT_THAT(FooYDecl, NotNull());
2313 
2314         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2315         ASSERT_THAT(BarDecl, NotNull());
2316 
2317         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2318         ASSERT_THAT(BazDecl, NotNull());
2319 
2320         const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
2321         ASSERT_THAT(NullDecl, NotNull());
2322 
2323         const auto *FooXVal =
2324             cast<PointerValue>(Env.getValue(*FooXDecl, SkipPast::None));
2325         const auto *FooYVal =
2326             cast<PointerValue>(Env.getValue(*FooYDecl, SkipPast::None));
2327         const auto *BarVal =
2328             cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
2329         const auto *BazVal =
2330             cast<PointerValue>(Env.getValue(*BazDecl, SkipPast::None));
2331         const auto *NullVal =
2332             cast<PointerValue>(Env.getValue(*NullDecl, SkipPast::None));
2333 
2334         EXPECT_EQ(FooXVal, FooYVal);
2335         EXPECT_NE(FooXVal, BarVal);
2336         EXPECT_NE(FooXVal, BazVal);
2337         EXPECT_NE(BarVal, BazVal);
2338 
2339         const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
2340         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
2341         EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
2342 
2343         const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
2344         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
2345         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
2346 
2347         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
2348         EXPECT_TRUE(isa<AggregateStorageLocation>(BazPointeeLoc));
2349         EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull());
2350 
2351         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
2352         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
2353         EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
2354       });
2355 }
2356 
2357 TEST(TransferTest, NullToMemberPointerCast) {
2358   std::string Code = R"(
2359     struct Foo {};
2360     void target(Foo *Foo) {
2361       int Foo::*MemberPointer = nullptr;
2362       // [[p]]
2363     }
2364   )";
2365   runDataflow(
2366       Code,
2367       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2368          ASTContext &ASTCtx) {
2369         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2370         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2371 
2372         const ValueDecl *MemberPointerDecl =
2373             findValueDecl(ASTCtx, "MemberPointer");
2374         ASSERT_THAT(MemberPointerDecl, NotNull());
2375 
2376         const auto *MemberPointerVal = cast<PointerValue>(
2377             Env.getValue(*MemberPointerDecl, SkipPast::None));
2378 
2379         const StorageLocation &MemberLoc = MemberPointerVal->getPointeeLoc();
2380         EXPECT_THAT(Env.getValue(MemberLoc), IsNull());
2381       });
2382 }
2383 
2384 TEST(TransferTest, AddrOfValue) {
2385   std::string Code = R"(
2386     void target() {
2387       int Foo;
2388       int *Bar = &Foo;
2389       // [[p]]
2390     }
2391   )";
2392   runDataflow(
2393       Code,
2394       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2395          ASTContext &ASTCtx) {
2396         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2397         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2398 
2399         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2400         ASSERT_THAT(FooDecl, NotNull());
2401 
2402         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2403         ASSERT_THAT(BarDecl, NotNull());
2404 
2405         const auto *FooLoc = cast<ScalarStorageLocation>(
2406             Env.getStorageLocation(*FooDecl, SkipPast::None));
2407         const auto *BarVal =
2408             cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
2409         EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
2410       });
2411 }
2412 
2413 TEST(TransferTest, AddrOfReference) {
2414   std::string Code = R"(
2415     void target(int *Foo) {
2416       int *Bar = &(*Foo);
2417       // [[p]]
2418     }
2419   )";
2420   runDataflow(
2421       Code,
2422       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2423          ASTContext &ASTCtx) {
2424         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2425         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2426 
2427         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2428         ASSERT_THAT(FooDecl, NotNull());
2429 
2430         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2431         ASSERT_THAT(BarDecl, NotNull());
2432 
2433         const auto *FooVal =
2434             cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2435         const auto *BarVal =
2436             cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
2437         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
2438       });
2439 }
2440 
2441 TEST(TransferTest, DerefDependentPtr) {
2442   std::string Code = R"(
2443     template <typename T>
2444     void target(T *Foo) {
2445       T &Bar = *Foo;
2446       /*[[p]]*/
2447     }
2448   )";
2449   runDataflow(
2450       Code,
2451       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2452          ASTContext &ASTCtx) {
2453         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2454         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2455 
2456         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2457         ASSERT_THAT(FooDecl, NotNull());
2458 
2459         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2460         ASSERT_THAT(BarDecl, NotNull());
2461 
2462         const auto *FooVal =
2463             cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2464         const auto *BarVal =
2465             cast<ReferenceValue>(Env.getValue(*BarDecl, SkipPast::None));
2466         EXPECT_EQ(&BarVal->getReferentLoc(), &FooVal->getPointeeLoc());
2467       });
2468 }
2469 
2470 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
2471   std::string Code = R"(
2472     struct A {};
2473 
2474     void target(A Foo, A Bar, bool Cond) {
2475       A Baz = Cond ?  Foo : Bar;
2476       /*[[p]]*/
2477     }
2478   )";
2479   runDataflow(
2480       Code,
2481       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2482          ASTContext &ASTCtx) {
2483         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2484         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2485 
2486         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2487         ASSERT_THAT(FooDecl, NotNull());
2488 
2489         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2490         ASSERT_THAT(BarDecl, NotNull());
2491 
2492         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2493         ASSERT_THAT(BazDecl, NotNull());
2494 
2495         const auto *FooVal =
2496             cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None));
2497         const auto *BarVal =
2498             cast<StructValue>(Env.getValue(*BarDecl, SkipPast::None));
2499 
2500         const auto *BazVal =
2501             dyn_cast<StructValue>(Env.getValue(*BazDecl, SkipPast::None));
2502         ASSERT_THAT(BazVal, NotNull());
2503 
2504         EXPECT_NE(BazVal, FooVal);
2505         EXPECT_NE(BazVal, BarVal);
2506       });
2507 }
2508 
2509 TEST(TransferTest, VarDeclInDoWhile) {
2510   std::string Code = R"(
2511     void target(int *Foo) {
2512       do {
2513         int Bar = *Foo;
2514       } while (true);
2515       (void)0;
2516       /*[[p]]*/
2517     }
2518   )";
2519   runDataflow(
2520       Code,
2521       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2522          ASTContext &ASTCtx) {
2523         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2524         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2525 
2526         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2527         ASSERT_THAT(FooDecl, NotNull());
2528 
2529         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2530         ASSERT_THAT(BarDecl, NotNull());
2531 
2532         const auto *FooVal =
2533             cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2534         const auto *FooPointeeVal =
2535             cast<IntegerValue>(Env.getValue(FooVal->getPointeeLoc()));
2536 
2537         const auto *BarVal = dyn_cast_or_null<IntegerValue>(
2538             Env.getValue(*BarDecl, SkipPast::None));
2539         ASSERT_THAT(BarVal, NotNull());
2540 
2541         EXPECT_EQ(BarVal, FooPointeeVal);
2542       });
2543 }
2544 
2545 TEST(TransferTest, AggregateInitialization) {
2546   std::string BracesCode = R"(
2547     struct A {
2548       int Foo;
2549     };
2550 
2551     struct B {
2552       int Bar;
2553       A Baz;
2554       int Qux;
2555     };
2556 
2557     void target(int BarArg, int FooArg, int QuxArg) {
2558       B Quux{BarArg, {FooArg}, QuxArg};
2559       /*[[p]]*/
2560     }
2561   )";
2562   std::string BraceEllisionCode = R"(
2563     struct A {
2564       int Foo;
2565     };
2566 
2567     struct B {
2568       int Bar;
2569       A Baz;
2570       int Qux;
2571     };
2572 
2573     void target(int BarArg, int FooArg, int QuxArg) {
2574       B Quux = {BarArg, FooArg, QuxArg};
2575       /*[[p]]*/
2576     }
2577   )";
2578   for (const std::string &Code : {BracesCode, BraceEllisionCode}) {
2579     runDataflow(
2580         Code,
2581         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2582            ASTContext &ASTCtx) {
2583           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2584           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2585 
2586           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2587           ASSERT_THAT(FooDecl, NotNull());
2588 
2589           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2590           ASSERT_THAT(BarDecl, NotNull());
2591 
2592           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2593           ASSERT_THAT(BazDecl, NotNull());
2594 
2595           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2596           ASSERT_THAT(QuxDecl, NotNull());
2597 
2598           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
2599           ASSERT_THAT(FooArgDecl, NotNull());
2600 
2601           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
2602           ASSERT_THAT(BarArgDecl, NotNull());
2603 
2604           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
2605           ASSERT_THAT(QuxArgDecl, NotNull());
2606 
2607           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
2608           ASSERT_THAT(QuuxDecl, NotNull());
2609 
2610           const auto *FooArgVal =
2611               cast<IntegerValue>(Env.getValue(*FooArgDecl, SkipPast::None));
2612           const auto *BarArgVal =
2613               cast<IntegerValue>(Env.getValue(*BarArgDecl, SkipPast::None));
2614           const auto *QuxArgVal =
2615               cast<IntegerValue>(Env.getValue(*QuxArgDecl, SkipPast::None));
2616 
2617           const auto *QuuxVal =
2618               cast<StructValue>(Env.getValue(*QuuxDecl, SkipPast::None));
2619           ASSERT_THAT(QuuxVal, NotNull());
2620 
2621           const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl));
2622           ASSERT_THAT(BazVal, NotNull());
2623 
2624           EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal);
2625           EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal);
2626           EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal);
2627         });
2628   }
2629 }
2630 
2631 TEST(TransferTest, AssignToUnionMember) {
2632   std::string Code = R"(
2633     union A {
2634       int Foo;
2635     };
2636 
2637     void target(int Bar) {
2638       A Baz;
2639       Baz.Foo = Bar;
2640       // [[p]]
2641     }
2642   )";
2643   runDataflow(
2644       Code,
2645       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2646          ASTContext &ASTCtx) {
2647         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2648         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2649 
2650         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2651         ASSERT_THAT(BazDecl, NotNull());
2652         ASSERT_TRUE(BazDecl->getType()->isUnionType());
2653 
2654         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
2655         FieldDecl *FooDecl = nullptr;
2656         for (FieldDecl *Field : BazFields) {
2657           if (Field->getNameAsString() == "Foo") {
2658             FooDecl = Field;
2659           } else {
2660             FAIL() << "Unexpected field: " << Field->getNameAsString();
2661           }
2662         }
2663         ASSERT_THAT(FooDecl, NotNull());
2664 
2665         const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>(
2666             Env.getStorageLocation(*BazDecl, SkipPast::None));
2667         ASSERT_THAT(BazLoc, NotNull());
2668         ASSERT_THAT(Env.getValue(*BazLoc), NotNull());
2669 
2670         const auto *BazVal = cast<StructValue>(Env.getValue(*BazLoc));
2671         const auto *FooValFromBazVal = cast<IntegerValue>(BazVal->getChild(*FooDecl));
2672         const auto *FooValFromBazLoc = cast<IntegerValue>(Env.getValue(BazLoc->getChild(*FooDecl)));
2673         EXPECT_EQ(FooValFromBazLoc, FooValFromBazVal);
2674 
2675         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2676         ASSERT_THAT(BarDecl, NotNull());
2677         const auto *BarLoc = Env.getStorageLocation(*BarDecl, SkipPast::None);
2678         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2679 
2680         EXPECT_EQ(Env.getValue(*BarLoc), FooValFromBazVal);
2681         EXPECT_EQ(Env.getValue(*BarLoc), FooValFromBazLoc);
2682       });
2683 }
2684 
2685 TEST(TransferTest, AssignFromBoolLiteral) {
2686   std::string Code = R"(
2687     void target() {
2688       bool Foo = true;
2689       bool Bar = false;
2690       // [[p]]
2691     }
2692   )";
2693   runDataflow(
2694       Code,
2695       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2696          ASTContext &ASTCtx) {
2697         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2698         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2699 
2700         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2701         ASSERT_THAT(FooDecl, NotNull());
2702 
2703         const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>(
2704             Env.getValue(*FooDecl, SkipPast::None));
2705         ASSERT_THAT(FooVal, NotNull());
2706 
2707         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2708         ASSERT_THAT(BarDecl, NotNull());
2709 
2710         const auto *BarVal = dyn_cast_or_null<AtomicBoolValue>(
2711             Env.getValue(*BarDecl, SkipPast::None));
2712         ASSERT_THAT(BarVal, NotNull());
2713 
2714         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
2715         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
2716       });
2717 }
2718 
2719 TEST(TransferTest, AssignFromCompositeBoolExpression) {
2720   {
2721     std::string Code = R"(
2722     void target(bool Foo, bool Bar, bool Qux) {
2723       bool Baz = (Foo) && (Bar || Qux);
2724       // [[p]]
2725     }
2726   )";
2727     runDataflow(
2728         Code,
2729         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2730            ASTContext &ASTCtx) {
2731           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2732           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2733 
2734           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2735           ASSERT_THAT(FooDecl, NotNull());
2736 
2737           const auto *FooVal = dyn_cast_or_null<BoolValue>(
2738               Env.getValue(*FooDecl, SkipPast::None));
2739           ASSERT_THAT(FooVal, NotNull());
2740 
2741           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2742           ASSERT_THAT(BarDecl, NotNull());
2743 
2744           const auto *BarVal = dyn_cast_or_null<BoolValue>(
2745               Env.getValue(*BarDecl, SkipPast::None));
2746           ASSERT_THAT(BarVal, NotNull());
2747 
2748           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2749           ASSERT_THAT(QuxDecl, NotNull());
2750 
2751           const auto *QuxVal = dyn_cast_or_null<BoolValue>(
2752               Env.getValue(*QuxDecl, SkipPast::None));
2753           ASSERT_THAT(QuxVal, NotNull());
2754 
2755           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2756           ASSERT_THAT(BazDecl, NotNull());
2757 
2758           const auto *BazVal = dyn_cast_or_null<ConjunctionValue>(
2759               Env.getValue(*BazDecl, SkipPast::None));
2760           ASSERT_THAT(BazVal, NotNull());
2761           EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
2762 
2763           const auto *BazRightSubValVal =
2764               cast<DisjunctionValue>(&BazVal->getRightSubValue());
2765           EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal);
2766           EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal);
2767         });
2768   }
2769 
2770   {
2771     std::string Code = R"(
2772     void target(bool Foo, bool Bar, bool Qux) {
2773       bool Baz = (Foo && Qux) || (Bar);
2774       // [[p]]
2775     }
2776   )";
2777     runDataflow(
2778         Code,
2779         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2780            ASTContext &ASTCtx) {
2781           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2782           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2783 
2784           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2785           ASSERT_THAT(FooDecl, NotNull());
2786 
2787           const auto *FooVal = dyn_cast_or_null<BoolValue>(
2788               Env.getValue(*FooDecl, SkipPast::None));
2789           ASSERT_THAT(FooVal, NotNull());
2790 
2791           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2792           ASSERT_THAT(BarDecl, NotNull());
2793 
2794           const auto *BarVal = dyn_cast_or_null<BoolValue>(
2795               Env.getValue(*BarDecl, SkipPast::None));
2796           ASSERT_THAT(BarVal, NotNull());
2797 
2798           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2799           ASSERT_THAT(QuxDecl, NotNull());
2800 
2801           const auto *QuxVal = dyn_cast_or_null<BoolValue>(
2802               Env.getValue(*QuxDecl, SkipPast::None));
2803           ASSERT_THAT(QuxVal, NotNull());
2804 
2805           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2806           ASSERT_THAT(BazDecl, NotNull());
2807 
2808           const auto *BazVal = dyn_cast_or_null<DisjunctionValue>(
2809               Env.getValue(*BazDecl, SkipPast::None));
2810           ASSERT_THAT(BazVal, NotNull());
2811 
2812           const auto *BazLeftSubValVal =
2813               cast<ConjunctionValue>(&BazVal->getLeftSubValue());
2814           EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal);
2815           EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal);
2816 
2817           EXPECT_EQ(&BazVal->getRightSubValue(), BarVal);
2818         });
2819   }
2820 
2821   {
2822     std::string Code = R"(
2823       void target(bool A, bool B, bool C, bool D) {
2824         bool Foo = ((A && B) && C) && D;
2825         // [[p]]
2826       }
2827     )";
2828     runDataflow(
2829         Code,
2830         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2831            ASTContext &ASTCtx) {
2832           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2833           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2834 
2835           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
2836           ASSERT_THAT(ADecl, NotNull());
2837 
2838           const auto *AVal =
2839               dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl, SkipPast::None));
2840           ASSERT_THAT(AVal, NotNull());
2841 
2842           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
2843           ASSERT_THAT(BDecl, NotNull());
2844 
2845           const auto *BVal =
2846               dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl, SkipPast::None));
2847           ASSERT_THAT(BVal, NotNull());
2848 
2849           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
2850           ASSERT_THAT(CDecl, NotNull());
2851 
2852           const auto *CVal =
2853               dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
2854           ASSERT_THAT(CVal, NotNull());
2855 
2856           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
2857           ASSERT_THAT(DDecl, NotNull());
2858 
2859           const auto *DVal =
2860               dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl, SkipPast::None));
2861           ASSERT_THAT(DVal, NotNull());
2862 
2863           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2864           ASSERT_THAT(FooDecl, NotNull());
2865 
2866           const auto *FooVal = dyn_cast_or_null<ConjunctionValue>(
2867               Env.getValue(*FooDecl, SkipPast::None));
2868           ASSERT_THAT(FooVal, NotNull());
2869 
2870           const auto &FooLeftSubVal =
2871               cast<ConjunctionValue>(FooVal->getLeftSubValue());
2872           const auto &FooLeftLeftSubVal =
2873               cast<ConjunctionValue>(FooLeftSubVal.getLeftSubValue());
2874           EXPECT_EQ(&FooLeftLeftSubVal.getLeftSubValue(), AVal);
2875           EXPECT_EQ(&FooLeftLeftSubVal.getRightSubValue(), BVal);
2876           EXPECT_EQ(&FooLeftSubVal.getRightSubValue(), CVal);
2877           EXPECT_EQ(&FooVal->getRightSubValue(), DVal);
2878         });
2879   }
2880 }
2881 
2882 TEST(TransferTest, AssignFromBoolNegation) {
2883   std::string Code = R"(
2884     void target() {
2885       bool Foo = true;
2886       bool Bar = !(Foo);
2887       // [[p]]
2888     }
2889   )";
2890   runDataflow(
2891       Code,
2892       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2893          ASTContext &ASTCtx) {
2894         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2895         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2896 
2897         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2898         ASSERT_THAT(FooDecl, NotNull());
2899 
2900         const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>(
2901             Env.getValue(*FooDecl, SkipPast::None));
2902         ASSERT_THAT(FooVal, NotNull());
2903 
2904         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2905         ASSERT_THAT(BarDecl, NotNull());
2906 
2907         const auto *BarVal = dyn_cast_or_null<NegationValue>(
2908             Env.getValue(*BarDecl, SkipPast::None));
2909         ASSERT_THAT(BarVal, NotNull());
2910 
2911         EXPECT_EQ(&BarVal->getSubVal(), FooVal);
2912       });
2913 }
2914 
2915 TEST(TransferTest, BuiltinExpect) {
2916   std::string Code = R"(
2917     void target(long Foo) {
2918       long Bar = __builtin_expect(Foo, true);
2919       /*[[p]]*/
2920     }
2921   )";
2922   runDataflow(
2923       Code,
2924       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2925          ASTContext &ASTCtx) {
2926         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2927         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2928 
2929         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2930         ASSERT_THAT(FooDecl, NotNull());
2931 
2932         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2933         ASSERT_THAT(BarDecl, NotNull());
2934 
2935         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2936                   Env.getValue(*BarDecl, SkipPast::None));
2937       });
2938 }
2939 
2940 // `__builtin_expect` takes and returns a `long` argument, so other types
2941 // involve casts. This verifies that we identify the input and output in that
2942 // case.
2943 TEST(TransferTest, BuiltinExpectBoolArg) {
2944   std::string Code = R"(
2945     void target(bool Foo) {
2946       bool Bar = __builtin_expect(Foo, true);
2947       /*[[p]]*/
2948     }
2949   )";
2950   runDataflow(
2951       Code,
2952       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2953          ASTContext &ASTCtx) {
2954         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2955         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2956 
2957         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2958         ASSERT_THAT(FooDecl, NotNull());
2959 
2960         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2961         ASSERT_THAT(BarDecl, NotNull());
2962 
2963         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2964                   Env.getValue(*BarDecl, SkipPast::None));
2965       });
2966 }
2967 
2968 TEST(TransferTest, BuiltinUnreachable) {
2969   std::string Code = R"(
2970     void target(bool Foo) {
2971       bool Bar = false;
2972       if (Foo)
2973         Bar = Foo;
2974       else
2975         __builtin_unreachable();
2976       (void)0;
2977       /*[[p]]*/
2978     }
2979   )";
2980   runDataflow(
2981       Code,
2982       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2983          ASTContext &ASTCtx) {
2984         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2985         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2986 
2987         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2988         ASSERT_THAT(FooDecl, NotNull());
2989 
2990         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2991         ASSERT_THAT(BarDecl, NotNull());
2992 
2993         // `__builtin_unreachable` promises that the code is
2994         // unreachable, so the compiler treats the "then" branch as the
2995         // only possible predecessor of this statement.
2996         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2997                   Env.getValue(*BarDecl, SkipPast::None));
2998       });
2999 }
3000 
3001 TEST(TransferTest, BuiltinTrap) {
3002   std::string Code = R"(
3003     void target(bool Foo) {
3004       bool Bar = false;
3005       if (Foo)
3006         Bar = Foo;
3007       else
3008         __builtin_trap();
3009       (void)0;
3010       /*[[p]]*/
3011     }
3012   )";
3013   runDataflow(
3014       Code,
3015       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3016          ASTContext &ASTCtx) {
3017         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3018         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3019 
3020         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3021         ASSERT_THAT(FooDecl, NotNull());
3022 
3023         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3024         ASSERT_THAT(BarDecl, NotNull());
3025 
3026         // `__builtin_trap` ensures program termination, so only the
3027         // "then" branch is a predecessor of this statement.
3028         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
3029                   Env.getValue(*BarDecl, SkipPast::None));
3030       });
3031 }
3032 
3033 TEST(TransferTest, BuiltinDebugTrap) {
3034   std::string Code = R"(
3035     void target(bool Foo) {
3036       bool Bar = false;
3037       if (Foo)
3038         Bar = Foo;
3039       else
3040         __builtin_debugtrap();
3041       (void)0;
3042       /*[[p]]*/
3043     }
3044   )";
3045   runDataflow(
3046       Code,
3047       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3048          ASTContext &ASTCtx) {
3049         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3050         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3051 
3052         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3053         ASSERT_THAT(FooDecl, NotNull());
3054 
3055         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3056         ASSERT_THAT(BarDecl, NotNull());
3057 
3058         // `__builtin_debugtrap` doesn't ensure program termination.
3059         EXPECT_NE(Env.getValue(*FooDecl, SkipPast::None),
3060                   Env.getValue(*BarDecl, SkipPast::None));
3061       });
3062 }
3063 
3064 TEST(TransferTest, StaticIntSingleVarDecl) {
3065   std::string Code = R"(
3066     void target() {
3067       static int Foo;
3068       // [[p]]
3069     }
3070   )";
3071   runDataflow(
3072       Code,
3073       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3074          ASTContext &ASTCtx) {
3075         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3076         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3077 
3078         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3079         ASSERT_THAT(FooDecl, NotNull());
3080 
3081         const StorageLocation *FooLoc =
3082             Env.getStorageLocation(*FooDecl, SkipPast::None);
3083         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3084 
3085         const Value *FooVal = Env.getValue(*FooLoc);
3086         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3087       });
3088 }
3089 
3090 TEST(TransferTest, StaticIntGroupVarDecl) {
3091   std::string Code = R"(
3092     void target() {
3093       static int Foo, Bar;
3094       (void)0;
3095       // [[p]]
3096     }
3097   )";
3098   runDataflow(
3099       Code,
3100       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3101          ASTContext &ASTCtx) {
3102         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3103         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3104 
3105         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3106         ASSERT_THAT(FooDecl, NotNull());
3107 
3108         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3109         ASSERT_THAT(BarDecl, NotNull());
3110 
3111         const StorageLocation *FooLoc =
3112             Env.getStorageLocation(*FooDecl, SkipPast::None);
3113         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3114 
3115         const StorageLocation *BarLoc =
3116             Env.getStorageLocation(*BarDecl, SkipPast::None);
3117         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3118 
3119         const Value *FooVal = Env.getValue(*FooLoc);
3120         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3121 
3122         const Value *BarVal = Env.getValue(*BarLoc);
3123         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
3124 
3125         EXPECT_NE(FooVal, BarVal);
3126       });
3127 }
3128 
3129 TEST(TransferTest, GlobalIntVarDecl) {
3130   std::string Code = R"(
3131     static int Foo;
3132 
3133     void target() {
3134       int Bar = Foo;
3135       int Baz = Foo;
3136       // [[p]]
3137     }
3138   )";
3139   runDataflow(
3140       Code,
3141       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3142          ASTContext &ASTCtx) {
3143         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3144         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3145 
3146         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3147         ASSERT_THAT(BarDecl, NotNull());
3148 
3149         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3150         ASSERT_THAT(BazDecl, NotNull());
3151 
3152         const Value *BarVal =
3153             cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3154         const Value *BazVal =
3155             cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
3156         EXPECT_EQ(BarVal, BazVal);
3157       });
3158 }
3159 
3160 TEST(TransferTest, StaticMemberIntVarDecl) {
3161   std::string Code = R"(
3162     struct A {
3163       static int Foo;
3164     };
3165 
3166     void target(A a) {
3167       int Bar = a.Foo;
3168       int Baz = a.Foo;
3169       // [[p]]
3170     }
3171   )";
3172   runDataflow(
3173       Code,
3174       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3175          ASTContext &ASTCtx) {
3176         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3177         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3178 
3179         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3180         ASSERT_THAT(BarDecl, NotNull());
3181 
3182         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3183         ASSERT_THAT(BazDecl, NotNull());
3184 
3185         const Value *BarVal =
3186             cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3187         const Value *BazVal =
3188             cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
3189         EXPECT_EQ(BarVal, BazVal);
3190       });
3191 }
3192 
3193 TEST(TransferTest, StaticMemberRefVarDecl) {
3194   std::string Code = R"(
3195     struct A {
3196       static int &Foo;
3197     };
3198 
3199     void target(A a) {
3200       int Bar = a.Foo;
3201       int Baz = a.Foo;
3202       // [[p]]
3203     }
3204   )";
3205   runDataflow(
3206       Code,
3207       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3208          ASTContext &ASTCtx) {
3209         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3210         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3211 
3212         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3213         ASSERT_THAT(BarDecl, NotNull());
3214 
3215         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3216         ASSERT_THAT(BazDecl, NotNull());
3217 
3218         const Value *BarVal =
3219             cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3220         const Value *BazVal =
3221             cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
3222         EXPECT_EQ(BarVal, BazVal);
3223       });
3224 }
3225 
3226 TEST(TransferTest, AssignMemberBeforeCopy) {
3227   std::string Code = R"(
3228     struct A {
3229       int Foo;
3230     };
3231 
3232     void target() {
3233       A A1;
3234       A A2;
3235       int Bar;
3236       A1.Foo = Bar;
3237       A2 = A1;
3238       // [[p]]
3239     }
3240   )";
3241   runDataflow(
3242       Code,
3243       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3244          ASTContext &ASTCtx) {
3245         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3246         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3247 
3248         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3249         ASSERT_THAT(FooDecl, NotNull());
3250 
3251         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3252         ASSERT_THAT(BarDecl, NotNull());
3253 
3254         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
3255         ASSERT_THAT(A1Decl, NotNull());
3256 
3257         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
3258         ASSERT_THAT(A2Decl, NotNull());
3259 
3260         const auto *BarVal =
3261             cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3262 
3263         const auto *A2Val =
3264             cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None));
3265         EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal);
3266       });
3267 }
3268 
3269 TEST(TransferTest, BooleanEquality) {
3270   std::string Code = R"(
3271     void target(bool Bar) {
3272       bool Foo = true;
3273       if (Bar == Foo) {
3274         (void)0;
3275         /*[[p-then]]*/
3276       } else {
3277         (void)0;
3278         /*[[p-else]]*/
3279       }
3280     }
3281   )";
3282   runDataflow(
3283       Code,
3284       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3285          ASTContext &ASTCtx) {
3286         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3287         const Environment &EnvThen =
3288             getEnvironmentAtAnnotation(Results, "p-then");
3289         const Environment &EnvElse =
3290             getEnvironmentAtAnnotation(Results, "p-else");
3291 
3292         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3293         ASSERT_THAT(BarDecl, NotNull());
3294 
3295         auto &BarValThen =
3296             *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None));
3297         EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen));
3298 
3299         auto &BarValElse =
3300             *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None));
3301         EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse));
3302       });
3303 }
3304 
3305 TEST(TransferTest, BooleanInequality) {
3306   std::string Code = R"(
3307     void target(bool Bar) {
3308       bool Foo = true;
3309       if (Bar != Foo) {
3310         (void)0;
3311         /*[[p-then]]*/
3312       } else {
3313         (void)0;
3314         /*[[p-else]]*/
3315       }
3316     }
3317   )";
3318   runDataflow(
3319       Code,
3320       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3321          ASTContext &ASTCtx) {
3322         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3323         const Environment &EnvThen =
3324             getEnvironmentAtAnnotation(Results, "p-then");
3325         const Environment &EnvElse =
3326             getEnvironmentAtAnnotation(Results, "p-else");
3327 
3328         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3329         ASSERT_THAT(BarDecl, NotNull());
3330 
3331         auto &BarValThen =
3332             *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None));
3333         EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen));
3334 
3335         auto &BarValElse =
3336             *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None));
3337         EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse));
3338       });
3339 }
3340 
3341 TEST(TransferTest, CorrelatedBranches) {
3342   std::string Code = R"(
3343     void target(bool B, bool C) {
3344       if (B) {
3345         return;
3346       }
3347       (void)0;
3348       /*[[p0]]*/
3349       if (C) {
3350         B = true;
3351         /*[[p1]]*/
3352       }
3353       if (B) {
3354         (void)0;
3355         /*[[p2]]*/
3356       }
3357     }
3358   )";
3359   runDataflow(
3360       Code,
3361       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3362          ASTContext &ASTCtx) {
3363         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
3364 
3365         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3366         ASSERT_THAT(CDecl, NotNull());
3367 
3368         {
3369           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
3370           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3371           ASSERT_THAT(BDecl, NotNull());
3372           auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl, SkipPast::None));
3373 
3374           EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal)));
3375         }
3376 
3377         {
3378           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
3379           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
3380           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3381         }
3382 
3383         {
3384           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
3385           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
3386           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3387         }
3388       });
3389 }
3390 
3391 TEST(TransferTest, LoopWithAssignmentConverges) {
3392   std::string Code = R"(
3393     bool foo();
3394 
3395     void target() {
3396        do {
3397         bool Bar = foo();
3398         if (Bar) break;
3399         (void)Bar;
3400         /*[[p]]*/
3401       } while (true);
3402     }
3403   )";
3404   // The key property that we are verifying is implicit in `runDataflow` --
3405   // namely, that the analysis succeeds, rather than hitting the maximum number
3406   // of iterations.
3407   runDataflow(
3408       Code,
3409       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3410          ASTContext &ASTCtx) {
3411         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3412         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3413 
3414         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3415         ASSERT_THAT(BarDecl, NotNull());
3416 
3417         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
3418         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3419       });
3420 }
3421 
3422 TEST(TransferTest, LoopWithStagedAssignments) {
3423   std::string Code = R"(
3424     bool foo();
3425 
3426     void target() {
3427       bool Bar = false;
3428       bool Err = false;
3429       while (foo()) {
3430         if (Bar)
3431           Err = true;
3432         Bar = true;
3433         /*[[p]]*/
3434       }
3435     }
3436   )";
3437   runDataflow(
3438       Code,
3439       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3440          ASTContext &ASTCtx) {
3441         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3442         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3443 
3444         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3445         ASSERT_THAT(BarDecl, NotNull());
3446         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
3447         ASSERT_THAT(ErrDecl, NotNull());
3448 
3449         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
3450         auto &ErrVal = *cast<BoolValue>(Env.getValue(*ErrDecl, SkipPast::None));
3451         EXPECT_TRUE(Env.flowConditionImplies(BarVal));
3452         // An unsound analysis, for example only evaluating the loop once, can
3453         // conclude that `Err` is false. So, we test that this conclusion is not
3454         // reached.
3455         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(ErrVal)));
3456       });
3457 }
3458 
3459 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
3460   std::string Code = R"(
3461     bool &foo();
3462 
3463     void target() {
3464        do {
3465         bool& Bar = foo();
3466         if (Bar) break;
3467         (void)Bar;
3468         /*[[p]]*/
3469       } while (true);
3470     }
3471   )";
3472   // The key property that we are verifying is that the analysis succeeds,
3473   // rather than hitting the maximum number of iterations.
3474   runDataflow(
3475       Code,
3476       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3477          ASTContext &ASTCtx) {
3478         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3479         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3480 
3481         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3482         ASSERT_THAT(BarDecl, NotNull());
3483 
3484         auto &BarVal =
3485             *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::Reference));
3486         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3487       });
3488 }
3489 
3490 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
3491   std::string Code = R"(
3492     struct Lookup {
3493       int x;
3494     };
3495 
3496     void target(Lookup val, bool b) {
3497       const Lookup* l = nullptr;
3498       while (b) {
3499         l = &val;
3500         /*[[p-inner]]*/
3501       }
3502       (void)0;
3503       /*[[p-outer]]*/
3504     }
3505   )";
3506   // The key property that we are verifying is implicit in `runDataflow` --
3507   // namely, that the analysis succeeds, rather than hitting the maximum number
3508   // of iterations.
3509   runDataflow(
3510       Code,
3511       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3512          ASTContext &ASTCtx) {
3513         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
3514         const Environment &InnerEnv =
3515             getEnvironmentAtAnnotation(Results, "p-inner");
3516         const Environment &OuterEnv =
3517             getEnvironmentAtAnnotation(Results, "p-outer");
3518 
3519         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
3520         ASSERT_THAT(ValDecl, NotNull());
3521 
3522         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
3523         ASSERT_THAT(LDecl, NotNull());
3524 
3525         // Inner.
3526         auto *LVal =
3527             dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl, SkipPast::None));
3528         ASSERT_THAT(LVal, NotNull());
3529 
3530         EXPECT_EQ(&LVal->getPointeeLoc(),
3531                   InnerEnv.getStorageLocation(*ValDecl, SkipPast::Reference));
3532 
3533         // Outer.
3534         LVal =
3535             dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl, SkipPast::None));
3536         ASSERT_THAT(LVal, NotNull());
3537 
3538         // The loop body may not have been executed, so we should not conclude
3539         // that `l` points to `val`.
3540         EXPECT_NE(&LVal->getPointeeLoc(),
3541                   OuterEnv.getStorageLocation(*ValDecl, SkipPast::Reference));
3542       });
3543 }
3544 
3545 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
3546   std::string Code = R"(
3547     union Union {
3548       int A;
3549       float B;
3550     };
3551 
3552     void foo() {
3553       Union A;
3554       Union B;
3555       A = B;
3556     }
3557   )";
3558   // This is a crash regression test when calling the transfer function on a
3559   // `CXXThisExpr` that refers to a union.
3560   runDataflow(
3561       Code,
3562       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
3563          ASTContext &) {},
3564       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
3565 }
3566 
3567 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
3568   std::string Code = R"(
3569     struct A {
3570       int Foo;
3571       int Bar;
3572     };
3573 
3574     void target() {
3575       int Qux;
3576       A Baz;
3577       Baz.Foo = Qux;
3578       auto &FooRef = Baz.Foo;
3579       auto &BarRef = Baz.Bar;
3580       auto &[BoundFooRef, BoundBarRef] = Baz;
3581       // [[p]]
3582     }
3583   )";
3584   runDataflow(
3585       Code,
3586       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3587          ASTContext &ASTCtx) {
3588         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3589         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3590 
3591         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3592         ASSERT_THAT(FooRefDecl, NotNull());
3593 
3594         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3595         ASSERT_THAT(BarRefDecl, NotNull());
3596 
3597         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3598         ASSERT_THAT(QuxDecl, NotNull());
3599 
3600         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3601         ASSERT_THAT(BoundFooRefDecl, NotNull());
3602 
3603         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3604         ASSERT_THAT(BoundBarRefDecl, NotNull());
3605 
3606         const StorageLocation *FooRefLoc =
3607             Env.getStorageLocation(*FooRefDecl, SkipPast::Reference);
3608         ASSERT_THAT(FooRefLoc, NotNull());
3609 
3610         const StorageLocation *BarRefLoc =
3611             Env.getStorageLocation(*BarRefDecl, SkipPast::Reference);
3612         ASSERT_THAT(BarRefLoc, NotNull());
3613 
3614         const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None);
3615         ASSERT_THAT(QuxVal, NotNull());
3616 
3617         const StorageLocation *BoundFooRefLoc =
3618             Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference);
3619         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3620 
3621         const StorageLocation *BoundBarRefLoc =
3622             Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference);
3623         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3624 
3625         EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal);
3626       });
3627 }
3628 
3629 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
3630   std::string Code = R"(
3631     struct A {
3632       int &Foo;
3633       int &Bar;
3634     };
3635 
3636     void target(A Baz) {
3637       int Qux;
3638       Baz.Foo = Qux;
3639       auto &FooRef = Baz.Foo;
3640       auto &BarRef = Baz.Bar;
3641       auto &[BoundFooRef, BoundBarRef] = Baz;
3642       // [[p]]
3643     }
3644   )";
3645   runDataflow(
3646       Code,
3647       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3648          ASTContext &ASTCtx) {
3649         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3650         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3651 
3652         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3653         ASSERT_THAT(FooRefDecl, NotNull());
3654 
3655         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3656         ASSERT_THAT(BarRefDecl, NotNull());
3657 
3658         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3659         ASSERT_THAT(QuxDecl, NotNull());
3660 
3661         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3662         ASSERT_THAT(BoundFooRefDecl, NotNull());
3663 
3664         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3665         ASSERT_THAT(BoundBarRefDecl, NotNull());
3666 
3667         const StorageLocation *FooRefLoc =
3668             Env.getStorageLocation(*FooRefDecl, SkipPast::Reference);
3669         ASSERT_THAT(FooRefLoc, NotNull());
3670 
3671         const StorageLocation *BarRefLoc =
3672             Env.getStorageLocation(*BarRefDecl, SkipPast::Reference);
3673         ASSERT_THAT(BarRefLoc, NotNull());
3674 
3675         const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None);
3676         ASSERT_THAT(QuxVal, NotNull());
3677 
3678         const StorageLocation *BoundFooRefLoc =
3679             Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference);
3680         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3681 
3682         const StorageLocation *BoundBarRefLoc =
3683             Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference);
3684         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3685 
3686         EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal);
3687       });
3688 }
3689 
3690 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
3691   std::string Code = R"(
3692     struct A {
3693       int Foo;
3694       int Bar;
3695     };
3696 
3697     void target() {
3698       int Qux;
3699       A Baz;
3700       Baz.Foo = Qux;
3701       auto &FooRef = Baz.Foo;
3702       auto &BarRef = Baz.Bar;
3703       auto [BoundFoo, BoundBar] = Baz;
3704       // [[p]]
3705     }
3706   )";
3707   runDataflow(
3708       Code,
3709       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3710          ASTContext &ASTCtx) {
3711         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3712         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3713 
3714         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3715         ASSERT_THAT(FooRefDecl, NotNull());
3716 
3717         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3718         ASSERT_THAT(BarRefDecl, NotNull());
3719 
3720         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
3721         ASSERT_THAT(BoundFooDecl, NotNull());
3722 
3723         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
3724         ASSERT_THAT(BoundBarDecl, NotNull());
3725 
3726         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3727         ASSERT_THAT(QuxDecl, NotNull());
3728 
3729         const StorageLocation *FooRefLoc =
3730             Env.getStorageLocation(*FooRefDecl, SkipPast::Reference);
3731         ASSERT_THAT(FooRefLoc, NotNull());
3732 
3733         const StorageLocation *BarRefLoc =
3734             Env.getStorageLocation(*BarRefDecl, SkipPast::Reference);
3735         ASSERT_THAT(BarRefLoc, NotNull());
3736 
3737         const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None);
3738         ASSERT_THAT(QuxVal, NotNull());
3739 
3740         const StorageLocation *BoundFooLoc =
3741             Env.getStorageLocation(*BoundFooDecl, SkipPast::Reference);
3742         EXPECT_NE(BoundFooLoc, FooRefLoc);
3743 
3744         const StorageLocation *BoundBarLoc =
3745             Env.getStorageLocation(*BoundBarDecl, SkipPast::Reference);
3746         EXPECT_NE(BoundBarLoc, BarRefLoc);
3747 
3748         EXPECT_EQ(Env.getValue(*BoundFooDecl, SkipPast::Reference), QuxVal);
3749       });
3750 }
3751 
3752 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
3753   std::string Code = R"(
3754     namespace std {
3755     using size_t = int;
3756     template <class> struct tuple_size;
3757     template <std::size_t, class> struct tuple_element;
3758     template <class...> class tuple;
3759 
3760     namespace {
3761     template <class T, T v>
3762     struct size_helper { static const T value = v; };
3763     } // namespace
3764 
3765     template <class... T>
3766     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
3767 
3768     template <std::size_t I, class... T>
3769     struct tuple_element<I, tuple<T...>> {
3770       using type =  __type_pack_element<I, T...>;
3771     };
3772 
3773     template <class...> class tuple {};
3774 
3775     template <std::size_t I, class... T>
3776     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
3777     } // namespace std
3778 
3779     std::tuple<bool, int> makeTuple();
3780 
3781     void target(bool B) {
3782       auto [BoundFoo, BoundBar] = makeTuple();
3783       bool Baz;
3784       // Include if-then-else to test interaction of `BindingDecl` with join.
3785       if (B) {
3786         Baz = BoundFoo;
3787         (void)BoundBar;
3788         // [[p1]]
3789       } else {
3790         Baz = BoundFoo;
3791       }
3792       (void)0;
3793       // [[p2]]
3794     }
3795   )";
3796   runDataflow(
3797       Code,
3798       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3799          ASTContext &ASTCtx) {
3800         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
3801         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
3802 
3803         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
3804         ASSERT_THAT(BoundFooDecl, NotNull());
3805 
3806         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
3807         ASSERT_THAT(BoundBarDecl, NotNull());
3808 
3809         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3810         ASSERT_THAT(BazDecl, NotNull());
3811 
3812         const Value *BoundFooValue =
3813             Env1.getValue(*BoundFooDecl, SkipPast::Reference);
3814         ASSERT_THAT(BoundFooValue, NotNull());
3815         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
3816 
3817         const Value *BoundBarValue =
3818             Env1.getValue(*BoundBarDecl, SkipPast::Reference);
3819         ASSERT_THAT(BoundBarValue, NotNull());
3820         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
3821 
3822         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
3823         EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), BoundFooValue);
3824 
3825         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
3826 
3827         // Test that `BoundFooDecl` retains the value we expect, after the join.
3828         BoundFooValue = Env2.getValue(*BoundFooDecl, SkipPast::Reference);
3829         EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BoundFooValue);
3830       });
3831 }
3832 
3833 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
3834   std::string Code = R"(
3835     namespace std {
3836     using size_t = int;
3837     template <class> struct tuple_size;
3838     template <std::size_t, class> struct tuple_element;
3839     template <class...> class tuple;
3840 
3841     namespace {
3842     template <class T, T v>
3843     struct size_helper { static const T value = v; };
3844     } // namespace
3845 
3846     template <class... T>
3847     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
3848 
3849     template <std::size_t I, class... T>
3850     struct tuple_element<I, tuple<T...>> {
3851       using type =  __type_pack_element<I, T...>;
3852     };
3853 
3854     template <class...> class tuple {};
3855 
3856     template <std::size_t I, class... T>
3857     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
3858     } // namespace std
3859 
3860     std::tuple<bool, int> &getTuple();
3861 
3862     void target(bool B) {
3863       auto &[BoundFoo, BoundBar] = getTuple();
3864       bool Baz;
3865       // Include if-then-else to test interaction of `BindingDecl` with join.
3866       if (B) {
3867         Baz = BoundFoo;
3868         (void)BoundBar;
3869         // [[p1]]
3870       } else {
3871         Baz = BoundFoo;
3872       }
3873       (void)0;
3874       // [[p2]]
3875     }
3876   )";
3877   runDataflow(
3878       Code,
3879       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3880          ASTContext &ASTCtx) {
3881         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
3882         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
3883 
3884         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
3885         ASSERT_THAT(BoundFooDecl, NotNull());
3886 
3887         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
3888         ASSERT_THAT(BoundBarDecl, NotNull());
3889 
3890         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3891         ASSERT_THAT(BazDecl, NotNull());
3892 
3893         const Value *BoundFooValue =
3894             Env1.getValue(*BoundFooDecl, SkipPast::Reference);
3895         ASSERT_THAT(BoundFooValue, NotNull());
3896         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
3897 
3898         const Value *BoundBarValue =
3899             Env1.getValue(*BoundBarDecl, SkipPast::Reference);
3900         ASSERT_THAT(BoundBarValue, NotNull());
3901         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
3902 
3903         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
3904         // works as expected. We don't test aliasing properties of the
3905         // reference, because we don't model `std::get` and so have no way to
3906         // equate separate references into the tuple.
3907         EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), BoundFooValue);
3908 
3909         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
3910 
3911         // Test that `BoundFooDecl` retains the value we expect, after the join.
3912         BoundFooValue = Env2.getValue(*BoundFooDecl, SkipPast::Reference);
3913         EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BoundFooValue);
3914       });
3915 }
3916 // TODO: ref binding
3917 
3918 TEST(TransferTest, BinaryOperatorComma) {
3919   std::string Code = R"(
3920     void target(int Foo, int Bar) {
3921       int &Baz = (Foo, Bar);
3922       // [[p]]
3923     }
3924   )";
3925   runDataflow(
3926       Code,
3927       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3928          ASTContext &ASTCtx) {
3929         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3930         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3931 
3932         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3933         ASSERT_THAT(BarDecl, NotNull());
3934 
3935         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3936         ASSERT_THAT(BazDecl, NotNull());
3937 
3938         const StorageLocation *BarLoc =
3939             Env.getStorageLocation(*BarDecl, SkipPast::Reference);
3940         ASSERT_THAT(BarLoc, NotNull());
3941 
3942         const StorageLocation *BazLoc =
3943             Env.getStorageLocation(*BazDecl, SkipPast::Reference);
3944         EXPECT_EQ(BazLoc, BarLoc);
3945       });
3946 }
3947 
3948 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
3949   std::string Code = R"(
3950     void target(bool Foo) {
3951       if (Foo) {
3952         (void)0;
3953         // [[if_then]]
3954       } else {
3955         (void)0;
3956         // [[if_else]]
3957       }
3958     }
3959   )";
3960   runDataflow(
3961       Code,
3962       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3963          ASTContext &ASTCtx) {
3964         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
3965         const Environment &ThenEnv =
3966             getEnvironmentAtAnnotation(Results, "if_then");
3967         const Environment &ElseEnv =
3968             getEnvironmentAtAnnotation(Results, "if_else");
3969 
3970         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3971         ASSERT_THAT(FooDecl, NotNull());
3972 
3973         BoolValue &ThenFooVal =
3974             *cast<BoolValue>(ThenEnv.getValue(*FooDecl, SkipPast::None));
3975         EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal));
3976 
3977         BoolValue &ElseFooVal =
3978             *cast<BoolValue>(ElseEnv.getValue(*FooDecl, SkipPast::None));
3979         EXPECT_TRUE(ElseEnv.flowConditionImplies(ElseEnv.makeNot(ElseFooVal)));
3980       });
3981 }
3982 
3983 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
3984   std::string Code = R"(
3985     void target(bool Foo) {
3986       while (Foo) {
3987         (void)0;
3988         // [[loop_body]]
3989       }
3990       (void)0;
3991       // [[after_loop]]
3992     }
3993   )";
3994   runDataflow(
3995       Code,
3996       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3997          ASTContext &ASTCtx) {
3998         ASSERT_THAT(Results.keys(),
3999                     UnorderedElementsAre("loop_body", "after_loop"));
4000         const Environment &LoopBodyEnv =
4001             getEnvironmentAtAnnotation(Results, "loop_body");
4002         const Environment &AfterLoopEnv =
4003             getEnvironmentAtAnnotation(Results, "after_loop");
4004 
4005         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4006         ASSERT_THAT(FooDecl, NotNull());
4007 
4008         BoolValue &LoopBodyFooVal =
4009             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
4010         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4011 
4012         BoolValue &AfterLoopFooVal =
4013             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
4014         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4015             AfterLoopEnv.makeNot(AfterLoopFooVal)));
4016       });
4017 }
4018 
4019 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
4020   std::string Code = R"(
4021     void target(bool Foo) {
4022       bool Bar = true;
4023       do {
4024         (void)0;
4025         // [[loop_body]]
4026         Bar = false;
4027       } while (Foo);
4028       (void)0;
4029       // [[after_loop]]
4030     }
4031   )";
4032   runDataflow(
4033       Code,
4034       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4035          ASTContext &ASTCtx) {
4036         ASSERT_THAT(Results.keys(),
4037                     UnorderedElementsAre("loop_body", "after_loop"));
4038         const Environment &LoopBodyEnv =
4039             getEnvironmentAtAnnotation(Results, "loop_body");
4040         const Environment &AfterLoopEnv =
4041             getEnvironmentAtAnnotation(Results, "after_loop");
4042 
4043         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4044         ASSERT_THAT(FooDecl, NotNull());
4045 
4046         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4047         ASSERT_THAT(BarDecl, NotNull());
4048 
4049         BoolValue &LoopBodyFooVal =
4050             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
4051         BoolValue &LoopBodyBarVal =
4052             *cast<BoolValue>(LoopBodyEnv.getValue(*BarDecl, SkipPast::None));
4053         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(
4054             LoopBodyEnv.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
4055 
4056         BoolValue &AfterLoopFooVal =
4057             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
4058         BoolValue &AfterLoopBarVal =
4059             *cast<BoolValue>(AfterLoopEnv.getValue(*BarDecl, SkipPast::None));
4060         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4061             AfterLoopEnv.makeNot(AfterLoopFooVal)));
4062         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4063             AfterLoopEnv.makeNot(AfterLoopBarVal)));
4064       });
4065 }
4066 
4067 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
4068   std::string Code = R"(
4069     void target(bool Foo) {
4070       for (; Foo;) {
4071         (void)0;
4072         // [[loop_body]]
4073       }
4074       (void)0;
4075       // [[after_loop]]
4076     }
4077   )";
4078   runDataflow(
4079       Code,
4080       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4081          ASTContext &ASTCtx) {
4082         ASSERT_THAT(Results.keys(),
4083                     UnorderedElementsAre("loop_body", "after_loop"));
4084         const Environment &LoopBodyEnv =
4085             getEnvironmentAtAnnotation(Results, "loop_body");
4086         const Environment &AfterLoopEnv =
4087             getEnvironmentAtAnnotation(Results, "after_loop");
4088 
4089         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4090         ASSERT_THAT(FooDecl, NotNull());
4091 
4092         BoolValue &LoopBodyFooVal =
4093             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
4094         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4095 
4096         BoolValue &AfterLoopFooVal =
4097             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
4098         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4099             AfterLoopEnv.makeNot(AfterLoopFooVal)));
4100       });
4101 }
4102 
4103 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
4104   std::string Code = R"(
4105     void target(bool Foo) {
4106       for (;;) {
4107         (void)0;
4108         // [[loop_body]]
4109       }
4110     }
4111   )";
4112   runDataflow(
4113       Code,
4114       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4115          ASTContext &ASTCtx) {
4116         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
4117         const Environment &LoopBodyEnv =
4118             getEnvironmentAtAnnotation(Results, "loop_body");
4119 
4120         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4121         ASSERT_THAT(FooDecl, NotNull());
4122 
4123         BoolValue &LoopBodyFooVal =
4124             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
4125         EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4126       });
4127 }
4128 
4129 TEST(TransferTest, ContextSensitiveOptionDisabled) {
4130   std::string Code = R"(
4131     bool GiveBool();
4132     void SetBool(bool &Var) { Var = true; }
4133 
4134     void target() {
4135       bool Foo = GiveBool();
4136       SetBool(Foo);
4137       // [[p]]
4138     }
4139   )";
4140   runDataflow(
4141       Code,
4142       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4143          ASTContext &ASTCtx) {
4144         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4145         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4146 
4147         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4148         ASSERT_THAT(FooDecl, NotNull());
4149 
4150         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4151         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4152         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4153       },
4154       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
4155 }
4156 
4157 // This test is a regression test, based on a real crash.
4158 TEST(TransferTest, ContextSensitiveReturnReferenceFromNonReferenceLvalue) {
4159   // This code exercises an unusual code path. If we return an lvalue directly,
4160   // the code will catch that it's an l-value based on the `Value`'s kind. If we
4161   // pass through a dummy function, the framework won't populate a value at
4162   // all. In contrast, this code results in a (fresh) value, but it is not
4163   // `ReferenceValue`. This test verifies that we catch this case as well.
4164   std::string Code = R"(
4165     class S {};
4166     S& target(bool b, S &s) {
4167       return b ? s : s;
4168       // [[p]]
4169     }
4170   )";
4171   runDataflow(
4172       Code,
4173       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4174          ASTContext &ASTCtx) {
4175         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4176         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4177 
4178         auto *Loc = Env.getReturnStorageLocation();
4179         ASSERT_THAT(Loc, NotNull());
4180 
4181         EXPECT_THAT(Env.getValue(*Loc), IsNull());
4182       },
4183       {BuiltinOptions{ContextSensitiveOptions{}}});
4184 }
4185 
4186 TEST(TransferTest, ContextSensitiveDepthZero) {
4187   std::string Code = R"(
4188     bool GiveBool();
4189     void SetBool(bool &Var) { Var = true; }
4190 
4191     void target() {
4192       bool Foo = GiveBool();
4193       SetBool(Foo);
4194       // [[p]]
4195     }
4196   )";
4197   runDataflow(
4198       Code,
4199       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4200          ASTContext &ASTCtx) {
4201         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4202         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4203 
4204         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4205         ASSERT_THAT(FooDecl, NotNull());
4206 
4207         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4208         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4209         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4210       },
4211       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
4212 }
4213 
4214 TEST(TransferTest, ContextSensitiveSetTrue) {
4215   std::string Code = R"(
4216     bool GiveBool();
4217     void SetBool(bool &Var) { Var = true; }
4218 
4219     void target() {
4220       bool Foo = GiveBool();
4221       SetBool(Foo);
4222       // [[p]]
4223     }
4224   )";
4225   runDataflow(
4226       Code,
4227       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4228          ASTContext &ASTCtx) {
4229         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4230         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4231 
4232         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4233         ASSERT_THAT(FooDecl, NotNull());
4234 
4235         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4236         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4237       },
4238       {BuiltinOptions{ContextSensitiveOptions{}}});
4239 }
4240 
4241 TEST(TransferTest, ContextSensitiveSetFalse) {
4242   std::string Code = R"(
4243     bool GiveBool();
4244     void SetBool(bool &Var) { Var = false; }
4245 
4246     void target() {
4247       bool Foo = GiveBool();
4248       SetBool(Foo);
4249       // [[p]]
4250     }
4251   )";
4252   runDataflow(
4253       Code,
4254       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4255          ASTContext &ASTCtx) {
4256         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4257         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4258 
4259         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4260         ASSERT_THAT(FooDecl, NotNull());
4261 
4262         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4263         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4264       },
4265       {BuiltinOptions{ContextSensitiveOptions{}}});
4266 }
4267 
4268 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
4269   std::string Code = R"(
4270     bool GiveBool();
4271     void SetBool(bool &Var, bool Val) { Var = Val; }
4272 
4273     void target() {
4274       bool Foo = GiveBool();
4275       bool Bar = GiveBool();
4276       SetBool(Foo, true);
4277       SetBool(Bar, false);
4278       // [[p]]
4279     }
4280   )";
4281   runDataflow(
4282       Code,
4283       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4284          ASTContext &ASTCtx) {
4285         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4286         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4287 
4288         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4289         ASSERT_THAT(FooDecl, NotNull());
4290 
4291         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4292         ASSERT_THAT(BarDecl, NotNull());
4293 
4294         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4295         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4296         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4297 
4298         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
4299         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4300         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4301       },
4302       {BuiltinOptions{ContextSensitiveOptions{}}});
4303 }
4304 
4305 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
4306   std::string Code = R"(
4307     bool GiveBool();
4308     void SetBool1(bool &Var) { Var = true; }
4309     void SetBool2(bool &Var) { SetBool1(Var); }
4310 
4311     void target() {
4312       bool Foo = GiveBool();
4313       SetBool2(Foo);
4314       // [[p]]
4315     }
4316   )";
4317   runDataflow(
4318       Code,
4319       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4320          ASTContext &ASTCtx) {
4321         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4322         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4323 
4324         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4325         ASSERT_THAT(FooDecl, NotNull());
4326 
4327         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4328         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4329         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4330       },
4331       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
4332 }
4333 
4334 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
4335   std::string Code = R"(
4336     bool GiveBool();
4337     void SetBool1(bool &Var) { Var = true; }
4338     void SetBool2(bool &Var) { SetBool1(Var); }
4339 
4340     void target() {
4341       bool Foo = GiveBool();
4342       SetBool2(Foo);
4343       // [[p]]
4344     }
4345   )";
4346   runDataflow(
4347       Code,
4348       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4349          ASTContext &ASTCtx) {
4350         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4351         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4352 
4353         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4354         ASSERT_THAT(FooDecl, NotNull());
4355 
4356         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4357         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4358       },
4359       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4360 }
4361 
4362 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
4363   std::string Code = R"(
4364     bool GiveBool();
4365     void SetBool1(bool &Var) { Var = true; }
4366     void SetBool2(bool &Var) { SetBool1(Var); }
4367     void SetBool3(bool &Var) { SetBool2(Var); }
4368 
4369     void target() {
4370       bool Foo = GiveBool();
4371       SetBool3(Foo);
4372       // [[p]]
4373     }
4374   )";
4375   runDataflow(
4376       Code,
4377       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4378          ASTContext &ASTCtx) {
4379         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4380         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4381 
4382         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4383         ASSERT_THAT(FooDecl, NotNull());
4384 
4385         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4386         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4387         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4388       },
4389       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4390 }
4391 
4392 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
4393   std::string Code = R"(
4394     bool GiveBool();
4395     void SetBool1(bool &Var) { Var = true; }
4396     void SetBool2(bool &Var) { SetBool1(Var); }
4397     void SetBool3(bool &Var) { SetBool2(Var); }
4398 
4399     void target() {
4400       bool Foo = GiveBool();
4401       SetBool3(Foo);
4402       // [[p]]
4403     }
4404   )";
4405   runDataflow(
4406       Code,
4407       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4408          ASTContext &ASTCtx) {
4409         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4410         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4411 
4412         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4413         ASSERT_THAT(FooDecl, NotNull());
4414 
4415         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4416         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4417       },
4418       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
4419 }
4420 
4421 TEST(TransferTest, ContextSensitiveMutualRecursion) {
4422   std::string Code = R"(
4423     bool Pong(bool X, bool Y);
4424 
4425     bool Ping(bool X, bool Y) {
4426       if (X) {
4427         return Y;
4428       } else {
4429         return Pong(!X, Y);
4430       }
4431     }
4432 
4433     bool Pong(bool X, bool Y) {
4434       if (Y) {
4435         return X;
4436       } else {
4437         return Ping(X, !Y);
4438       }
4439     }
4440 
4441     void target() {
4442       bool Foo = Ping(false, false);
4443       // [[p]]
4444     }
4445   )";
4446   runDataflow(
4447       Code,
4448       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4449          ASTContext &ASTCtx) {
4450         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4451         // The analysis doesn't crash...
4452         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4453 
4454         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4455         ASSERT_THAT(FooDecl, NotNull());
4456 
4457         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4458         // ... but it also can't prove anything here.
4459         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4460         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4461       },
4462       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
4463 }
4464 
4465 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
4466   std::string Code = R"(
4467     void SetBools(bool &Var1, bool &Var2) {
4468       Var1 = true;
4469       Var2 = false;
4470     }
4471 
4472     void target() {
4473       bool Foo = false;
4474       bool Bar = true;
4475       SetBools(Foo, Bar);
4476       // [[p]]
4477     }
4478   )";
4479   runDataflow(
4480       Code,
4481       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4482          ASTContext &ASTCtx) {
4483         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4484         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4485 
4486         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4487         ASSERT_THAT(FooDecl, NotNull());
4488 
4489         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4490         ASSERT_THAT(BarDecl, NotNull());
4491 
4492         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4493         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4494         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4495 
4496         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
4497         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4498         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4499       },
4500       {BuiltinOptions{ContextSensitiveOptions{}}});
4501 }
4502 
4503 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
4504   std::string Code = R"(
4505     void IfCond(bool Cond, bool &Then, bool &Else) {
4506       if (Cond) {
4507         Then = true;
4508       } else {
4509         Else = true;
4510       }
4511     }
4512 
4513     void target() {
4514       bool Foo = false;
4515       bool Bar = false;
4516       bool Baz = false;
4517       IfCond(Foo, Bar, Baz);
4518       // [[p]]
4519     }
4520   )";
4521   runDataflow(
4522       Code,
4523       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4524          ASTContext &ASTCtx) {
4525         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4526         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4527 
4528         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4529         ASSERT_THAT(BarDecl, NotNull());
4530 
4531         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4532         ASSERT_THAT(BazDecl, NotNull());
4533 
4534         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
4535         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4536         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4537 
4538         auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl, SkipPast::None));
4539         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
4540         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(BazVal)));
4541       },
4542       {BuiltinOptions{ContextSensitiveOptions{}}});
4543 }
4544 
4545 TEST(TransferTest, ContextSensitiveReturnVoid) {
4546   std::string Code = R"(
4547     void Noop() { return; }
4548 
4549     void target() {
4550       Noop();
4551       // [[p]]
4552     }
4553   )";
4554   runDataflow(
4555       Code,
4556       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4557          ASTContext &ASTCtx) {
4558         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4559         // This just tests that the analysis doesn't crash.
4560       },
4561       {BuiltinOptions{ContextSensitiveOptions{}}});
4562 }
4563 
4564 TEST(TransferTest, ContextSensitiveReturnTrue) {
4565   std::string Code = R"(
4566     bool GiveBool() { return true; }
4567 
4568     void target() {
4569       bool Foo = GiveBool();
4570       // [[p]]
4571     }
4572   )";
4573   runDataflow(
4574       Code,
4575       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4576          ASTContext &ASTCtx) {
4577         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4578         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4579 
4580         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4581         ASSERT_THAT(FooDecl, NotNull());
4582 
4583         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4584         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4585       },
4586       {BuiltinOptions{ContextSensitiveOptions{}}});
4587 }
4588 
4589 TEST(TransferTest, ContextSensitiveReturnFalse) {
4590   std::string Code = R"(
4591     bool GiveBool() { return false; }
4592 
4593     void target() {
4594       bool Foo = GiveBool();
4595       // [[p]]
4596     }
4597   )";
4598   runDataflow(
4599       Code,
4600       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4601          ASTContext &ASTCtx) {
4602         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4603         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4604 
4605         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4606         ASSERT_THAT(FooDecl, NotNull());
4607 
4608         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4609         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4610       },
4611       {BuiltinOptions{ContextSensitiveOptions{}}});
4612 }
4613 
4614 TEST(TransferTest, ContextSensitiveReturnArg) {
4615   std::string Code = R"(
4616     bool GiveBool();
4617     bool GiveBack(bool Arg) { return Arg; }
4618 
4619     void target() {
4620       bool Foo = GiveBool();
4621       bool Bar = GiveBack(Foo);
4622       bool Baz = Foo == Bar;
4623       // [[p]]
4624     }
4625   )";
4626   runDataflow(
4627       Code,
4628       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4629          ASTContext &ASTCtx) {
4630         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4631         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4632 
4633         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4634         ASSERT_THAT(BazDecl, NotNull());
4635 
4636         auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl, SkipPast::None));
4637         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
4638       },
4639       {BuiltinOptions{ContextSensitiveOptions{}}});
4640 }
4641 
4642 TEST(TransferTest, ContextSensitiveReturnInt) {
4643   std::string Code = R"(
4644     int identity(int x) { return x; }
4645 
4646     void target() {
4647       int y = identity(42);
4648       // [[p]]
4649     }
4650   )";
4651   runDataflow(
4652       Code,
4653       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4654          ASTContext &ASTCtx) {
4655         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4656         // This just tests that the analysis doesn't crash.
4657       },
4658       {BuiltinOptions{ContextSensitiveOptions{}}});
4659 }
4660 
4661 TEST(TransferTest, ContextSensitiveMethodLiteral) {
4662   std::string Code = R"(
4663     class MyClass {
4664     public:
4665       bool giveBool() { return true; }
4666     };
4667 
4668     void target() {
4669       MyClass MyObj;
4670       bool Foo = MyObj.giveBool();
4671       // [[p]]
4672     }
4673   )";
4674   runDataflow(
4675       Code,
4676       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4677          ASTContext &ASTCtx) {
4678         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4679         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4680 
4681         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4682         ASSERT_THAT(FooDecl, NotNull());
4683 
4684         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4685         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4686       },
4687       {BuiltinOptions{ContextSensitiveOptions{}}});
4688 }
4689 
4690 TEST(TransferTest, ContextSensitiveMethodGetter) {
4691   std::string Code = R"(
4692     class MyClass {
4693     public:
4694       bool getField() { return Field; }
4695 
4696       bool Field;
4697     };
4698 
4699     void target() {
4700       MyClass MyObj;
4701       MyObj.Field = true;
4702       bool Foo = MyObj.getField();
4703       // [[p]]
4704     }
4705   )";
4706   runDataflow(
4707       Code,
4708       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4709          ASTContext &ASTCtx) {
4710         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4711         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4712 
4713         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4714         ASSERT_THAT(FooDecl, NotNull());
4715 
4716         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4717         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4718       },
4719       {BuiltinOptions{ContextSensitiveOptions{}}});
4720 }
4721 
4722 TEST(TransferTest, ContextSensitiveMethodSetter) {
4723   std::string Code = R"(
4724     class MyClass {
4725     public:
4726       void setField(bool Val) { Field = Val; }
4727 
4728       bool Field;
4729     };
4730 
4731     void target() {
4732       MyClass MyObj;
4733       MyObj.setField(true);
4734       bool Foo = MyObj.Field;
4735       // [[p]]
4736     }
4737   )";
4738   runDataflow(
4739       Code,
4740       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4741          ASTContext &ASTCtx) {
4742         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4743         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4744 
4745         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4746         ASSERT_THAT(FooDecl, NotNull());
4747 
4748         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4749         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4750       },
4751       {BuiltinOptions{ContextSensitiveOptions{}}});
4752 }
4753 
4754 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
4755   std::string Code = R"(
4756     class MyClass {
4757     public:
4758       bool getField() { return Field; }
4759       void setField(bool Val) { Field = Val; }
4760 
4761     private:
4762       bool Field;
4763     };
4764 
4765     void target() {
4766       MyClass MyObj;
4767       MyObj.setField(true);
4768       bool Foo = MyObj.getField();
4769       // [[p]]
4770     }
4771   )";
4772   runDataflow(
4773       Code,
4774       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4775          ASTContext &ASTCtx) {
4776         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4777         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4778 
4779         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4780         ASSERT_THAT(FooDecl, NotNull());
4781 
4782         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4783         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4784       },
4785       {BuiltinOptions{ContextSensitiveOptions{}}});
4786 }
4787 
4788 
4789 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
4790   std::string Code = R"(
4791     class MyClass {
4792     public:
4793       void Inner() { MyField = true; }
4794       void Outer() { Inner(); }
4795 
4796       bool MyField;
4797     };
4798 
4799     void target() {
4800       MyClass MyObj;
4801       MyObj.Outer();
4802       bool Foo = MyObj.MyField;
4803       // [[p]]
4804     }
4805   )";
4806   runDataflow(
4807       Code,
4808       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4809          ASTContext &ASTCtx) {
4810         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4811         ;
4812         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4813 
4814         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4815         ASSERT_THAT(FooDecl, NotNull());
4816 
4817         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4818         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4819       },
4820       {BuiltinOptions{ContextSensitiveOptions{}}});
4821 }
4822 
4823 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
4824   std::string Code = R"(
4825     class MyClass {
4826     public:
4827       bool Inner() { return MyField; }
4828       bool Outer() { return Inner(); }
4829 
4830       bool MyField;
4831     };
4832 
4833     void target() {
4834       MyClass MyObj;
4835       MyObj.MyField = true;
4836       bool Foo = MyObj.Outer();
4837       // [[p]]
4838     }
4839   )";
4840   runDataflow(
4841       Code,
4842       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4843          ASTContext &ASTCtx) {
4844         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4845         ;
4846         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4847 
4848         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4849         ASSERT_THAT(FooDecl, NotNull());
4850 
4851         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4852         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4853       },
4854       {BuiltinOptions{ContextSensitiveOptions{}}});
4855 }
4856 
4857 TEST(TransferTest, ContextSensitiveConstructorBody) {
4858   std::string Code = R"(
4859     class MyClass {
4860     public:
4861       MyClass() { MyField = true; }
4862 
4863       bool MyField;
4864     };
4865 
4866     void target() {
4867       MyClass MyObj;
4868       bool Foo = MyObj.MyField;
4869       // [[p]]
4870     }
4871   )";
4872   runDataflow(
4873       Code,
4874       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4875          ASTContext &ASTCtx) {
4876         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4877         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4878 
4879         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4880         ASSERT_THAT(FooDecl, NotNull());
4881 
4882         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4883         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4884       },
4885       {BuiltinOptions{ContextSensitiveOptions{}}});
4886 }
4887 
4888 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
4889   std::string Code = R"(
4890     class MyClass {
4891     public:
4892       MyClass() : MyField(true) {}
4893 
4894       bool MyField;
4895     };
4896 
4897     void target() {
4898       MyClass MyObj;
4899       bool Foo = MyObj.MyField;
4900       // [[p]]
4901     }
4902   )";
4903   runDataflow(
4904       Code,
4905       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4906          ASTContext &ASTCtx) {
4907         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4908         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4909 
4910         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4911         ASSERT_THAT(FooDecl, NotNull());
4912 
4913         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4914         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4915       },
4916       {BuiltinOptions{ContextSensitiveOptions{}}});
4917 }
4918 
4919 TEST(TransferTest, ContextSensitiveConstructorDefault) {
4920   std::string Code = R"(
4921     class MyClass {
4922     public:
4923       MyClass() = default;
4924 
4925       bool MyField = true;
4926     };
4927 
4928     void target() {
4929       MyClass MyObj;
4930       bool Foo = MyObj.MyField;
4931       // [[p]]
4932     }
4933   )";
4934   runDataflow(
4935       Code,
4936       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4937          ASTContext &ASTCtx) {
4938         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4939         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4940 
4941         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4942         ASSERT_THAT(FooDecl, NotNull());
4943 
4944         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4945         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4946       },
4947       {BuiltinOptions{ContextSensitiveOptions{}}});
4948 }
4949 
4950 } // namespace
4951