xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision eb2131bdbad3f74be2fcf236b4d6921612af47a9)
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 "NoopAnalysis.h"
10 #include "TestingSupport.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/AST/Decl.h"
13 #include "clang/ASTMatchers/ASTMatchFinder.h"
14 #include "clang/ASTMatchers/ASTMatchers.h"
15 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
16 #include "clang/Analysis/FlowSensitive/StorageLocation.h"
17 #include "clang/Analysis/FlowSensitive/Value.h"
18 #include "clang/Basic/LangStandard.h"
19 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/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::_;
34 using ::testing::ElementsAre;
35 using ::testing::IsNull;
36 using ::testing::NotNull;
37 using ::testing::Pair;
38 using ::testing::SizeIs;
39 
40 class TransferTest : public ::testing::Test {
41 protected:
42   template <typename Matcher>
43   void runDataflow(llvm::StringRef Code, Matcher Match,
44                    LangStandard::Kind Std = LangStandard::lang_cxx17,
45                    bool ApplyBuiltinTransfer = true) {
46     ASSERT_THAT_ERROR(
47         test::checkDataflow<NoopAnalysis>(
48             Code, "target",
49             [ApplyBuiltinTransfer](ASTContext &C, Environment &) {
50               return NoopAnalysis(C, ApplyBuiltinTransfer);
51             },
52             [&Match](
53                 llvm::ArrayRef<
54                     std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
55                     Results,
56                 ASTContext &ASTCtx) { Match(Results, ASTCtx); },
57             {"-fsyntax-only", "-fno-delayed-template-parsing",
58              "-std=" +
59                  std::string(
60                      LangStandard::getLangStandardForKind(Std).getName())}),
61         llvm::Succeeded());
62   }
63 };
64 
65 TEST_F(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
66   std::string Code = R"(
67     void target() {
68       int Foo;
69       // [[p]]
70     }
71   )";
72   runDataflow(
73       Code,
74       [](llvm::ArrayRef<
75              std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
76              Results,
77          ASTContext &ASTCtx) {
78         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
79         const Environment &Env = Results[0].second.Env;
80 
81         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
82         ASSERT_THAT(FooDecl, NotNull());
83 
84         EXPECT_EQ(Env.getStorageLocation(*FooDecl, SkipPast::None), nullptr);
85       },
86       LangStandard::lang_cxx17,
87       /*ApplyBuiltinTransfer=*/false);
88 }
89 
90 TEST_F(TransferTest, BoolVarDecl) {
91   std::string Code = R"(
92     void target() {
93       bool Foo;
94       // [[p]]
95     }
96   )";
97   runDataflow(Code,
98               [](llvm::ArrayRef<
99                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
100                      Results,
101                  ASTContext &ASTCtx) {
102                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
103                 const Environment &Env = Results[0].second.Env;
104 
105                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
106                 ASSERT_THAT(FooDecl, NotNull());
107 
108                 const StorageLocation *FooLoc =
109                     Env.getStorageLocation(*FooDecl, SkipPast::None);
110                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
111 
112                 const Value *FooVal = Env.getValue(*FooLoc);
113                 EXPECT_TRUE(isa_and_nonnull<BoolValue>(FooVal));
114               });
115 }
116 
117 TEST_F(TransferTest, IntVarDecl) {
118   std::string Code = R"(
119     void target() {
120       int Foo;
121       // [[p]]
122     }
123   )";
124   runDataflow(
125       Code, [](llvm::ArrayRef<
126                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
127                    Results,
128                ASTContext &ASTCtx) {
129         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
130         const Environment &Env = Results[0].second.Env;
131 
132         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
133         ASSERT_THAT(FooDecl, NotNull());
134 
135         const StorageLocation *FooLoc =
136             Env.getStorageLocation(*FooDecl, SkipPast::None);
137         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
138 
139         const Value *FooVal = Env.getValue(*FooLoc);
140         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
141       });
142 }
143 
144 TEST_F(TransferTest, StructVarDecl) {
145   std::string Code = R"(
146     struct A {
147       int Bar;
148     };
149 
150     void target() {
151       A Foo;
152       // [[p]]
153     }
154   )";
155   runDataflow(
156       Code, [](llvm::ArrayRef<
157                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
158                    Results,
159                ASTContext &ASTCtx) {
160         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
161         const Environment &Env = Results[0].second.Env;
162 
163         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
164         ASSERT_THAT(FooDecl, NotNull());
165 
166         ASSERT_TRUE(FooDecl->getType()->isStructureType());
167         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
168 
169         FieldDecl *BarDecl = nullptr;
170         for (FieldDecl *Field : FooFields) {
171           if (Field->getNameAsString() == "Bar") {
172             BarDecl = Field;
173           } else {
174             FAIL() << "Unexpected field: " << Field->getNameAsString();
175           }
176         }
177         ASSERT_THAT(BarDecl, NotNull());
178 
179         const auto *FooLoc = cast<AggregateStorageLocation>(
180             Env.getStorageLocation(*FooDecl, SkipPast::None));
181         const auto *BarLoc =
182             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
183 
184         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
185         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
186         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
187       });
188 }
189 
190 TEST_F(TransferTest, StructVarDeclWithInit) {
191   std::string Code = R"(
192     struct A {
193       int Bar;
194     };
195 
196     A Gen();
197 
198     void target() {
199       A Foo = Gen();
200       // [[p]]
201     }
202   )";
203   runDataflow(
204       Code, [](llvm::ArrayRef<
205                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
206                    Results,
207                ASTContext &ASTCtx) {
208         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
209         const Environment &Env = Results[0].second.Env;
210 
211         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
212         ASSERT_THAT(FooDecl, NotNull());
213 
214         ASSERT_TRUE(FooDecl->getType()->isStructureType());
215         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
216 
217         FieldDecl *BarDecl = nullptr;
218         for (FieldDecl *Field : FooFields) {
219           if (Field->getNameAsString() == "Bar") {
220             BarDecl = Field;
221           } else {
222             FAIL() << "Unexpected field: " << Field->getNameAsString();
223           }
224         }
225         ASSERT_THAT(BarDecl, NotNull());
226 
227         const auto *FooLoc = cast<AggregateStorageLocation>(
228             Env.getStorageLocation(*FooDecl, SkipPast::None));
229         const auto *BarLoc =
230             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
231 
232         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
233         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
234         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
235       });
236 }
237 
238 TEST_F(TransferTest, ClassVarDecl) {
239   std::string Code = R"(
240     class A {
241       int Bar;
242     };
243 
244     void target() {
245       A Foo;
246       // [[p]]
247     }
248   )";
249   runDataflow(
250       Code, [](llvm::ArrayRef<
251                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
252                    Results,
253                ASTContext &ASTCtx) {
254         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
255         const Environment &Env = Results[0].second.Env;
256 
257         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
258         ASSERT_THAT(FooDecl, NotNull());
259 
260         ASSERT_TRUE(FooDecl->getType()->isClassType());
261         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
262 
263         FieldDecl *BarDecl = nullptr;
264         for (FieldDecl *Field : FooFields) {
265           if (Field->getNameAsString() == "Bar") {
266             BarDecl = Field;
267           } else {
268             FAIL() << "Unexpected field: " << Field->getNameAsString();
269           }
270         }
271         ASSERT_THAT(BarDecl, NotNull());
272 
273         const auto *FooLoc = cast<AggregateStorageLocation>(
274             Env.getStorageLocation(*FooDecl, SkipPast::None));
275         const auto *BarLoc =
276             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
277 
278         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
279         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
280         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
281       });
282 }
283 
284 TEST_F(TransferTest, ReferenceVarDecl) {
285   std::string Code = R"(
286     struct A {};
287 
288     A &getA();
289 
290     void target() {
291       A &Foo = getA();
292       // [[p]]
293     }
294   )";
295   runDataflow(
296       Code, [](llvm::ArrayRef<
297                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
298                    Results,
299                ASTContext &ASTCtx) {
300         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
301         const Environment &Env = Results[0].second.Env;
302 
303         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
304         ASSERT_THAT(FooDecl, NotNull());
305 
306         const StorageLocation *FooLoc =
307             Env.getStorageLocation(*FooDecl, SkipPast::None);
308         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
309 
310         const ReferenceValue *FooVal =
311             cast<ReferenceValue>(Env.getValue(*FooLoc));
312         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
313         EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc));
314 
315         const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
316         EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal));
317       });
318 }
319 
320 TEST_F(TransferTest, SelfReferentialReferenceVarDecl) {
321   std::string Code = R"(
322     struct A;
323 
324     struct B {};
325 
326     struct C {
327       A &FooRef;
328       A *FooPtr;
329       B &BazRef;
330       B *BazPtr;
331     };
332 
333     struct A {
334       C &Bar;
335     };
336 
337     A &getA();
338 
339     void target() {
340       A &Foo = getA();
341       // [[p]]
342     }
343   )";
344   runDataflow(Code, [](llvm::ArrayRef<std::pair<
345                            std::string, DataflowAnalysisState<NoopLattice>>>
346                            Results,
347                        ASTContext &ASTCtx) {
348     ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
349     const Environment &Env = Results[0].second.Env;
350 
351     const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
352     ASSERT_THAT(FooDecl, NotNull());
353 
354     ASSERT_TRUE(FooDecl->getType()->isReferenceType());
355     ASSERT_TRUE(FooDecl->getType().getNonReferenceType()->isStructureType());
356     const auto FooFields =
357         FooDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields();
358 
359     FieldDecl *BarDecl = nullptr;
360     for (FieldDecl *Field : FooFields) {
361       if (Field->getNameAsString() == "Bar") {
362         BarDecl = Field;
363       } else {
364         FAIL() << "Unexpected field: " << Field->getNameAsString();
365       }
366     }
367     ASSERT_THAT(BarDecl, NotNull());
368 
369     ASSERT_TRUE(BarDecl->getType()->isReferenceType());
370     ASSERT_TRUE(BarDecl->getType().getNonReferenceType()->isStructureType());
371     const auto BarFields =
372         BarDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields();
373 
374     FieldDecl *FooRefDecl = nullptr;
375     FieldDecl *FooPtrDecl = nullptr;
376     FieldDecl *BazRefDecl = nullptr;
377     FieldDecl *BazPtrDecl = nullptr;
378     for (FieldDecl *Field : BarFields) {
379       if (Field->getNameAsString() == "FooRef") {
380         FooRefDecl = Field;
381       } else if (Field->getNameAsString() == "FooPtr") {
382         FooPtrDecl = Field;
383       } else if (Field->getNameAsString() == "BazRef") {
384         BazRefDecl = Field;
385       } else if (Field->getNameAsString() == "BazPtr") {
386         BazPtrDecl = Field;
387       } else {
388         FAIL() << "Unexpected field: " << Field->getNameAsString();
389       }
390     }
391     ASSERT_THAT(FooRefDecl, NotNull());
392     ASSERT_THAT(FooPtrDecl, NotNull());
393     ASSERT_THAT(BazRefDecl, NotNull());
394     ASSERT_THAT(BazPtrDecl, NotNull());
395 
396     const auto *FooLoc = cast<ScalarStorageLocation>(
397         Env.getStorageLocation(*FooDecl, SkipPast::None));
398     const auto *FooVal = cast<ReferenceValue>(Env.getValue(*FooLoc));
399     const auto *FooPointeeVal =
400         cast<StructValue>(Env.getValue(FooVal->getPointeeLoc()));
401 
402     const auto *BarVal =
403         cast<ReferenceValue>(FooPointeeVal->getChild(*BarDecl));
404     const auto *BarPointeeVal =
405         cast<StructValue>(Env.getValue(BarVal->getPointeeLoc()));
406 
407     const auto *FooRefVal =
408         cast<ReferenceValue>(BarPointeeVal->getChild(*FooRefDecl));
409     const StorageLocation &FooRefPointeeLoc = FooRefVal->getPointeeLoc();
410     EXPECT_THAT(Env.getValue(FooRefPointeeLoc), IsNull());
411 
412     const auto *FooPtrVal =
413         cast<PointerValue>(BarPointeeVal->getChild(*FooPtrDecl));
414     const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc();
415     EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull());
416 
417     const auto *BazRefVal =
418         cast<ReferenceValue>(BarPointeeVal->getChild(*BazRefDecl));
419     const StorageLocation &BazRefPointeeLoc = BazRefVal->getPointeeLoc();
420     EXPECT_THAT(Env.getValue(BazRefPointeeLoc), NotNull());
421 
422     const auto *BazPtrVal =
423         cast<PointerValue>(BarPointeeVal->getChild(*BazPtrDecl));
424     const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc();
425     EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull());
426   });
427 }
428 
429 TEST_F(TransferTest, PointerVarDecl) {
430   std::string Code = R"(
431     struct A {};
432 
433     A *getA();
434 
435     void target() {
436       A *Foo = getA();
437       // [[p]]
438     }
439   )";
440   runDataflow(
441       Code, [](llvm::ArrayRef<
442                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
443                    Results,
444                ASTContext &ASTCtx) {
445         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
446         const Environment &Env = Results[0].second.Env;
447 
448         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
449         ASSERT_THAT(FooDecl, NotNull());
450 
451         const StorageLocation *FooLoc =
452             Env.getStorageLocation(*FooDecl, SkipPast::None);
453         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
454 
455         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
456         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
457         EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc));
458 
459         const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
460         EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal));
461       });
462 }
463 
464 TEST_F(TransferTest, SelfReferentialPointerVarDecl) {
465   std::string Code = R"(
466     struct A;
467 
468     struct B {};
469 
470     struct C {
471       A &FooRef;
472       A *FooPtr;
473       B &BazRef;
474       B *BazPtr;
475     };
476 
477     struct A {
478       C *Bar;
479     };
480 
481     A *getA();
482 
483     void target() {
484       A *Foo = getA();
485       // [[p]]
486     }
487   )";
488   runDataflow(
489       Code, [](llvm::ArrayRef<
490                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
491                    Results,
492                ASTContext &ASTCtx) {
493         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
494         const Environment &Env = Results[0].second.Env;
495 
496         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
497         ASSERT_THAT(FooDecl, NotNull());
498 
499         ASSERT_TRUE(FooDecl->getType()->isPointerType());
500         ASSERT_TRUE(FooDecl->getType()
501                         ->getAs<PointerType>()
502                         ->getPointeeType()
503                         ->isStructureType());
504         const auto FooFields = FooDecl->getType()
505                                    ->getAs<PointerType>()
506                                    ->getPointeeType()
507                                    ->getAsRecordDecl()
508                                    ->fields();
509 
510         FieldDecl *BarDecl = nullptr;
511         for (FieldDecl *Field : FooFields) {
512           if (Field->getNameAsString() == "Bar") {
513             BarDecl = Field;
514           } else {
515             FAIL() << "Unexpected field: " << Field->getNameAsString();
516           }
517         }
518         ASSERT_THAT(BarDecl, NotNull());
519 
520         ASSERT_TRUE(BarDecl->getType()->isPointerType());
521         ASSERT_TRUE(BarDecl->getType()
522                         ->getAs<PointerType>()
523                         ->getPointeeType()
524                         ->isStructureType());
525         const auto BarFields = BarDecl->getType()
526                                    ->getAs<PointerType>()
527                                    ->getPointeeType()
528                                    ->getAsRecordDecl()
529                                    ->fields();
530 
531         FieldDecl *FooRefDecl = nullptr;
532         FieldDecl *FooPtrDecl = nullptr;
533         FieldDecl *BazRefDecl = nullptr;
534         FieldDecl *BazPtrDecl = nullptr;
535         for (FieldDecl *Field : BarFields) {
536           if (Field->getNameAsString() == "FooRef") {
537             FooRefDecl = Field;
538           } else if (Field->getNameAsString() == "FooPtr") {
539             FooPtrDecl = Field;
540           } else if (Field->getNameAsString() == "BazRef") {
541             BazRefDecl = Field;
542           } else if (Field->getNameAsString() == "BazPtr") {
543             BazPtrDecl = Field;
544           } else {
545             FAIL() << "Unexpected field: " << Field->getNameAsString();
546           }
547         }
548         ASSERT_THAT(FooRefDecl, NotNull());
549         ASSERT_THAT(FooPtrDecl, NotNull());
550         ASSERT_THAT(BazRefDecl, NotNull());
551         ASSERT_THAT(BazPtrDecl, NotNull());
552 
553         const auto *FooLoc = cast<ScalarStorageLocation>(
554             Env.getStorageLocation(*FooDecl, SkipPast::None));
555         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
556         const auto *FooPointeeVal =
557             cast<StructValue>(Env.getValue(FooVal->getPointeeLoc()));
558 
559         const auto *BarVal =
560             cast<PointerValue>(FooPointeeVal->getChild(*BarDecl));
561         const auto *BarPointeeVal =
562             cast<StructValue>(Env.getValue(BarVal->getPointeeLoc()));
563 
564         const auto *FooRefVal =
565             cast<ReferenceValue>(BarPointeeVal->getChild(*FooRefDecl));
566         const StorageLocation &FooRefPointeeLoc = FooRefVal->getPointeeLoc();
567         EXPECT_THAT(Env.getValue(FooRefPointeeLoc), IsNull());
568 
569         const auto *FooPtrVal =
570             cast<PointerValue>(BarPointeeVal->getChild(*FooPtrDecl));
571         const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc();
572         EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull());
573 
574         const auto *BazRefVal =
575             cast<ReferenceValue>(BarPointeeVal->getChild(*BazRefDecl));
576         const StorageLocation &BazRefPointeeLoc = BazRefVal->getPointeeLoc();
577         EXPECT_THAT(Env.getValue(BazRefPointeeLoc), NotNull());
578 
579         const auto *BazPtrVal =
580             cast<PointerValue>(BarPointeeVal->getChild(*BazPtrDecl));
581         const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc();
582         EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull());
583       });
584 }
585 
586 TEST_F(TransferTest, MultipleVarsDecl) {
587   std::string Code = R"(
588     void target() {
589       int Foo, Bar;
590       (void)0;
591       // [[p]]
592     }
593   )";
594   runDataflow(Code,
595               [](llvm::ArrayRef<
596                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
597                      Results,
598                  ASTContext &ASTCtx) {
599                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
600                 const Environment &Env = Results[0].second.Env;
601 
602                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
603                 ASSERT_THAT(FooDecl, NotNull());
604 
605                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
606                 ASSERT_THAT(BarDecl, NotNull());
607 
608                 const StorageLocation *FooLoc =
609                     Env.getStorageLocation(*FooDecl, SkipPast::None);
610                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
611 
612                 const StorageLocation *BarLoc =
613                     Env.getStorageLocation(*BarDecl, SkipPast::None);
614                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
615 
616                 const Value *FooVal = Env.getValue(*FooLoc);
617                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
618 
619                 const Value *BarVal = Env.getValue(*BarLoc);
620                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
621               });
622 }
623 
624 TEST_F(TransferTest, JoinVarDecl) {
625   std::string Code = R"(
626     void target(bool B) {
627       int Foo;
628       // [[p1]]
629       if (B) {
630         int Bar;
631         // [[p2]]
632       } else {
633         int Baz;
634         // [[p3]]
635       }
636       (void)0;
637       // [[p4]]
638     }
639   )";
640   runDataflow(Code, [](llvm::ArrayRef<std::pair<
641                            std::string, DataflowAnalysisState<NoopLattice>>>
642                            Results,
643                        ASTContext &ASTCtx) {
644     ASSERT_THAT(Results, ElementsAre(Pair("p4", _), Pair("p3", _),
645                                      Pair("p2", _), Pair("p1", _)));
646     const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
647     ASSERT_THAT(FooDecl, NotNull());
648 
649     const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
650     ASSERT_THAT(BarDecl, NotNull());
651 
652     const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
653     ASSERT_THAT(BazDecl, NotNull());
654 
655     const Environment &Env1 = Results[3].second.Env;
656     const StorageLocation *FooLoc =
657         Env1.getStorageLocation(*FooDecl, SkipPast::None);
658     EXPECT_THAT(FooLoc, NotNull());
659     EXPECT_THAT(Env1.getStorageLocation(*BarDecl, SkipPast::None), IsNull());
660     EXPECT_THAT(Env1.getStorageLocation(*BazDecl, SkipPast::None), IsNull());
661 
662     const Environment &Env2 = Results[2].second.Env;
663     EXPECT_EQ(Env2.getStorageLocation(*FooDecl, SkipPast::None), FooLoc);
664     EXPECT_THAT(Env2.getStorageLocation(*BarDecl, SkipPast::None), NotNull());
665     EXPECT_THAT(Env2.getStorageLocation(*BazDecl, SkipPast::None), IsNull());
666 
667     const Environment &Env3 = Results[1].second.Env;
668     EXPECT_EQ(Env3.getStorageLocation(*FooDecl, SkipPast::None), FooLoc);
669     EXPECT_THAT(Env3.getStorageLocation(*BarDecl, SkipPast::None), IsNull());
670     EXPECT_THAT(Env3.getStorageLocation(*BazDecl, SkipPast::None), NotNull());
671 
672     const Environment &Env4 = Results[0].second.Env;
673     EXPECT_EQ(Env4.getStorageLocation(*FooDecl, SkipPast::None), FooLoc);
674     EXPECT_THAT(Env4.getStorageLocation(*BarDecl, SkipPast::None), IsNull());
675     EXPECT_THAT(Env4.getStorageLocation(*BazDecl, SkipPast::None), IsNull());
676   });
677 }
678 
679 TEST_F(TransferTest, BinaryOperatorAssign) {
680   std::string Code = R"(
681     void target() {
682       int Foo;
683       int Bar;
684       (Bar) = (Foo);
685       // [[p]]
686     }
687   )";
688   runDataflow(Code,
689               [](llvm::ArrayRef<
690                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
691                      Results,
692                  ASTContext &ASTCtx) {
693                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
694                 const Environment &Env = Results[0].second.Env;
695 
696                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
697                 ASSERT_THAT(FooDecl, NotNull());
698 
699                 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None);
700                 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
701 
702                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
703                 ASSERT_THAT(BarDecl, NotNull());
704 
705                 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal);
706               });
707 }
708 
709 TEST_F(TransferTest, VarDeclInitAssign) {
710   std::string Code = R"(
711     void target() {
712       int Foo;
713       int Bar = Foo;
714       // [[p]]
715     }
716   )";
717   runDataflow(Code,
718               [](llvm::ArrayRef<
719                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
720                      Results,
721                  ASTContext &ASTCtx) {
722                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
723                 const Environment &Env = Results[0].second.Env;
724 
725                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
726                 ASSERT_THAT(FooDecl, NotNull());
727 
728                 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None);
729                 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
730 
731                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
732                 ASSERT_THAT(BarDecl, NotNull());
733 
734                 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal);
735               });
736 }
737 
738 TEST_F(TransferTest, VarDeclInitAssignChained) {
739   std::string Code = R"(
740     void target() {
741       int Foo;
742       int Bar;
743       int Baz = (Bar = Foo);
744       // [[p]]
745     }
746   )";
747   runDataflow(Code,
748               [](llvm::ArrayRef<
749                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
750                      Results,
751                  ASTContext &ASTCtx) {
752                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
753                 const Environment &Env = Results[0].second.Env;
754 
755                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
756                 ASSERT_THAT(FooDecl, NotNull());
757 
758                 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None);
759                 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
760 
761                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
762                 ASSERT_THAT(BarDecl, NotNull());
763 
764                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
765                 ASSERT_THAT(BazDecl, NotNull());
766 
767                 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal);
768                 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), FooVal);
769               });
770 }
771 
772 TEST_F(TransferTest, VarDeclInitAssignPtrDeref) {
773   std::string Code = R"(
774     void target() {
775       int Foo;
776       int *Bar;
777       *(Bar) = Foo;
778       int Baz = *(Bar);
779       // [[p]]
780     }
781   )";
782   runDataflow(Code,
783               [](llvm::ArrayRef<
784                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
785                      Results,
786                  ASTContext &ASTCtx) {
787                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
788                 const Environment &Env = Results[0].second.Env;
789 
790                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
791                 ASSERT_THAT(FooDecl, NotNull());
792 
793                 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None);
794                 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
795 
796                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
797                 ASSERT_THAT(BarDecl, NotNull());
798 
799                 const auto *BarVal =
800                     cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
801                 EXPECT_EQ(Env.getValue(BarVal->getPointeeLoc()), FooVal);
802 
803                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
804                 ASSERT_THAT(BazDecl, NotNull());
805 
806                 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), FooVal);
807               });
808 }
809 
810 TEST_F(TransferTest, AssignToAndFromReference) {
811   std::string Code = R"(
812     void target() {
813       int Foo;
814       int Bar;
815       int &Baz = Foo;
816       // [[p1]]
817       Baz = Bar;
818       int Qux = Baz;
819       int &Quux = Baz;
820       // [[p2]]
821     }
822   )";
823   runDataflow(
824       Code, [](llvm::ArrayRef<
825                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
826                    Results,
827                ASTContext &ASTCtx) {
828         ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
829         const Environment &Env1 = Results[0].second.Env;
830         const Environment &Env2 = Results[1].second.Env;
831 
832         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
833         ASSERT_THAT(FooDecl, NotNull());
834 
835         const Value *FooVal = Env1.getValue(*FooDecl, SkipPast::None);
836         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
837 
838         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
839         ASSERT_THAT(BarDecl, NotNull());
840 
841         const Value *BarVal = Env1.getValue(*BarDecl, SkipPast::None);
842         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
843 
844         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
845         ASSERT_THAT(BazDecl, NotNull());
846 
847         EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), FooVal);
848 
849         EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BarVal);
850         EXPECT_EQ(Env2.getValue(*FooDecl, SkipPast::None), BarVal);
851 
852         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
853         ASSERT_THAT(QuxDecl, NotNull());
854         EXPECT_EQ(Env2.getValue(*QuxDecl, SkipPast::None), BarVal);
855 
856         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
857         ASSERT_THAT(QuuxDecl, NotNull());
858         EXPECT_EQ(Env2.getValue(*QuuxDecl, SkipPast::Reference), BarVal);
859       });
860 }
861 
862 TEST_F(TransferTest, MultipleParamDecls) {
863   std::string Code = R"(
864     void target(int Foo, int Bar) {
865       (void)0;
866       // [[p]]
867     }
868   )";
869   runDataflow(Code,
870               [](llvm::ArrayRef<
871                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
872                      Results,
873                  ASTContext &ASTCtx) {
874                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
875                 const Environment &Env = Results[0].second.Env;
876 
877                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
878                 ASSERT_THAT(FooDecl, NotNull());
879 
880                 const StorageLocation *FooLoc =
881                     Env.getStorageLocation(*FooDecl, SkipPast::None);
882                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
883 
884                 const Value *FooVal = Env.getValue(*FooLoc);
885                 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
886 
887                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
888                 ASSERT_THAT(BarDecl, NotNull());
889 
890                 const StorageLocation *BarLoc =
891                     Env.getStorageLocation(*BarDecl, SkipPast::None);
892                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
893 
894                 const Value *BarVal = Env.getValue(*BarLoc);
895                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
896               });
897 }
898 
899 TEST_F(TransferTest, StructParamDecl) {
900   std::string Code = R"(
901     struct A {
902       int Bar;
903     };
904 
905     void target(A Foo) {
906       (void)0;
907       // [[p]]
908     }
909   )";
910   runDataflow(
911       Code, [](llvm::ArrayRef<
912                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
913                    Results,
914                ASTContext &ASTCtx) {
915         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
916         const Environment &Env = Results[0].second.Env;
917 
918         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
919         ASSERT_THAT(FooDecl, NotNull());
920 
921         ASSERT_TRUE(FooDecl->getType()->isStructureType());
922         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
923 
924         FieldDecl *BarDecl = nullptr;
925         for (FieldDecl *Field : FooFields) {
926           if (Field->getNameAsString() == "Bar") {
927             BarDecl = Field;
928           } else {
929             FAIL() << "Unexpected field: " << Field->getNameAsString();
930           }
931         }
932         ASSERT_THAT(BarDecl, NotNull());
933 
934         const auto *FooLoc = cast<AggregateStorageLocation>(
935             Env.getStorageLocation(*FooDecl, SkipPast::None));
936         const auto *BarLoc =
937             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
938 
939         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
940         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
941         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
942       });
943 }
944 
945 TEST_F(TransferTest, ReferenceParamDecl) {
946   std::string Code = R"(
947     struct A {};
948 
949     void target(A &Foo) {
950       (void)0;
951       // [[p]]
952     }
953   )";
954   runDataflow(Code,
955               [](llvm::ArrayRef<
956                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
957                      Results,
958                  ASTContext &ASTCtx) {
959                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
960                 const Environment &Env = Results[0].second.Env;
961 
962                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
963                 ASSERT_THAT(FooDecl, NotNull());
964 
965                 const StorageLocation *FooLoc =
966                     Env.getStorageLocation(*FooDecl, SkipPast::None);
967                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
968 
969                 const ReferenceValue *FooVal =
970                     dyn_cast<ReferenceValue>(Env.getValue(*FooLoc));
971                 ASSERT_THAT(FooVal, NotNull());
972 
973                 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
974                 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc));
975 
976                 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
977                 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal));
978               });
979 }
980 
981 TEST_F(TransferTest, PointerParamDecl) {
982   std::string Code = R"(
983     struct A {};
984 
985     void target(A *Foo) {
986       (void)0;
987       // [[p]]
988     }
989   )";
990   runDataflow(
991       Code, [](llvm::ArrayRef<
992                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
993                    Results,
994                ASTContext &ASTCtx) {
995         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
996         const Environment &Env = Results[0].second.Env;
997 
998         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
999         ASSERT_THAT(FooDecl, NotNull());
1000 
1001         const StorageLocation *FooLoc =
1002             Env.getStorageLocation(*FooDecl, SkipPast::None);
1003         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1004 
1005         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
1006         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
1007         EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc));
1008 
1009         const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
1010         EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal));
1011       });
1012 }
1013 
1014 TEST_F(TransferTest, StructMember) {
1015   std::string Code = R"(
1016     struct A {
1017       int Bar;
1018     };
1019 
1020     void target(A Foo) {
1021       int Baz = Foo.Bar;
1022       // [[p]]
1023     }
1024   )";
1025   runDataflow(
1026       Code, [](llvm::ArrayRef<
1027                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1028                    Results,
1029                ASTContext &ASTCtx) {
1030         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1031         const Environment &Env = Results[0].second.Env;
1032 
1033         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1034         ASSERT_THAT(FooDecl, NotNull());
1035 
1036         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1037         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1038 
1039         FieldDecl *BarDecl = nullptr;
1040         for (FieldDecl *Field : FooFields) {
1041           if (Field->getNameAsString() == "Bar") {
1042             BarDecl = Field;
1043           } else {
1044             FAIL() << "Unexpected field: " << Field->getNameAsString();
1045           }
1046         }
1047         ASSERT_THAT(BarDecl, NotNull());
1048 
1049         const auto *FooLoc = cast<AggregateStorageLocation>(
1050             Env.getStorageLocation(*FooDecl, SkipPast::None));
1051         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1052         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1053 
1054         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1055         ASSERT_THAT(BazDecl, NotNull());
1056 
1057         EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal);
1058       });
1059 }
1060 
1061 TEST_F(TransferTest, DerivedBaseMemberClass) {
1062   std::string Code = R"(
1063     class A {
1064       int ADefault;
1065     protected:
1066       int AProtected;
1067     private:
1068       int APrivate;
1069     public:
1070       int APublic;
1071     };
1072 
1073     class B : public A {
1074       int BDefault;
1075     protected:
1076       int BProtected;
1077     private:
1078       int BPrivate;
1079     };
1080 
1081     void target() {
1082       B Foo;
1083       // [[p]]
1084     }
1085   )";
1086   runDataflow(
1087       Code, [](llvm::ArrayRef<
1088                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1089                    Results,
1090                ASTContext &ASTCtx) {
1091         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1092         const Environment &Env = Results[0].second.Env;
1093 
1094         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1095         ASSERT_THAT(FooDecl, NotNull());
1096         ASSERT_TRUE(FooDecl->getType()->isRecordType());
1097 
1098         // Derived-class fields.
1099         const FieldDecl *BDefaultDecl = nullptr;
1100         const FieldDecl *BProtectedDecl = nullptr;
1101         const FieldDecl *BPrivateDecl = nullptr;
1102         for (const FieldDecl *Field :
1103              FooDecl->getType()->getAsRecordDecl()->fields()) {
1104           if (Field->getNameAsString() == "BDefault") {
1105             BDefaultDecl = Field;
1106           } else if (Field->getNameAsString() == "BProtected") {
1107             BProtectedDecl = Field;
1108           } else if (Field->getNameAsString() == "BPrivate") {
1109             BPrivateDecl = Field;
1110           } else {
1111             FAIL() << "Unexpected field: " << Field->getNameAsString();
1112           }
1113         }
1114         ASSERT_THAT(BDefaultDecl, NotNull());
1115         ASSERT_THAT(BProtectedDecl, NotNull());
1116         ASSERT_THAT(BPrivateDecl, NotNull());
1117 
1118         // Base-class fields.
1119         const FieldDecl *ADefaultDecl = nullptr;
1120         const FieldDecl *APrivateDecl = nullptr;
1121         const FieldDecl *AProtectedDecl = nullptr;
1122         const FieldDecl *APublicDecl = nullptr;
1123         for (const clang::CXXBaseSpecifier &Base :
1124              FooDecl->getType()->getAsCXXRecordDecl()->bases()) {
1125           QualType BaseType = Base.getType();
1126           ASSERT_TRUE(BaseType->isRecordType());
1127           for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) {
1128             if (Field->getNameAsString() == "ADefault") {
1129               ADefaultDecl = Field;
1130             } else if (Field->getNameAsString() == "AProtected") {
1131               AProtectedDecl = Field;
1132             } else if (Field->getNameAsString() == "APrivate") {
1133               APrivateDecl = Field;
1134             } else if (Field->getNameAsString() == "APublic") {
1135               APublicDecl = Field;
1136             } else {
1137               FAIL() << "Unexpected field: " << Field->getNameAsString();
1138             }
1139           }
1140         }
1141         ASSERT_THAT(ADefaultDecl, NotNull());
1142         ASSERT_THAT(AProtectedDecl, NotNull());
1143         ASSERT_THAT(APrivateDecl, NotNull());
1144         ASSERT_THAT(APublicDecl, NotNull());
1145 
1146         const auto &FooLoc = *cast<AggregateStorageLocation>(
1147             Env.getStorageLocation(*FooDecl, SkipPast::None));
1148         const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc));
1149 
1150         // Note: we can't test presence of children in `FooLoc`, because
1151         // `getChild` requires its argument be present (or fails an assert). So,
1152         // we limit to testing presence in `FooVal` and coherence between the
1153         // two.
1154 
1155         // Base-class fields.
1156         EXPECT_THAT(FooVal.getChild(*ADefaultDecl), IsNull());
1157         EXPECT_THAT(FooVal.getChild(*APrivateDecl), IsNull());
1158 
1159         EXPECT_THAT(FooVal.getChild(*AProtectedDecl), NotNull());
1160         EXPECT_EQ(Env.getValue(FooLoc.getChild(*APublicDecl)),
1161                   FooVal.getChild(*APublicDecl));
1162         EXPECT_THAT(FooVal.getChild(*APublicDecl), NotNull());
1163         EXPECT_EQ(Env.getValue(FooLoc.getChild(*AProtectedDecl)),
1164                   FooVal.getChild(*AProtectedDecl));
1165 
1166         // Derived-class fields.
1167         EXPECT_THAT(FooVal.getChild(*BDefaultDecl), NotNull());
1168         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BDefaultDecl)),
1169                   FooVal.getChild(*BDefaultDecl));
1170         EXPECT_THAT(FooVal.getChild(*BProtectedDecl), NotNull());
1171         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BProtectedDecl)),
1172                   FooVal.getChild(*BProtectedDecl));
1173         EXPECT_THAT(FooVal.getChild(*BPrivateDecl), NotNull());
1174         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BPrivateDecl)),
1175                   FooVal.getChild(*BPrivateDecl));
1176       });
1177 }
1178 
1179 TEST_F(TransferTest, DerivedBaseMemberStructDefault) {
1180   std::string Code = R"(
1181     struct A {
1182       int Bar;
1183     };
1184     struct B : public A {
1185     };
1186 
1187     void target() {
1188       B Foo;
1189       // [[p]]
1190     }
1191   )";
1192   runDataflow(
1193       Code, [](llvm::ArrayRef<
1194                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1195                    Results,
1196                ASTContext &ASTCtx) {
1197         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1198         const Environment &Env = Results[0].second.Env;
1199 
1200         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1201         ASSERT_THAT(FooDecl, NotNull());
1202 
1203         ASSERT_TRUE(FooDecl->getType()->isRecordType());
1204         const FieldDecl *BarDecl = nullptr;
1205         for (const clang::CXXBaseSpecifier &Base :
1206              FooDecl->getType()->getAsCXXRecordDecl()->bases()) {
1207           QualType BaseType = Base.getType();
1208           ASSERT_TRUE(BaseType->isStructureType());
1209 
1210           for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) {
1211             if (Field->getNameAsString() == "Bar") {
1212               BarDecl = Field;
1213             } else {
1214               FAIL() << "Unexpected field: " << Field->getNameAsString();
1215             }
1216           }
1217         }
1218         ASSERT_THAT(BarDecl, NotNull());
1219 
1220         const auto &FooLoc = *cast<AggregateStorageLocation>(
1221             Env.getStorageLocation(*FooDecl, SkipPast::None));
1222         const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc));
1223         EXPECT_THAT(FooVal.getChild(*BarDecl), NotNull());
1224         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BarDecl)),
1225                   FooVal.getChild(*BarDecl));
1226       });
1227 }
1228 
1229 TEST_F(TransferTest, ClassMember) {
1230   std::string Code = R"(
1231     class A {
1232     public:
1233       int Bar;
1234     };
1235 
1236     void target(A Foo) {
1237       int Baz = Foo.Bar;
1238       // [[p]]
1239     }
1240   )";
1241   runDataflow(
1242       Code, [](llvm::ArrayRef<
1243                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1244                    Results,
1245                ASTContext &ASTCtx) {
1246         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1247         const Environment &Env = Results[0].second.Env;
1248 
1249         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1250         ASSERT_THAT(FooDecl, NotNull());
1251 
1252         ASSERT_TRUE(FooDecl->getType()->isClassType());
1253         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1254 
1255         FieldDecl *BarDecl = nullptr;
1256         for (FieldDecl *Field : FooFields) {
1257           if (Field->getNameAsString() == "Bar") {
1258             BarDecl = Field;
1259           } else {
1260             FAIL() << "Unexpected field: " << Field->getNameAsString();
1261           }
1262         }
1263         ASSERT_THAT(BarDecl, NotNull());
1264 
1265         const auto *FooLoc = cast<AggregateStorageLocation>(
1266             Env.getStorageLocation(*FooDecl, SkipPast::None));
1267         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1268         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1269 
1270         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1271         ASSERT_THAT(BazDecl, NotNull());
1272 
1273         EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal);
1274       });
1275 }
1276 
1277 TEST_F(TransferTest, ReferenceMember) {
1278   std::string Code = R"(
1279     struct A {
1280       int &Bar;
1281     };
1282 
1283     void target(A Foo) {
1284       int Baz = Foo.Bar;
1285       // [[p]]
1286     }
1287   )";
1288   runDataflow(
1289       Code, [](llvm::ArrayRef<
1290                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1291                    Results,
1292                ASTContext &ASTCtx) {
1293         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1294         const Environment &Env = Results[0].second.Env;
1295 
1296         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1297         ASSERT_THAT(FooDecl, NotNull());
1298 
1299         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1300         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1301 
1302         FieldDecl *BarDecl = nullptr;
1303         for (FieldDecl *Field : FooFields) {
1304           if (Field->getNameAsString() == "Bar") {
1305             BarDecl = Field;
1306           } else {
1307             FAIL() << "Unexpected field: " << Field->getNameAsString();
1308           }
1309         }
1310         ASSERT_THAT(BarDecl, NotNull());
1311 
1312         const auto *FooLoc = cast<AggregateStorageLocation>(
1313             Env.getStorageLocation(*FooDecl, SkipPast::None));
1314         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1315         const auto *BarVal = cast<ReferenceValue>(FooVal->getChild(*BarDecl));
1316         const auto *BarPointeeVal =
1317             cast<IntegerValue>(Env.getValue(BarVal->getPointeeLoc()));
1318 
1319         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1320         ASSERT_THAT(BazDecl, NotNull());
1321 
1322         EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarPointeeVal);
1323       });
1324 }
1325 
1326 TEST_F(TransferTest, StructThisMember) {
1327   std::string Code = R"(
1328     struct A {
1329       int Bar;
1330 
1331       struct B {
1332         int Baz;
1333       };
1334 
1335       B Qux;
1336 
1337       void target() {
1338         int Foo = Bar;
1339         int Quux = Qux.Baz;
1340         // [[p]]
1341       }
1342     };
1343   )";
1344   runDataflow(
1345       Code, [](llvm::ArrayRef<
1346                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1347                    Results,
1348                ASTContext &ASTCtx) {
1349         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1350         const Environment &Env = Results[0].second.Env;
1351 
1352         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1353             Env.getThisPointeeStorageLocation());
1354         ASSERT_THAT(ThisLoc, NotNull());
1355 
1356         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1357         ASSERT_THAT(BarDecl, NotNull());
1358 
1359         const auto *BarLoc =
1360             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1361         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1362 
1363         const Value *BarVal = Env.getValue(*BarLoc);
1364         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1365 
1366         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1367         ASSERT_THAT(FooDecl, NotNull());
1368         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1369 
1370         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1371         ASSERT_THAT(QuxDecl, NotNull());
1372 
1373         ASSERT_TRUE(QuxDecl->getType()->isStructureType());
1374         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1375 
1376         FieldDecl *BazDecl = nullptr;
1377         for (FieldDecl *Field : QuxFields) {
1378           if (Field->getNameAsString() == "Baz") {
1379             BazDecl = Field;
1380           } else {
1381             FAIL() << "Unexpected field: " << Field->getNameAsString();
1382           }
1383         }
1384         ASSERT_THAT(BazDecl, NotNull());
1385 
1386         const auto *QuxLoc =
1387             cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl));
1388         const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc));
1389         ASSERT_THAT(QuxVal, NotNull());
1390 
1391         const auto *BazLoc =
1392             cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl));
1393         const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl));
1394         EXPECT_EQ(Env.getValue(*BazLoc), BazVal);
1395 
1396         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1397         ASSERT_THAT(QuuxDecl, NotNull());
1398         EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal);
1399       });
1400 }
1401 
1402 TEST_F(TransferTest, ClassThisMember) {
1403   std::string Code = R"(
1404     class A {
1405       int Bar;
1406 
1407       class B {
1408       public:
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, [](llvm::ArrayRef<
1423                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1424                    Results,
1425                ASTContext &ASTCtx) {
1426         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1427         const Environment &Env = Results[0].second.Env;
1428 
1429         const auto *ThisLoc =
1430             cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation());
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()->isClassType());
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_F(TransferTest, ConstructorInitializer) {
1479   std::string Code = R"(
1480     struct target {
1481       int Bar;
1482 
1483       target(int Foo) : Bar(Foo) {
1484         int Qux = Bar;
1485         // [[p]]
1486       }
1487     };
1488   )";
1489   runDataflow(Code,
1490               [](llvm::ArrayRef<
1491                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1492                      Results,
1493                  ASTContext &ASTCtx) {
1494                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1495                 const Environment &Env = Results[0].second.Env;
1496 
1497                 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1498                     Env.getThisPointeeStorageLocation());
1499                 ASSERT_THAT(ThisLoc, NotNull());
1500 
1501                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1502                 ASSERT_THAT(FooDecl, NotNull());
1503 
1504                 const auto *FooVal =
1505                     cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None));
1506 
1507                 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1508                 ASSERT_THAT(QuxDecl, NotNull());
1509                 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal);
1510               });
1511 }
1512 
1513 TEST_F(TransferTest, DefaultInitializer) {
1514   std::string Code = R"(
1515     struct target {
1516       int Bar;
1517       int Baz = Bar;
1518 
1519       target(int Foo) : Bar(Foo) {
1520         int Qux = Baz;
1521         // [[p]]
1522       }
1523     };
1524   )";
1525   runDataflow(Code,
1526               [](llvm::ArrayRef<
1527                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1528                      Results,
1529                  ASTContext &ASTCtx) {
1530                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1531                 const Environment &Env = Results[0].second.Env;
1532 
1533                 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1534                     Env.getThisPointeeStorageLocation());
1535                 ASSERT_THAT(ThisLoc, NotNull());
1536 
1537                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1538                 ASSERT_THAT(FooDecl, NotNull());
1539 
1540                 const auto *FooVal =
1541                     cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None));
1542 
1543                 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1544                 ASSERT_THAT(QuxDecl, NotNull());
1545                 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal);
1546               });
1547 }
1548 
1549 TEST_F(TransferTest, DefaultInitializerReference) {
1550   std::string Code = R"(
1551     struct target {
1552       int &Bar;
1553       int &Baz = Bar;
1554 
1555       target(int &Foo) : Bar(Foo) {
1556         int &Qux = Baz;
1557         // [[p]]
1558       }
1559     };
1560   )";
1561   runDataflow(
1562       Code, [](llvm::ArrayRef<
1563                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1564                    Results,
1565                ASTContext &ASTCtx) {
1566         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1567         const Environment &Env = Results[0].second.Env;
1568 
1569         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1570             Env.getThisPointeeStorageLocation());
1571         ASSERT_THAT(ThisLoc, NotNull());
1572 
1573         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1574         ASSERT_THAT(FooDecl, NotNull());
1575 
1576         const auto *FooVal =
1577             cast<ReferenceValue>(Env.getValue(*FooDecl, SkipPast::None));
1578 
1579         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1580         ASSERT_THAT(QuxDecl, NotNull());
1581 
1582         const auto *QuxVal =
1583             cast<ReferenceValue>(Env.getValue(*QuxDecl, SkipPast::None));
1584         EXPECT_EQ(&QuxVal->getPointeeLoc(), &FooVal->getPointeeLoc());
1585       });
1586 }
1587 
1588 TEST_F(TransferTest, TemporaryObject) {
1589   std::string Code = R"(
1590     struct A {
1591       int Bar;
1592     };
1593 
1594     void target() {
1595       A Foo = A();
1596       // [[p]]
1597     }
1598   )";
1599   runDataflow(
1600       Code, [](llvm::ArrayRef<
1601                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1602                    Results,
1603                ASTContext &ASTCtx) {
1604         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1605         const Environment &Env = Results[0].second.Env;
1606 
1607         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1608         ASSERT_THAT(FooDecl, NotNull());
1609 
1610         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1611         ASSERT_THAT(BarDecl, NotNull());
1612 
1613         const auto *FooLoc = cast<AggregateStorageLocation>(
1614             Env.getStorageLocation(*FooDecl, SkipPast::None));
1615         const auto *BarLoc =
1616             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
1617 
1618         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1619         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1620         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
1621       });
1622 }
1623 
1624 TEST_F(TransferTest, ElidableConstructor) {
1625   // This test is effectively the same as TransferTest.TemporaryObject, but
1626   // the code is compiled as C++ 14.
1627   std::string Code = R"(
1628     struct A {
1629       int Bar;
1630     };
1631 
1632     void target() {
1633       A Foo = A();
1634       // [[p]]
1635     }
1636   )";
1637   runDataflow(
1638       Code,
1639       [](llvm::ArrayRef<
1640              std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1641              Results,
1642          ASTContext &ASTCtx) {
1643         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1644         const Environment &Env = Results[0].second.Env;
1645 
1646         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1647         ASSERT_THAT(FooDecl, NotNull());
1648 
1649         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1650         ASSERT_THAT(BarDecl, NotNull());
1651 
1652         const auto *FooLoc = cast<AggregateStorageLocation>(
1653             Env.getStorageLocation(*FooDecl, SkipPast::None));
1654         const auto *BarLoc =
1655             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
1656 
1657         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1658         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1659         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
1660       },
1661       LangStandard::lang_cxx14);
1662 }
1663 
1664 TEST_F(TransferTest, AssignmentOperator) {
1665   std::string Code = R"(
1666     struct A {
1667       int Baz;
1668     };
1669 
1670     void target() {
1671       A Foo;
1672       A Bar;
1673       // [[p1]]
1674       Foo = Bar;
1675       // [[p2]]
1676     }
1677   )";
1678   runDataflow(
1679       Code, [](llvm::ArrayRef<
1680                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1681                    Results,
1682                ASTContext &ASTCtx) {
1683         ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
1684         const Environment &Env1 = Results[0].second.Env;
1685         const Environment &Env2 = Results[1].second.Env;
1686 
1687         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1688         ASSERT_THAT(FooDecl, NotNull());
1689 
1690         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1691         ASSERT_THAT(BarDecl, NotNull());
1692 
1693         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1694         ASSERT_THAT(BazDecl, NotNull());
1695 
1696         const auto *FooLoc1 = cast<AggregateStorageLocation>(
1697             Env1.getStorageLocation(*FooDecl, SkipPast::None));
1698         const auto *BarLoc1 = cast<AggregateStorageLocation>(
1699             Env1.getStorageLocation(*BarDecl, SkipPast::None));
1700 
1701         const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1));
1702         const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1));
1703         EXPECT_NE(FooVal1, BarVal1);
1704 
1705         const auto *FooBazVal1 =
1706             cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl)));
1707         const auto *BarBazVal1 =
1708             cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl)));
1709         EXPECT_NE(FooBazVal1, BarBazVal1);
1710 
1711         const auto *FooLoc2 = cast<AggregateStorageLocation>(
1712             Env2.getStorageLocation(*FooDecl, SkipPast::None));
1713         const auto *BarLoc2 = cast<AggregateStorageLocation>(
1714             Env2.getStorageLocation(*BarDecl, SkipPast::None));
1715 
1716         const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2));
1717         const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2));
1718         EXPECT_EQ(FooVal2, BarVal2);
1719 
1720         const auto *FooBazVal2 =
1721             cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl)));
1722         const auto *BarBazVal2 =
1723             cast<IntegerValue>(Env2.getValue(BarLoc1->getChild(*BazDecl)));
1724         EXPECT_EQ(FooBazVal2, BarBazVal2);
1725       });
1726 }
1727 
1728 TEST_F(TransferTest, CopyConstructor) {
1729   std::string Code = R"(
1730     struct A {
1731       int Baz;
1732     };
1733 
1734     void target() {
1735       A Foo;
1736       A Bar = Foo;
1737       // [[p]]
1738     }
1739   )";
1740   runDataflow(
1741       Code, [](llvm::ArrayRef<
1742                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1743                    Results,
1744                ASTContext &ASTCtx) {
1745         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1746         const Environment &Env = Results[0].second.Env;
1747 
1748         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1749         ASSERT_THAT(FooDecl, NotNull());
1750 
1751         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1752         ASSERT_THAT(BarDecl, NotNull());
1753 
1754         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1755         ASSERT_THAT(BazDecl, NotNull());
1756 
1757         const auto *FooLoc = cast<AggregateStorageLocation>(
1758             Env.getStorageLocation(*FooDecl, SkipPast::None));
1759         const auto *BarLoc = cast<AggregateStorageLocation>(
1760             Env.getStorageLocation(*BarDecl, SkipPast::None));
1761 
1762         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1763         const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc));
1764         EXPECT_EQ(FooVal, BarVal);
1765 
1766         const auto *FooBazVal =
1767             cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl)));
1768         const auto *BarBazVal =
1769             cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl)));
1770         EXPECT_EQ(FooBazVal, BarBazVal);
1771       });
1772 }
1773 
1774 TEST_F(TransferTest, CopyConstructorWithParens) {
1775   std::string Code = R"(
1776     struct A {
1777       int Baz;
1778     };
1779 
1780     void target() {
1781       A Foo;
1782       A Bar((A(Foo)));
1783       // [[p]]
1784     }
1785   )";
1786   runDataflow(
1787       Code, [](llvm::ArrayRef<
1788                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1789                    Results,
1790                ASTContext &ASTCtx) {
1791         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1792         const Environment &Env = Results[0].second.Env;
1793 
1794         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1795         ASSERT_THAT(FooDecl, NotNull());
1796 
1797         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1798         ASSERT_THAT(BarDecl, NotNull());
1799 
1800         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1801         ASSERT_THAT(BazDecl, NotNull());
1802 
1803         const auto *FooLoc = cast<AggregateStorageLocation>(
1804             Env.getStorageLocation(*FooDecl, SkipPast::None));
1805         const auto *BarLoc = cast<AggregateStorageLocation>(
1806             Env.getStorageLocation(*BarDecl, SkipPast::None));
1807 
1808         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1809         const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc));
1810         EXPECT_EQ(FooVal, BarVal);
1811 
1812         const auto *FooBazVal =
1813             cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl)));
1814         const auto *BarBazVal =
1815             cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl)));
1816         EXPECT_EQ(FooBazVal, BarBazVal);
1817       });
1818 }
1819 
1820 TEST_F(TransferTest, MoveConstructor) {
1821   std::string Code = R"(
1822     namespace std {
1823 
1824     template <typename T> struct remove_reference      { using type = T; };
1825     template <typename T> struct remove_reference<T&>  { using type = T; };
1826     template <typename T> struct remove_reference<T&&> { using type = T; };
1827 
1828     template <typename T>
1829     using remove_reference_t = typename remove_reference<T>::type;
1830 
1831     template <typename T>
1832     std::remove_reference_t<T>&& move(T&& x);
1833 
1834     } // namespace std
1835 
1836     struct A {
1837       int Baz;
1838     };
1839 
1840     void target() {
1841       A Foo;
1842       A Bar;
1843       // [[p1]]
1844       Foo = std::move(Bar);
1845       // [[p2]]
1846     }
1847   )";
1848   runDataflow(
1849       Code, [](llvm::ArrayRef<
1850                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1851                    Results,
1852                ASTContext &ASTCtx) {
1853         ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
1854         const Environment &Env1 = Results[0].second.Env;
1855         const Environment &Env2 = Results[1].second.Env;
1856 
1857         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1858         ASSERT_THAT(FooDecl, NotNull());
1859 
1860         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1861         ASSERT_THAT(BarDecl, NotNull());
1862 
1863         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1864         ASSERT_THAT(BazDecl, NotNull());
1865 
1866         const auto *FooLoc1 = cast<AggregateStorageLocation>(
1867             Env1.getStorageLocation(*FooDecl, SkipPast::None));
1868         const auto *BarLoc1 = cast<AggregateStorageLocation>(
1869             Env1.getStorageLocation(*BarDecl, SkipPast::None));
1870 
1871         const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1));
1872         const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1));
1873         EXPECT_NE(FooVal1, BarVal1);
1874 
1875         const auto *FooBazVal1 =
1876             cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl)));
1877         const auto *BarBazVal1 =
1878             cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl)));
1879         EXPECT_NE(FooBazVal1, BarBazVal1);
1880 
1881         const auto *FooLoc2 = cast<AggregateStorageLocation>(
1882             Env2.getStorageLocation(*FooDecl, SkipPast::None));
1883         const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2));
1884         EXPECT_EQ(FooVal2, BarVal1);
1885 
1886         const auto *FooBazVal2 =
1887             cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl)));
1888         EXPECT_EQ(FooBazVal2, BarBazVal1);
1889       });
1890 }
1891 
1892 TEST_F(TransferTest, BindTemporary) {
1893   std::string Code = R"(
1894     struct A {
1895       virtual ~A() = default;
1896 
1897       int Baz;
1898     };
1899 
1900     void target(A Foo) {
1901       int Bar = A(Foo).Baz;
1902       // [[p]]
1903     }
1904   )";
1905   runDataflow(Code,
1906               [](llvm::ArrayRef<
1907                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1908                      Results,
1909                  ASTContext &ASTCtx) {
1910                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1911                 const Environment &Env = Results[0].second.Env;
1912 
1913                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1914                 ASSERT_THAT(FooDecl, NotNull());
1915 
1916                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1917                 ASSERT_THAT(BarDecl, NotNull());
1918 
1919                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1920                 ASSERT_THAT(BazDecl, NotNull());
1921 
1922                 const auto &FooVal =
1923                     *cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None));
1924                 const auto *BarVal =
1925                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
1926                 EXPECT_EQ(BarVal, FooVal.getChild(*BazDecl));
1927               });
1928 }
1929 
1930 TEST_F(TransferTest, StaticCast) {
1931   std::string Code = R"(
1932     void target(int Foo) {
1933       int Bar = static_cast<int>(Foo);
1934       // [[p]]
1935     }
1936   )";
1937   runDataflow(Code,
1938               [](llvm::ArrayRef<
1939                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1940                      Results,
1941                  ASTContext &ASTCtx) {
1942                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1943                 const Environment &Env = Results[0].second.Env;
1944 
1945                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1946                 ASSERT_THAT(FooDecl, NotNull());
1947 
1948                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1949                 ASSERT_THAT(BarDecl, NotNull());
1950 
1951                 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
1952                 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
1953                 EXPECT_TRUE(isa<IntegerValue>(FooVal));
1954                 EXPECT_TRUE(isa<IntegerValue>(BarVal));
1955                 EXPECT_EQ(FooVal, BarVal);
1956               });
1957 }
1958 
1959 TEST_F(TransferTest, IntegralCast) {
1960   std::string Code = R"(
1961     void target(int Foo) {
1962       long Bar = Foo;
1963       // [[p]]
1964     }
1965   )";
1966   runDataflow(Code,
1967               [](llvm::ArrayRef<
1968                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1969                      Results,
1970                  ASTContext &ASTCtx) {
1971                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1972                 const Environment &Env = Results[0].second.Env;
1973 
1974                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1975                 ASSERT_THAT(FooDecl, NotNull());
1976 
1977                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1978                 ASSERT_THAT(BarDecl, NotNull());
1979 
1980                 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
1981                 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
1982                 EXPECT_TRUE(isa<IntegerValue>(FooVal));
1983                 EXPECT_TRUE(isa<IntegerValue>(BarVal));
1984                 EXPECT_EQ(FooVal, BarVal);
1985               });
1986 }
1987 
1988 TEST_F(TransferTest, IntegraltoBooleanCast) {
1989   std::string Code = R"(
1990     void target(int Foo) {
1991       bool Bar = Foo;
1992       // [[p]]
1993     }
1994   )";
1995   runDataflow(Code,
1996               [](llvm::ArrayRef<
1997                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1998                      Results,
1999                  ASTContext &ASTCtx) {
2000                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2001                 const Environment &Env = Results[0].second.Env;
2002 
2003                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2004                 ASSERT_THAT(FooDecl, NotNull());
2005 
2006                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2007                 ASSERT_THAT(BarDecl, NotNull());
2008 
2009                 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2010                 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2011                 EXPECT_TRUE(isa<IntegerValue>(FooVal));
2012                 EXPECT_TRUE(isa<BoolValue>(BarVal));
2013               });
2014 }
2015 
2016 TEST_F(TransferTest, IntegralToBooleanCastFromBool) {
2017   std::string Code = R"(
2018     void target(bool Foo) {
2019       int Zab = Foo;
2020       bool Bar = Zab;
2021       // [[p]]
2022     }
2023   )";
2024   runDataflow(Code,
2025               [](llvm::ArrayRef<
2026                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2027                      Results,
2028                  ASTContext &ASTCtx) {
2029                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2030                 const Environment &Env = Results[0].second.Env;
2031 
2032                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2033                 ASSERT_THAT(FooDecl, NotNull());
2034 
2035                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2036                 ASSERT_THAT(BarDecl, NotNull());
2037 
2038                 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2039                 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2040                 EXPECT_TRUE(isa<BoolValue>(FooVal));
2041                 EXPECT_TRUE(isa<BoolValue>(BarVal));
2042                 EXPECT_EQ(FooVal, BarVal);
2043               });
2044 }
2045 
2046 TEST_F(TransferTest, AddrOfValue) {
2047   std::string Code = R"(
2048     void target() {
2049       int Foo;
2050       int *Bar = &Foo;
2051       // [[p]]
2052     }
2053   )";
2054   runDataflow(Code,
2055               [](llvm::ArrayRef<
2056                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2057                      Results,
2058                  ASTContext &ASTCtx) {
2059                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2060                 const Environment &Env = Results[0].second.Env;
2061 
2062                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2063                 ASSERT_THAT(FooDecl, NotNull());
2064 
2065                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2066                 ASSERT_THAT(BarDecl, NotNull());
2067 
2068                 const auto *FooLoc = cast<ScalarStorageLocation>(
2069                     Env.getStorageLocation(*FooDecl, SkipPast::None));
2070                 const auto *BarVal =
2071                     cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
2072                 EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
2073               });
2074 }
2075 
2076 TEST_F(TransferTest, AddrOfReference) {
2077   std::string Code = R"(
2078     void target(int *Foo) {
2079       int *Bar = &(*Foo);
2080       // [[p]]
2081     }
2082   )";
2083   runDataflow(Code,
2084               [](llvm::ArrayRef<
2085                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2086                      Results,
2087                  ASTContext &ASTCtx) {
2088                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2089                 const Environment &Env = Results[0].second.Env;
2090 
2091                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2092                 ASSERT_THAT(FooDecl, NotNull());
2093 
2094                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2095                 ASSERT_THAT(BarDecl, NotNull());
2096 
2097                 const auto *FooVal =
2098                     cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2099                 const auto *BarVal =
2100                     cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
2101                 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
2102               });
2103 }
2104 
2105 TEST_F(TransferTest, DerefDependentPtr) {
2106   std::string Code = R"(
2107     template <typename T>
2108     void target(T *Foo) {
2109       T &Bar = *Foo;
2110       /*[[p]]*/
2111     }
2112   )";
2113   runDataflow(
2114       Code, [](llvm::ArrayRef<
2115                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2116                    Results,
2117                ASTContext &ASTCtx) {
2118         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2119         const Environment &Env = Results[0].second.Env;
2120 
2121         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2122         ASSERT_THAT(FooDecl, NotNull());
2123 
2124         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2125         ASSERT_THAT(BarDecl, NotNull());
2126 
2127         const auto *FooVal =
2128             cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2129         const auto *BarVal =
2130             cast<ReferenceValue>(Env.getValue(*BarDecl, SkipPast::None));
2131         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
2132       });
2133 }
2134 
2135 TEST_F(TransferTest, VarDeclInitAssignConditionalOperator) {
2136   std::string Code = R"(
2137     struct A {};
2138 
2139     void target(A Foo, A Bar, bool Cond) {
2140       A Baz = Cond ?  Foo : Bar;
2141       /*[[p]]*/
2142     }
2143   )";
2144   runDataflow(
2145       Code, [](llvm::ArrayRef<
2146                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2147                    Results,
2148                ASTContext &ASTCtx) {
2149         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2150         const Environment &Env = Results[0].second.Env;
2151 
2152         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2153         ASSERT_THAT(FooDecl, NotNull());
2154 
2155         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2156         ASSERT_THAT(BarDecl, NotNull());
2157 
2158         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2159         ASSERT_THAT(BazDecl, NotNull());
2160 
2161         const auto *FooVal =
2162             cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None));
2163         const auto *BarVal =
2164             cast<StructValue>(Env.getValue(*BarDecl, SkipPast::None));
2165 
2166         const auto *BazVal =
2167             dyn_cast<StructValue>(Env.getValue(*BazDecl, SkipPast::None));
2168         ASSERT_THAT(BazVal, NotNull());
2169 
2170         EXPECT_NE(BazVal, FooVal);
2171         EXPECT_NE(BazVal, BarVal);
2172       });
2173 }
2174 
2175 TEST_F(TransferTest, VarDeclInDoWhile) {
2176   std::string Code = R"(
2177     void target(int *Foo) {
2178       do {
2179         int Bar = *Foo;
2180       } while (true);
2181       (void)0;
2182       /*[[p]]*/
2183     }
2184   )";
2185   runDataflow(Code,
2186               [](llvm::ArrayRef<
2187                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2188                      Results,
2189                  ASTContext &ASTCtx) {
2190                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2191                 const Environment &Env = Results[0].second.Env;
2192 
2193                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2194                 ASSERT_THAT(FooDecl, NotNull());
2195 
2196                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2197                 ASSERT_THAT(BarDecl, NotNull());
2198 
2199                 const auto *FooVal =
2200                     cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2201                 const auto *FooPointeeVal =
2202                     cast<IntegerValue>(Env.getValue(FooVal->getPointeeLoc()));
2203 
2204                 const auto *BarVal = dyn_cast_or_null<IntegerValue>(
2205                     Env.getValue(*BarDecl, SkipPast::None));
2206                 ASSERT_THAT(BarVal, NotNull());
2207 
2208                 EXPECT_EQ(BarVal, FooPointeeVal);
2209               });
2210 }
2211 
2212 TEST_F(TransferTest, AggregateInitialization) {
2213   std::string BracesCode = R"(
2214     struct A {
2215       int Foo;
2216     };
2217 
2218     struct B {
2219       int Bar;
2220       A Baz;
2221       int Qux;
2222     };
2223 
2224     void target(int BarArg, int FooArg, int QuxArg) {
2225       B Quux{BarArg, {FooArg}, QuxArg};
2226       /*[[p]]*/
2227     }
2228   )";
2229   std::string BraceEllisionCode = R"(
2230     struct A {
2231       int Foo;
2232     };
2233 
2234     struct B {
2235       int Bar;
2236       A Baz;
2237       int Qux;
2238     };
2239 
2240     void target(int BarArg, int FooArg, int QuxArg) {
2241       B Quux = {BarArg, FooArg, QuxArg};
2242       /*[[p]]*/
2243     }
2244   )";
2245   for (const std::string &Code : {BracesCode, BraceEllisionCode}) {
2246     runDataflow(
2247         Code, [](llvm::ArrayRef<
2248                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2249                      Results,
2250                  ASTContext &ASTCtx) {
2251           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2252           const Environment &Env = Results[0].second.Env;
2253 
2254           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2255           ASSERT_THAT(FooDecl, NotNull());
2256 
2257           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2258           ASSERT_THAT(BarDecl, NotNull());
2259 
2260           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2261           ASSERT_THAT(BazDecl, NotNull());
2262 
2263           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2264           ASSERT_THAT(QuxDecl, NotNull());
2265 
2266           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
2267           ASSERT_THAT(FooArgDecl, NotNull());
2268 
2269           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
2270           ASSERT_THAT(BarArgDecl, NotNull());
2271 
2272           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
2273           ASSERT_THAT(QuxArgDecl, NotNull());
2274 
2275           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
2276           ASSERT_THAT(QuuxDecl, NotNull());
2277 
2278           const auto *FooArgVal =
2279               cast<IntegerValue>(Env.getValue(*FooArgDecl, SkipPast::None));
2280           const auto *BarArgVal =
2281               cast<IntegerValue>(Env.getValue(*BarArgDecl, SkipPast::None));
2282           const auto *QuxArgVal =
2283               cast<IntegerValue>(Env.getValue(*QuxArgDecl, SkipPast::None));
2284 
2285           const auto *QuuxVal =
2286               cast<StructValue>(Env.getValue(*QuuxDecl, SkipPast::None));
2287           ASSERT_THAT(QuuxVal, NotNull());
2288 
2289           const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl));
2290           ASSERT_THAT(BazVal, NotNull());
2291 
2292           EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal);
2293           EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal);
2294           EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal);
2295         });
2296   }
2297 }
2298 
2299 TEST_F(TransferTest, AssignToUnionMember) {
2300   std::string Code = R"(
2301     union A {
2302       int Foo;
2303     };
2304 
2305     void target(int Bar) {
2306       A Baz;
2307       Baz.Foo = Bar;
2308       // [[p]]
2309     }
2310   )";
2311   runDataflow(Code,
2312               [](llvm::ArrayRef<
2313                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2314                      Results,
2315                  ASTContext &ASTCtx) {
2316                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2317                 const Environment &Env = Results[0].second.Env;
2318 
2319                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2320                 ASSERT_THAT(BazDecl, NotNull());
2321                 ASSERT_TRUE(BazDecl->getType()->isUnionType());
2322 
2323                 const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>(
2324                     Env.getStorageLocation(*BazDecl, SkipPast::None));
2325                 ASSERT_THAT(BazLoc, NotNull());
2326 
2327                 // FIXME: Add support for union types.
2328                 EXPECT_THAT(Env.getValue(*BazLoc), IsNull());
2329               });
2330 }
2331 
2332 TEST_F(TransferTest, AssignFromBoolLiteral) {
2333   std::string Code = R"(
2334     void target() {
2335       bool Foo = true;
2336       bool Bar = false;
2337       // [[p]]
2338     }
2339   )";
2340   runDataflow(Code,
2341               [](llvm::ArrayRef<
2342                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2343                      Results,
2344                  ASTContext &ASTCtx) {
2345                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2346                 const Environment &Env = Results[0].second.Env;
2347 
2348                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2349                 ASSERT_THAT(FooDecl, NotNull());
2350 
2351                 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>(
2352                     Env.getValue(*FooDecl, SkipPast::None));
2353                 ASSERT_THAT(FooVal, NotNull());
2354 
2355                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2356                 ASSERT_THAT(BarDecl, NotNull());
2357 
2358                 const auto *BarVal = dyn_cast_or_null<AtomicBoolValue>(
2359                     Env.getValue(*BarDecl, SkipPast::None));
2360                 ASSERT_THAT(BarVal, NotNull());
2361 
2362                 EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
2363                 EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
2364               });
2365 }
2366 
2367 TEST_F(TransferTest, AssignFromCompositeBoolExpression) {
2368   {
2369     std::string Code = R"(
2370     void target(bool Foo, bool Bar, bool Qux) {
2371       bool Baz = (Foo) && (Bar || Qux);
2372       // [[p]]
2373     }
2374   )";
2375     runDataflow(
2376         Code, [](llvm::ArrayRef<
2377                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2378                      Results,
2379                  ASTContext &ASTCtx) {
2380           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2381           const Environment &Env = Results[0].second.Env;
2382 
2383           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2384           ASSERT_THAT(FooDecl, NotNull());
2385 
2386           const auto *FooVal = dyn_cast_or_null<BoolValue>(
2387               Env.getValue(*FooDecl, SkipPast::None));
2388           ASSERT_THAT(FooVal, NotNull());
2389 
2390           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2391           ASSERT_THAT(BarDecl, NotNull());
2392 
2393           const auto *BarVal = dyn_cast_or_null<BoolValue>(
2394               Env.getValue(*BarDecl, SkipPast::None));
2395           ASSERT_THAT(BarVal, NotNull());
2396 
2397           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2398           ASSERT_THAT(QuxDecl, NotNull());
2399 
2400           const auto *QuxVal = dyn_cast_or_null<BoolValue>(
2401               Env.getValue(*QuxDecl, SkipPast::None));
2402           ASSERT_THAT(QuxVal, NotNull());
2403 
2404           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2405           ASSERT_THAT(BazDecl, NotNull());
2406 
2407           const auto *BazVal = dyn_cast_or_null<ConjunctionValue>(
2408               Env.getValue(*BazDecl, SkipPast::None));
2409           ASSERT_THAT(BazVal, NotNull());
2410           EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
2411 
2412           const auto *BazRightSubValVal =
2413               cast<DisjunctionValue>(&BazVal->getRightSubValue());
2414           EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal);
2415           EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal);
2416         });
2417   }
2418 
2419   {
2420     std::string Code = R"(
2421     void target(bool Foo, bool Bar, bool Qux) {
2422       bool Baz = (Foo && Qux) || (Bar);
2423       // [[p]]
2424     }
2425   )";
2426     runDataflow(
2427         Code, [](llvm::ArrayRef<
2428                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2429                      Results,
2430                  ASTContext &ASTCtx) {
2431           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2432           const Environment &Env = Results[0].second.Env;
2433 
2434           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2435           ASSERT_THAT(FooDecl, NotNull());
2436 
2437           const auto *FooVal = dyn_cast_or_null<BoolValue>(
2438               Env.getValue(*FooDecl, SkipPast::None));
2439           ASSERT_THAT(FooVal, NotNull());
2440 
2441           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2442           ASSERT_THAT(BarDecl, NotNull());
2443 
2444           const auto *BarVal = dyn_cast_or_null<BoolValue>(
2445               Env.getValue(*BarDecl, SkipPast::None));
2446           ASSERT_THAT(BarVal, NotNull());
2447 
2448           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2449           ASSERT_THAT(QuxDecl, NotNull());
2450 
2451           const auto *QuxVal = dyn_cast_or_null<BoolValue>(
2452               Env.getValue(*QuxDecl, SkipPast::None));
2453           ASSERT_THAT(QuxVal, NotNull());
2454 
2455           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2456           ASSERT_THAT(BazDecl, NotNull());
2457 
2458           const auto *BazVal = dyn_cast_or_null<DisjunctionValue>(
2459               Env.getValue(*BazDecl, SkipPast::None));
2460           ASSERT_THAT(BazVal, NotNull());
2461 
2462           const auto *BazLeftSubValVal =
2463               cast<ConjunctionValue>(&BazVal->getLeftSubValue());
2464           EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal);
2465           EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal);
2466 
2467           EXPECT_EQ(&BazVal->getRightSubValue(), BarVal);
2468         });
2469   }
2470 }
2471 
2472 TEST_F(TransferTest, AssignFromBoolNegation) {
2473   std::string Code = R"(
2474     void target() {
2475       bool Foo = true;
2476       bool Bar = !(Foo);
2477       // [[p]]
2478     }
2479   )";
2480   runDataflow(Code,
2481               [](llvm::ArrayRef<
2482                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2483                      Results,
2484                  ASTContext &ASTCtx) {
2485                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2486                 const Environment &Env = Results[0].second.Env;
2487 
2488                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2489                 ASSERT_THAT(FooDecl, NotNull());
2490 
2491                 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>(
2492                     Env.getValue(*FooDecl, SkipPast::None));
2493                 ASSERT_THAT(FooVal, NotNull());
2494 
2495                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2496                 ASSERT_THAT(BarDecl, NotNull());
2497 
2498                 const auto *BarVal = dyn_cast_or_null<NegationValue>(
2499                     Env.getValue(*BarDecl, SkipPast::None));
2500                 ASSERT_THAT(BarVal, NotNull());
2501 
2502                 EXPECT_EQ(&BarVal->getSubVal(), FooVal);
2503               });
2504 }
2505 
2506 TEST_F(TransferTest, BuiltinExpect) {
2507   std::string Code = R"(
2508     void target(long Foo) {
2509       long Bar = __builtin_expect(Foo, true);
2510       /*[[p]]*/
2511     }
2512   )";
2513   runDataflow(Code,
2514               [](llvm::ArrayRef<
2515                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2516                      Results,
2517                  ASTContext &ASTCtx) {
2518                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2519                 const auto &Env = Results[0].second.Env;
2520 
2521                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2522                 ASSERT_THAT(FooDecl, NotNull());
2523 
2524                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2525                 ASSERT_THAT(BarDecl, NotNull());
2526 
2527                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2528                           Env.getValue(*BarDecl, SkipPast::None));
2529               });
2530 }
2531 
2532 // `__builtin_expect` takes and returns a `long` argument, so other types
2533 // involve casts. This verifies that we identify the input and output in that
2534 // case.
2535 TEST_F(TransferTest, BuiltinExpectBoolArg) {
2536   std::string Code = R"(
2537     void target(bool Foo) {
2538       bool Bar = __builtin_expect(Foo, true);
2539       /*[[p]]*/
2540     }
2541   )";
2542   runDataflow(Code,
2543               [](llvm::ArrayRef<
2544                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2545                      Results,
2546                  ASTContext &ASTCtx) {
2547                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2548                 const auto &Env = Results[0].second.Env;
2549 
2550                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2551                 ASSERT_THAT(FooDecl, NotNull());
2552 
2553                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2554                 ASSERT_THAT(BarDecl, NotNull());
2555 
2556                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2557                           Env.getValue(*BarDecl, SkipPast::None));
2558               });
2559 }
2560 
2561 TEST_F(TransferTest, BuiltinUnreachable) {
2562   std::string Code = R"(
2563     void target(bool Foo) {
2564       bool Bar = false;
2565       if (Foo)
2566         Bar = Foo;
2567       else
2568         __builtin_unreachable();
2569       (void)0;
2570       /*[[p]]*/
2571     }
2572   )";
2573   runDataflow(Code,
2574               [](llvm::ArrayRef<
2575                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2576                      Results,
2577                  ASTContext &ASTCtx) {
2578                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2579                 const auto &Env = Results[0].second.Env;
2580 
2581                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2582                 ASSERT_THAT(FooDecl, NotNull());
2583 
2584                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2585                 ASSERT_THAT(BarDecl, NotNull());
2586 
2587                 // `__builtin_unreachable` promises that the code is
2588                 // unreachable, so the compiler treats the "then" branch as the
2589                 // only possible predecessor of this statement.
2590                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2591                           Env.getValue(*BarDecl, SkipPast::None));
2592               });
2593 }
2594 
2595 TEST_F(TransferTest, BuiltinTrap) {
2596   std::string Code = R"(
2597     void target(bool Foo) {
2598       bool Bar = false;
2599       if (Foo)
2600         Bar = Foo;
2601       else
2602         __builtin_trap();
2603       (void)0;
2604       /*[[p]]*/
2605     }
2606   )";
2607   runDataflow(Code,
2608               [](llvm::ArrayRef<
2609                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2610                      Results,
2611                  ASTContext &ASTCtx) {
2612                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2613                 const auto &Env = Results[0].second.Env;
2614 
2615                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2616                 ASSERT_THAT(FooDecl, NotNull());
2617 
2618                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2619                 ASSERT_THAT(BarDecl, NotNull());
2620 
2621                 // `__builtin_trap` ensures program termination, so only the
2622                 // "then" branch is a predecessor of this statement.
2623                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2624                           Env.getValue(*BarDecl, SkipPast::None));
2625               });
2626 }
2627 
2628 TEST_F(TransferTest, BuiltinDebugTrap) {
2629   std::string Code = R"(
2630     void target(bool Foo) {
2631       bool Bar = false;
2632       if (Foo)
2633         Bar = Foo;
2634       else
2635         __builtin_debugtrap();
2636       (void)0;
2637       /*[[p]]*/
2638     }
2639   )";
2640   runDataflow(Code,
2641               [](llvm::ArrayRef<
2642                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2643                      Results,
2644                  ASTContext &ASTCtx) {
2645                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2646                 const auto &Env = Results[0].second.Env;
2647 
2648                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2649                 ASSERT_THAT(FooDecl, NotNull());
2650 
2651                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2652                 ASSERT_THAT(BarDecl, NotNull());
2653 
2654                 // `__builtin_debugtrap` doesn't ensure program termination.
2655                 EXPECT_NE(Env.getValue(*FooDecl, SkipPast::None),
2656                           Env.getValue(*BarDecl, SkipPast::None));
2657               });
2658 }
2659 
2660 TEST_F(TransferTest, StaticIntSingleVarDecl) {
2661   std::string Code = R"(
2662     void target() {
2663       static int Foo;
2664       // [[p]]
2665     }
2666   )";
2667   runDataflow(Code,
2668               [](llvm::ArrayRef<
2669                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2670                      Results,
2671                  ASTContext &ASTCtx) {
2672                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2673                 const Environment &Env = Results[0].second.Env;
2674 
2675                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2676                 ASSERT_THAT(FooDecl, NotNull());
2677 
2678                 const StorageLocation *FooLoc =
2679                     Env.getStorageLocation(*FooDecl, SkipPast::None);
2680                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
2681 
2682                 const Value *FooVal = Env.getValue(*FooLoc);
2683                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
2684               });
2685 }
2686 
2687 TEST_F(TransferTest, StaticIntGroupVarDecl) {
2688   std::string Code = R"(
2689     void target() {
2690       static int Foo, Bar;
2691       (void)0;
2692       // [[p]]
2693     }
2694   )";
2695   runDataflow(Code,
2696               [](llvm::ArrayRef<
2697                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2698                      Results,
2699                  ASTContext &ASTCtx) {
2700                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2701                 const Environment &Env = Results[0].second.Env;
2702 
2703                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2704                 ASSERT_THAT(FooDecl, NotNull());
2705 
2706                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2707                 ASSERT_THAT(BarDecl, NotNull());
2708 
2709                 const StorageLocation *FooLoc =
2710                     Env.getStorageLocation(*FooDecl, SkipPast::None);
2711                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
2712 
2713                 const StorageLocation *BarLoc =
2714                     Env.getStorageLocation(*BarDecl, SkipPast::None);
2715                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2716 
2717                 const Value *FooVal = Env.getValue(*FooLoc);
2718                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
2719 
2720                 const Value *BarVal = Env.getValue(*BarLoc);
2721                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
2722 
2723                 EXPECT_NE(FooVal, BarVal);
2724               });
2725 }
2726 
2727 TEST_F(TransferTest, GlobalIntVarDecl) {
2728   std::string Code = R"(
2729     static int Foo;
2730 
2731     void target() {
2732       int Bar = Foo;
2733       int Baz = Foo;
2734       // [[p]]
2735     }
2736   )";
2737   runDataflow(Code,
2738               [](llvm::ArrayRef<
2739                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2740                      Results,
2741                  ASTContext &ASTCtx) {
2742                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2743                 const Environment &Env = Results[0].second.Env;
2744 
2745                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2746                 ASSERT_THAT(BarDecl, NotNull());
2747 
2748                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2749                 ASSERT_THAT(BazDecl, NotNull());
2750 
2751                 const Value *BarVal =
2752                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2753                 const Value *BazVal =
2754                     cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
2755                 EXPECT_EQ(BarVal, BazVal);
2756               });
2757 }
2758 
2759 TEST_F(TransferTest, StaticMemberIntVarDecl) {
2760   std::string Code = R"(
2761     struct A {
2762       static int Foo;
2763     };
2764 
2765     void target(A a) {
2766       int Bar = a.Foo;
2767       int Baz = a.Foo;
2768       // [[p]]
2769     }
2770   )";
2771   runDataflow(Code,
2772               [](llvm::ArrayRef<
2773                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2774                      Results,
2775                  ASTContext &ASTCtx) {
2776                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2777                 const Environment &Env = Results[0].second.Env;
2778 
2779                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2780                 ASSERT_THAT(BarDecl, NotNull());
2781 
2782                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2783                 ASSERT_THAT(BazDecl, NotNull());
2784 
2785                 const Value *BarVal =
2786                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2787                 const Value *BazVal =
2788                     cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
2789                 EXPECT_EQ(BarVal, BazVal);
2790               });
2791 }
2792 
2793 TEST_F(TransferTest, StaticMemberRefVarDecl) {
2794   std::string Code = R"(
2795     struct A {
2796       static int &Foo;
2797     };
2798 
2799     void target(A a) {
2800       int Bar = a.Foo;
2801       int Baz = a.Foo;
2802       // [[p]]
2803     }
2804   )";
2805   runDataflow(Code,
2806               [](llvm::ArrayRef<
2807                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2808                      Results,
2809                  ASTContext &ASTCtx) {
2810                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2811                 const Environment &Env = Results[0].second.Env;
2812 
2813                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2814                 ASSERT_THAT(BarDecl, NotNull());
2815 
2816                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2817                 ASSERT_THAT(BazDecl, NotNull());
2818 
2819                 const Value *BarVal =
2820                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2821                 const Value *BazVal =
2822                     cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
2823                 EXPECT_EQ(BarVal, BazVal);
2824               });
2825 }
2826 
2827 TEST_F(TransferTest, AssignMemberBeforeCopy) {
2828   std::string Code = R"(
2829     struct A {
2830       int Foo;
2831     };
2832 
2833     void target() {
2834       A A1;
2835       A A2;
2836       int Bar;
2837       A1.Foo = Bar;
2838       A2 = A1;
2839       // [[p]]
2840     }
2841   )";
2842   runDataflow(Code,
2843               [](llvm::ArrayRef<
2844                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2845                      Results,
2846                  ASTContext &ASTCtx) {
2847                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2848                 const Environment &Env = Results[0].second.Env;
2849 
2850                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2851                 ASSERT_THAT(FooDecl, NotNull());
2852 
2853                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2854                 ASSERT_THAT(BarDecl, NotNull());
2855 
2856                 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
2857                 ASSERT_THAT(A1Decl, NotNull());
2858 
2859                 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
2860                 ASSERT_THAT(A2Decl, NotNull());
2861 
2862                 const auto *BarVal =
2863                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2864 
2865                 const auto *A2Val =
2866                     cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None));
2867                 EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal);
2868               });
2869 }
2870 
2871 TEST_F(TransferTest, BooleanEquality) {
2872   std::string Code = R"(
2873     void target(bool Bar) {
2874       bool Foo = true;
2875       if (Bar == Foo) {
2876         (void)0;
2877         /*[[p-then]]*/
2878       } else {
2879         (void)0;
2880         /*[[p-else]]*/
2881       }
2882     }
2883   )";
2884   runDataflow(
2885       Code, [](llvm::ArrayRef<
2886                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2887                    Results,
2888                ASTContext &ASTCtx) {
2889         ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _)));
2890         const Environment &EnvElse = Results[0].second.Env;
2891         const Environment &EnvThen = Results[1].second.Env;
2892 
2893         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2894         ASSERT_THAT(BarDecl, NotNull());
2895 
2896         auto &BarValThen =
2897             *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None));
2898         EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen));
2899 
2900         auto &BarValElse =
2901             *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None));
2902         EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse));
2903       });
2904 }
2905 
2906 TEST_F(TransferTest, BooleanInequality) {
2907   std::string Code = R"(
2908     void target(bool Bar) {
2909       bool Foo = true;
2910       if (Bar != Foo) {
2911         (void)0;
2912         /*[[p-then]]*/
2913       } else {
2914         (void)0;
2915         /*[[p-else]]*/
2916       }
2917     }
2918   )";
2919   runDataflow(
2920       Code, [](llvm::ArrayRef<
2921                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2922                    Results,
2923                ASTContext &ASTCtx) {
2924         ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _)));
2925         const Environment &EnvElse = Results[0].second.Env;
2926         const Environment &EnvThen = Results[1].second.Env;
2927 
2928         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2929         ASSERT_THAT(BarDecl, NotNull());
2930 
2931         auto &BarValThen =
2932             *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None));
2933         EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen));
2934 
2935         auto &BarValElse =
2936             *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None));
2937         EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse));
2938       });
2939 }
2940 
2941 TEST_F(TransferTest, CorrelatedBranches) {
2942   std::string Code = R"(
2943     void target(bool B, bool C) {
2944       if (B) {
2945         return;
2946       }
2947       (void)0;
2948       /*[[p0]]*/
2949       if (C) {
2950         B = true;
2951         /*[[p1]]*/
2952       }
2953       if (B) {
2954         (void)0;
2955         /*[[p2]]*/
2956       }
2957     }
2958   )";
2959   runDataflow(
2960       Code, [](llvm::ArrayRef<
2961                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2962                    Results,
2963                ASTContext &ASTCtx) {
2964         ASSERT_THAT(Results, SizeIs(3));
2965 
2966         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
2967         ASSERT_THAT(CDecl, NotNull());
2968 
2969         {
2970           ASSERT_THAT(Results[2], Pair("p0", _));
2971           const Environment &Env = Results[2].second.Env;
2972           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
2973           ASSERT_THAT(BDecl, NotNull());
2974           auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl, SkipPast::None));
2975 
2976           EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal)));
2977         }
2978 
2979         {
2980           ASSERT_THAT(Results[1], Pair("p1", _));
2981           const Environment &Env = Results[1].second.Env;
2982           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
2983           EXPECT_TRUE(Env.flowConditionImplies(CVal));
2984         }
2985 
2986         {
2987           ASSERT_THAT(Results[0], Pair("p2", _));
2988           const Environment &Env = Results[0].second.Env;
2989           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
2990           EXPECT_TRUE(Env.flowConditionImplies(CVal));
2991         }
2992       });
2993 }
2994 
2995 TEST_F(TransferTest, LoopWithAssignmentConverges) {
2996   std::string Code = R"(
2997 
2998     bool &foo();
2999 
3000     void target() {
3001        do {
3002         bool Bar = foo();
3003         if (Bar) break;
3004         (void)Bar;
3005         /*[[p]]*/
3006       } while (true);
3007     }
3008   )";
3009   // The key property that we are verifying is implicit in `runDataflow` --
3010   // namely, that the analysis succeeds, rather than hitting the maximum number
3011   // of iterations.
3012   runDataflow(
3013       Code, [](llvm::ArrayRef<
3014                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3015                    Results,
3016                ASTContext &ASTCtx) {
3017         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3018         const Environment &Env = Results[0].second.Env;
3019 
3020         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3021         ASSERT_THAT(BarDecl, NotNull());
3022 
3023         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
3024         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3025       });
3026 }
3027 
3028 TEST_F(TransferTest, LoopWithReferenceAssignmentConverges) {
3029   std::string Code = R"(
3030 
3031     bool &foo();
3032 
3033     void target() {
3034        do {
3035         bool& Bar = foo();
3036         if (Bar) break;
3037         (void)Bar;
3038         /*[[p]]*/
3039       } while (true);
3040     }
3041   )";
3042   // The key property that we are verifying is implicit in `runDataflow` --
3043   // namely, that the analysis succeeds, rather than hitting the maximum number
3044   // of iterations.
3045   runDataflow(
3046       Code, [](llvm::ArrayRef<
3047                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3048                    Results,
3049                ASTContext &ASTCtx) {
3050         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3051         const Environment &Env = Results[0].second.Env;
3052 
3053         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3054         ASSERT_THAT(BarDecl, NotNull());
3055 
3056         auto &BarVal =
3057             *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::Reference));
3058         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3059       });
3060 }
3061 
3062 } // namespace
3063