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