xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision 2f93bbb9cd7c20ea1a273cf652d852d4b641f94a)
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     std::string Code = R"(
2473       void target(bool A, bool B, bool C, bool D) {
2474         bool Foo = ((A && B) && C) && D;
2475         // [[p]]
2476       }
2477     )";
2478     runDataflow(
2479         Code, [](llvm::ArrayRef<
2480                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2481                      Results,
2482                  ASTContext &ASTCtx) {
2483           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2484           const Environment &Env = Results[0].second.Env;
2485 
2486           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
2487           ASSERT_THAT(ADecl, NotNull());
2488 
2489           const auto *AVal =
2490               dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl, SkipPast::None));
2491           ASSERT_THAT(AVal, NotNull());
2492 
2493           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
2494           ASSERT_THAT(BDecl, NotNull());
2495 
2496           const auto *BVal =
2497               dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl, SkipPast::None));
2498           ASSERT_THAT(BVal, NotNull());
2499 
2500           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
2501           ASSERT_THAT(CDecl, NotNull());
2502 
2503           const auto *CVal =
2504               dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
2505           ASSERT_THAT(CVal, NotNull());
2506 
2507           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
2508           ASSERT_THAT(DDecl, NotNull());
2509 
2510           const auto *DVal =
2511               dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl, SkipPast::None));
2512           ASSERT_THAT(DVal, NotNull());
2513 
2514           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2515           ASSERT_THAT(FooDecl, NotNull());
2516 
2517           const auto *FooVal = dyn_cast_or_null<ConjunctionValue>(
2518               Env.getValue(*FooDecl, SkipPast::None));
2519           ASSERT_THAT(FooVal, NotNull());
2520 
2521           const auto &FooLeftSubVal =
2522               cast<ConjunctionValue>(FooVal->getLeftSubValue());
2523           const auto &FooLeftLeftSubVal =
2524               cast<ConjunctionValue>(FooLeftSubVal.getLeftSubValue());
2525           EXPECT_EQ(&FooLeftLeftSubVal.getLeftSubValue(), AVal);
2526           EXPECT_EQ(&FooLeftLeftSubVal.getRightSubValue(), BVal);
2527           EXPECT_EQ(&FooLeftSubVal.getRightSubValue(), CVal);
2528           EXPECT_EQ(&FooVal->getRightSubValue(), DVal);
2529         });
2530   }
2531 }
2532 
2533 TEST_F(TransferTest, AssignFromBoolNegation) {
2534   std::string Code = R"(
2535     void target() {
2536       bool Foo = true;
2537       bool Bar = !(Foo);
2538       // [[p]]
2539     }
2540   )";
2541   runDataflow(Code,
2542               [](llvm::ArrayRef<
2543                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2544                      Results,
2545                  ASTContext &ASTCtx) {
2546                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2547                 const Environment &Env = Results[0].second.Env;
2548 
2549                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2550                 ASSERT_THAT(FooDecl, NotNull());
2551 
2552                 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>(
2553                     Env.getValue(*FooDecl, SkipPast::None));
2554                 ASSERT_THAT(FooVal, NotNull());
2555 
2556                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2557                 ASSERT_THAT(BarDecl, NotNull());
2558 
2559                 const auto *BarVal = dyn_cast_or_null<NegationValue>(
2560                     Env.getValue(*BarDecl, SkipPast::None));
2561                 ASSERT_THAT(BarVal, NotNull());
2562 
2563                 EXPECT_EQ(&BarVal->getSubVal(), FooVal);
2564               });
2565 }
2566 
2567 TEST_F(TransferTest, BuiltinExpect) {
2568   std::string Code = R"(
2569     void target(long Foo) {
2570       long Bar = __builtin_expect(Foo, true);
2571       /*[[p]]*/
2572     }
2573   )";
2574   runDataflow(Code,
2575               [](llvm::ArrayRef<
2576                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2577                      Results,
2578                  ASTContext &ASTCtx) {
2579                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2580                 const auto &Env = Results[0].second.Env;
2581 
2582                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2583                 ASSERT_THAT(FooDecl, NotNull());
2584 
2585                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2586                 ASSERT_THAT(BarDecl, NotNull());
2587 
2588                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2589                           Env.getValue(*BarDecl, SkipPast::None));
2590               });
2591 }
2592 
2593 // `__builtin_expect` takes and returns a `long` argument, so other types
2594 // involve casts. This verifies that we identify the input and output in that
2595 // case.
2596 TEST_F(TransferTest, BuiltinExpectBoolArg) {
2597   std::string Code = R"(
2598     void target(bool Foo) {
2599       bool Bar = __builtin_expect(Foo, true);
2600       /*[[p]]*/
2601     }
2602   )";
2603   runDataflow(Code,
2604               [](llvm::ArrayRef<
2605                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2606                      Results,
2607                  ASTContext &ASTCtx) {
2608                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2609                 const auto &Env = Results[0].second.Env;
2610 
2611                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2612                 ASSERT_THAT(FooDecl, NotNull());
2613 
2614                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2615                 ASSERT_THAT(BarDecl, NotNull());
2616 
2617                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2618                           Env.getValue(*BarDecl, SkipPast::None));
2619               });
2620 }
2621 
2622 TEST_F(TransferTest, BuiltinUnreachable) {
2623   std::string Code = R"(
2624     void target(bool Foo) {
2625       bool Bar = false;
2626       if (Foo)
2627         Bar = Foo;
2628       else
2629         __builtin_unreachable();
2630       (void)0;
2631       /*[[p]]*/
2632     }
2633   )";
2634   runDataflow(Code,
2635               [](llvm::ArrayRef<
2636                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2637                      Results,
2638                  ASTContext &ASTCtx) {
2639                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2640                 const auto &Env = Results[0].second.Env;
2641 
2642                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2643                 ASSERT_THAT(FooDecl, NotNull());
2644 
2645                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2646                 ASSERT_THAT(BarDecl, NotNull());
2647 
2648                 // `__builtin_unreachable` promises that the code is
2649                 // unreachable, so the compiler treats the "then" branch as the
2650                 // only possible predecessor of this statement.
2651                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2652                           Env.getValue(*BarDecl, SkipPast::None));
2653               });
2654 }
2655 
2656 TEST_F(TransferTest, BuiltinTrap) {
2657   std::string Code = R"(
2658     void target(bool Foo) {
2659       bool Bar = false;
2660       if (Foo)
2661         Bar = Foo;
2662       else
2663         __builtin_trap();
2664       (void)0;
2665       /*[[p]]*/
2666     }
2667   )";
2668   runDataflow(Code,
2669               [](llvm::ArrayRef<
2670                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2671                      Results,
2672                  ASTContext &ASTCtx) {
2673                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2674                 const auto &Env = Results[0].second.Env;
2675 
2676                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2677                 ASSERT_THAT(FooDecl, NotNull());
2678 
2679                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2680                 ASSERT_THAT(BarDecl, NotNull());
2681 
2682                 // `__builtin_trap` ensures program termination, so only the
2683                 // "then" branch is a predecessor of this statement.
2684                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2685                           Env.getValue(*BarDecl, SkipPast::None));
2686               });
2687 }
2688 
2689 TEST_F(TransferTest, BuiltinDebugTrap) {
2690   std::string Code = R"(
2691     void target(bool Foo) {
2692       bool Bar = false;
2693       if (Foo)
2694         Bar = Foo;
2695       else
2696         __builtin_debugtrap();
2697       (void)0;
2698       /*[[p]]*/
2699     }
2700   )";
2701   runDataflow(Code,
2702               [](llvm::ArrayRef<
2703                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2704                      Results,
2705                  ASTContext &ASTCtx) {
2706                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2707                 const auto &Env = Results[0].second.Env;
2708 
2709                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2710                 ASSERT_THAT(FooDecl, NotNull());
2711 
2712                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2713                 ASSERT_THAT(BarDecl, NotNull());
2714 
2715                 // `__builtin_debugtrap` doesn't ensure program termination.
2716                 EXPECT_NE(Env.getValue(*FooDecl, SkipPast::None),
2717                           Env.getValue(*BarDecl, SkipPast::None));
2718               });
2719 }
2720 
2721 TEST_F(TransferTest, StaticIntSingleVarDecl) {
2722   std::string Code = R"(
2723     void target() {
2724       static int Foo;
2725       // [[p]]
2726     }
2727   )";
2728   runDataflow(Code,
2729               [](llvm::ArrayRef<
2730                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2731                      Results,
2732                  ASTContext &ASTCtx) {
2733                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2734                 const Environment &Env = Results[0].second.Env;
2735 
2736                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2737                 ASSERT_THAT(FooDecl, NotNull());
2738 
2739                 const StorageLocation *FooLoc =
2740                     Env.getStorageLocation(*FooDecl, SkipPast::None);
2741                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
2742 
2743                 const Value *FooVal = Env.getValue(*FooLoc);
2744                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
2745               });
2746 }
2747 
2748 TEST_F(TransferTest, StaticIntGroupVarDecl) {
2749   std::string Code = R"(
2750     void target() {
2751       static int Foo, Bar;
2752       (void)0;
2753       // [[p]]
2754     }
2755   )";
2756   runDataflow(Code,
2757               [](llvm::ArrayRef<
2758                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2759                      Results,
2760                  ASTContext &ASTCtx) {
2761                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2762                 const Environment &Env = Results[0].second.Env;
2763 
2764                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2765                 ASSERT_THAT(FooDecl, NotNull());
2766 
2767                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2768                 ASSERT_THAT(BarDecl, NotNull());
2769 
2770                 const StorageLocation *FooLoc =
2771                     Env.getStorageLocation(*FooDecl, SkipPast::None);
2772                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
2773 
2774                 const StorageLocation *BarLoc =
2775                     Env.getStorageLocation(*BarDecl, SkipPast::None);
2776                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2777 
2778                 const Value *FooVal = Env.getValue(*FooLoc);
2779                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
2780 
2781                 const Value *BarVal = Env.getValue(*BarLoc);
2782                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
2783 
2784                 EXPECT_NE(FooVal, BarVal);
2785               });
2786 }
2787 
2788 TEST_F(TransferTest, GlobalIntVarDecl) {
2789   std::string Code = R"(
2790     static int Foo;
2791 
2792     void target() {
2793       int Bar = Foo;
2794       int Baz = Foo;
2795       // [[p]]
2796     }
2797   )";
2798   runDataflow(Code,
2799               [](llvm::ArrayRef<
2800                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2801                      Results,
2802                  ASTContext &ASTCtx) {
2803                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2804                 const Environment &Env = Results[0].second.Env;
2805 
2806                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2807                 ASSERT_THAT(BarDecl, NotNull());
2808 
2809                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2810                 ASSERT_THAT(BazDecl, NotNull());
2811 
2812                 const Value *BarVal =
2813                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2814                 const Value *BazVal =
2815                     cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
2816                 EXPECT_EQ(BarVal, BazVal);
2817               });
2818 }
2819 
2820 TEST_F(TransferTest, StaticMemberIntVarDecl) {
2821   std::string Code = R"(
2822     struct A {
2823       static int Foo;
2824     };
2825 
2826     void target(A a) {
2827       int Bar = a.Foo;
2828       int Baz = a.Foo;
2829       // [[p]]
2830     }
2831   )";
2832   runDataflow(Code,
2833               [](llvm::ArrayRef<
2834                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2835                      Results,
2836                  ASTContext &ASTCtx) {
2837                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2838                 const Environment &Env = Results[0].second.Env;
2839 
2840                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2841                 ASSERT_THAT(BarDecl, NotNull());
2842 
2843                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2844                 ASSERT_THAT(BazDecl, NotNull());
2845 
2846                 const Value *BarVal =
2847                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2848                 const Value *BazVal =
2849                     cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
2850                 EXPECT_EQ(BarVal, BazVal);
2851               });
2852 }
2853 
2854 TEST_F(TransferTest, StaticMemberRefVarDecl) {
2855   std::string Code = R"(
2856     struct A {
2857       static int &Foo;
2858     };
2859 
2860     void target(A a) {
2861       int Bar = a.Foo;
2862       int Baz = a.Foo;
2863       // [[p]]
2864     }
2865   )";
2866   runDataflow(Code,
2867               [](llvm::ArrayRef<
2868                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2869                      Results,
2870                  ASTContext &ASTCtx) {
2871                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2872                 const Environment &Env = Results[0].second.Env;
2873 
2874                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2875                 ASSERT_THAT(BarDecl, NotNull());
2876 
2877                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2878                 ASSERT_THAT(BazDecl, NotNull());
2879 
2880                 const Value *BarVal =
2881                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2882                 const Value *BazVal =
2883                     cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
2884                 EXPECT_EQ(BarVal, BazVal);
2885               });
2886 }
2887 
2888 TEST_F(TransferTest, AssignMemberBeforeCopy) {
2889   std::string Code = R"(
2890     struct A {
2891       int Foo;
2892     };
2893 
2894     void target() {
2895       A A1;
2896       A A2;
2897       int Bar;
2898       A1.Foo = Bar;
2899       A2 = A1;
2900       // [[p]]
2901     }
2902   )";
2903   runDataflow(Code,
2904               [](llvm::ArrayRef<
2905                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2906                      Results,
2907                  ASTContext &ASTCtx) {
2908                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2909                 const Environment &Env = Results[0].second.Env;
2910 
2911                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2912                 ASSERT_THAT(FooDecl, NotNull());
2913 
2914                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2915                 ASSERT_THAT(BarDecl, NotNull());
2916 
2917                 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
2918                 ASSERT_THAT(A1Decl, NotNull());
2919 
2920                 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
2921                 ASSERT_THAT(A2Decl, NotNull());
2922 
2923                 const auto *BarVal =
2924                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2925 
2926                 const auto *A2Val =
2927                     cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None));
2928                 EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal);
2929               });
2930 }
2931 
2932 TEST_F(TransferTest, BooleanEquality) {
2933   std::string Code = R"(
2934     void target(bool Bar) {
2935       bool Foo = true;
2936       if (Bar == Foo) {
2937         (void)0;
2938         /*[[p-then]]*/
2939       } else {
2940         (void)0;
2941         /*[[p-else]]*/
2942       }
2943     }
2944   )";
2945   runDataflow(
2946       Code, [](llvm::ArrayRef<
2947                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2948                    Results,
2949                ASTContext &ASTCtx) {
2950         ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _)));
2951         const Environment &EnvElse = Results[0].second.Env;
2952         const Environment &EnvThen = Results[1].second.Env;
2953 
2954         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2955         ASSERT_THAT(BarDecl, NotNull());
2956 
2957         auto &BarValThen =
2958             *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None));
2959         EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen));
2960 
2961         auto &BarValElse =
2962             *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None));
2963         EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse));
2964       });
2965 }
2966 
2967 TEST_F(TransferTest, BooleanInequality) {
2968   std::string Code = R"(
2969     void target(bool Bar) {
2970       bool Foo = true;
2971       if (Bar != Foo) {
2972         (void)0;
2973         /*[[p-then]]*/
2974       } else {
2975         (void)0;
2976         /*[[p-else]]*/
2977       }
2978     }
2979   )";
2980   runDataflow(
2981       Code, [](llvm::ArrayRef<
2982                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2983                    Results,
2984                ASTContext &ASTCtx) {
2985         ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _)));
2986         const Environment &EnvElse = Results[0].second.Env;
2987         const Environment &EnvThen = Results[1].second.Env;
2988 
2989         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2990         ASSERT_THAT(BarDecl, NotNull());
2991 
2992         auto &BarValThen =
2993             *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None));
2994         EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen));
2995 
2996         auto &BarValElse =
2997             *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None));
2998         EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse));
2999       });
3000 }
3001 
3002 TEST_F(TransferTest, CorrelatedBranches) {
3003   std::string Code = R"(
3004     void target(bool B, bool C) {
3005       if (B) {
3006         return;
3007       }
3008       (void)0;
3009       /*[[p0]]*/
3010       if (C) {
3011         B = true;
3012         /*[[p1]]*/
3013       }
3014       if (B) {
3015         (void)0;
3016         /*[[p2]]*/
3017       }
3018     }
3019   )";
3020   runDataflow(
3021       Code, [](llvm::ArrayRef<
3022                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3023                    Results,
3024                ASTContext &ASTCtx) {
3025         ASSERT_THAT(Results, SizeIs(3));
3026 
3027         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3028         ASSERT_THAT(CDecl, NotNull());
3029 
3030         {
3031           ASSERT_THAT(Results[2], Pair("p0", _));
3032           const Environment &Env = Results[2].second.Env;
3033           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3034           ASSERT_THAT(BDecl, NotNull());
3035           auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl, SkipPast::None));
3036 
3037           EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal)));
3038         }
3039 
3040         {
3041           ASSERT_THAT(Results[1], Pair("p1", _));
3042           const Environment &Env = Results[1].second.Env;
3043           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
3044           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3045         }
3046 
3047         {
3048           ASSERT_THAT(Results[0], Pair("p2", _));
3049           const Environment &Env = Results[0].second.Env;
3050           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
3051           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3052         }
3053       });
3054 }
3055 
3056 TEST_F(TransferTest, LoopWithAssignmentConverges) {
3057   std::string Code = R"(
3058 
3059     bool &foo();
3060 
3061     void target() {
3062        do {
3063         bool Bar = foo();
3064         if (Bar) break;
3065         (void)Bar;
3066         /*[[p]]*/
3067       } while (true);
3068     }
3069   )";
3070   // The key property that we are verifying is implicit in `runDataflow` --
3071   // namely, that the analysis succeeds, rather than hitting the maximum number
3072   // of iterations.
3073   runDataflow(
3074       Code, [](llvm::ArrayRef<
3075                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3076                    Results,
3077                ASTContext &ASTCtx) {
3078         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3079         const Environment &Env = Results[0].second.Env;
3080 
3081         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3082         ASSERT_THAT(BarDecl, NotNull());
3083 
3084         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
3085         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3086       });
3087 }
3088 
3089 TEST_F(TransferTest, LoopWithReferenceAssignmentConverges) {
3090   std::string Code = R"(
3091 
3092     bool &foo();
3093 
3094     void target() {
3095        do {
3096         bool& Bar = foo();
3097         if (Bar) break;
3098         (void)Bar;
3099         /*[[p]]*/
3100       } while (true);
3101     }
3102   )";
3103   // The key property that we are verifying is implicit in `runDataflow` --
3104   // namely, that the analysis succeeds, rather than hitting the maximum number
3105   // of iterations.
3106   runDataflow(
3107       Code, [](llvm::ArrayRef<
3108                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3109                    Results,
3110                ASTContext &ASTCtx) {
3111         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3112         const Environment &Env = Results[0].second.Env;
3113 
3114         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3115         ASSERT_THAT(BarDecl, NotNull());
3116 
3117         auto &BarVal =
3118             *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::Reference));
3119         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3120       });
3121 }
3122 
3123 TEST_F(TransferTest, LoopWithStructReferenceAssignmentConverges) {
3124   std::string Code = R"(
3125     struct Lookup {
3126       int x;
3127     };
3128 
3129     void target(Lookup val, bool b) {
3130       const Lookup* l = nullptr;
3131       while (b) {
3132         l = &val;
3133         /*[[p-inner]]*/
3134       }
3135       (void)0;
3136       /*[[p-outer]]*/
3137     }
3138   )";
3139   // The key property that we are verifying is implicit in `runDataflow` --
3140   // namely, that the analysis succeeds, rather than hitting the maximum number
3141   // of iterations.
3142   runDataflow(
3143       Code, [](llvm::ArrayRef<
3144                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3145                    Results,
3146                ASTContext &ASTCtx) {
3147         ASSERT_THAT(Results,
3148                     ElementsAre(Pair("p-outer", _), Pair("p-inner", _)));
3149         const Environment &OuterEnv = Results[0].second.Env;
3150         const Environment &InnerEnv = Results[1].second.Env;
3151 
3152         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
3153         ASSERT_THAT(ValDecl, NotNull());
3154 
3155         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
3156         ASSERT_THAT(LDecl, NotNull());
3157 
3158         // Inner.
3159         auto *LVal = dyn_cast<IndirectionValue>(
3160             InnerEnv.getValue(*LDecl, SkipPast::None));
3161         ASSERT_THAT(LVal, NotNull());
3162 
3163         EXPECT_EQ(&LVal->getPointeeLoc(),
3164                   InnerEnv.getStorageLocation(*ValDecl, SkipPast::Reference));
3165 
3166         // Outer.
3167         LVal = dyn_cast<IndirectionValue>(
3168             OuterEnv.getValue(*LDecl, SkipPast::None));
3169         ASSERT_THAT(LVal, NotNull());
3170 
3171         // The loop body may not have been executed, so we should not conclude
3172         // that `l` points to `val`.
3173         EXPECT_NE(&LVal->getPointeeLoc(),
3174                   OuterEnv.getStorageLocation(*ValDecl, SkipPast::Reference));
3175 });
3176 }
3177 
3178 } // namespace
3179