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