xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision 01db10365e935ccca9dc2ed449b23319e170eea0)
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, ClassVarDecl) {
191   std::string Code = R"(
192     class A {
193       int Bar;
194     };
195 
196     void target() {
197       A Foo;
198       // [[p]]
199     }
200   )";
201   runDataflow(
202       Code, [](llvm::ArrayRef<
203                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
204                    Results,
205                ASTContext &ASTCtx) {
206         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
207         const Environment &Env = Results[0].second.Env;
208 
209         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
210         ASSERT_THAT(FooDecl, NotNull());
211 
212         ASSERT_TRUE(FooDecl->getType()->isClassType());
213         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
214 
215         FieldDecl *BarDecl = nullptr;
216         for (FieldDecl *Field : FooFields) {
217           if (Field->getNameAsString() == "Bar") {
218             BarDecl = Field;
219           } else {
220             FAIL() << "Unexpected field: " << Field->getNameAsString();
221           }
222         }
223         ASSERT_THAT(BarDecl, NotNull());
224 
225         const auto *FooLoc = cast<AggregateStorageLocation>(
226             Env.getStorageLocation(*FooDecl, SkipPast::None));
227         const auto *BarLoc =
228             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
229 
230         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
231         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
232         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
233       });
234 }
235 
236 TEST_F(TransferTest, ReferenceVarDecl) {
237   std::string Code = R"(
238     struct A {};
239 
240     A &getA();
241 
242     void target() {
243       A &Foo = getA();
244       // [[p]]
245     }
246   )";
247   runDataflow(
248       Code, [](llvm::ArrayRef<
249                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
250                    Results,
251                ASTContext &ASTCtx) {
252         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
253         const Environment &Env = Results[0].second.Env;
254 
255         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
256         ASSERT_THAT(FooDecl, NotNull());
257 
258         const StorageLocation *FooLoc =
259             Env.getStorageLocation(*FooDecl, SkipPast::None);
260         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
261 
262         const ReferenceValue *FooVal =
263             cast<ReferenceValue>(Env.getValue(*FooLoc));
264         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
265         EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc));
266 
267         const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
268         EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal));
269       });
270 }
271 
272 TEST_F(TransferTest, SelfReferentialReferenceVarDecl) {
273   std::string Code = R"(
274     struct A;
275 
276     struct B {};
277 
278     struct C {
279       A &FooRef;
280       A *FooPtr;
281       B &BazRef;
282       B *BazPtr;
283     };
284 
285     struct A {
286       C &Bar;
287     };
288 
289     A &getA();
290 
291     void target() {
292       A &Foo = getA();
293       // [[p]]
294     }
295   )";
296   runDataflow(Code, [](llvm::ArrayRef<std::pair<
297                            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     ASSERT_TRUE(FooDecl->getType()->isReferenceType());
307     ASSERT_TRUE(FooDecl->getType().getNonReferenceType()->isStructureType());
308     const auto FooFields =
309         FooDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields();
310 
311     FieldDecl *BarDecl = nullptr;
312     for (FieldDecl *Field : FooFields) {
313       if (Field->getNameAsString() == "Bar") {
314         BarDecl = Field;
315       } else {
316         FAIL() << "Unexpected field: " << Field->getNameAsString();
317       }
318     }
319     ASSERT_THAT(BarDecl, NotNull());
320 
321     ASSERT_TRUE(BarDecl->getType()->isReferenceType());
322     ASSERT_TRUE(BarDecl->getType().getNonReferenceType()->isStructureType());
323     const auto BarFields =
324         BarDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields();
325 
326     FieldDecl *FooRefDecl = nullptr;
327     FieldDecl *FooPtrDecl = nullptr;
328     FieldDecl *BazRefDecl = nullptr;
329     FieldDecl *BazPtrDecl = nullptr;
330     for (FieldDecl *Field : BarFields) {
331       if (Field->getNameAsString() == "FooRef") {
332         FooRefDecl = Field;
333       } else if (Field->getNameAsString() == "FooPtr") {
334         FooPtrDecl = Field;
335       } else if (Field->getNameAsString() == "BazRef") {
336         BazRefDecl = Field;
337       } else if (Field->getNameAsString() == "BazPtr") {
338         BazPtrDecl = Field;
339       } else {
340         FAIL() << "Unexpected field: " << Field->getNameAsString();
341       }
342     }
343     ASSERT_THAT(FooRefDecl, NotNull());
344     ASSERT_THAT(FooPtrDecl, NotNull());
345     ASSERT_THAT(BazRefDecl, NotNull());
346     ASSERT_THAT(BazPtrDecl, NotNull());
347 
348     const auto *FooLoc = cast<ScalarStorageLocation>(
349         Env.getStorageLocation(*FooDecl, SkipPast::None));
350     const auto *FooVal = cast<ReferenceValue>(Env.getValue(*FooLoc));
351     const auto *FooPointeeVal =
352         cast<StructValue>(Env.getValue(FooVal->getPointeeLoc()));
353 
354     const auto *BarVal =
355         cast<ReferenceValue>(FooPointeeVal->getChild(*BarDecl));
356     const auto *BarPointeeVal =
357         cast<StructValue>(Env.getValue(BarVal->getPointeeLoc()));
358 
359     const auto *FooRefVal =
360         cast<ReferenceValue>(BarPointeeVal->getChild(*FooRefDecl));
361     const StorageLocation &FooRefPointeeLoc = FooRefVal->getPointeeLoc();
362     EXPECT_THAT(Env.getValue(FooRefPointeeLoc), IsNull());
363 
364     const auto *FooPtrVal =
365         cast<PointerValue>(BarPointeeVal->getChild(*FooPtrDecl));
366     const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc();
367     EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull());
368 
369     const auto *BazRefVal =
370         cast<ReferenceValue>(BarPointeeVal->getChild(*BazRefDecl));
371     const StorageLocation &BazRefPointeeLoc = BazRefVal->getPointeeLoc();
372     EXPECT_THAT(Env.getValue(BazRefPointeeLoc), NotNull());
373 
374     const auto *BazPtrVal =
375         cast<PointerValue>(BarPointeeVal->getChild(*BazPtrDecl));
376     const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc();
377     EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull());
378   });
379 }
380 
381 TEST_F(TransferTest, PointerVarDecl) {
382   std::string Code = R"(
383     struct A {};
384 
385     A *getA();
386 
387     void target() {
388       A *Foo = getA();
389       // [[p]]
390     }
391   )";
392   runDataflow(
393       Code, [](llvm::ArrayRef<
394                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
395                    Results,
396                ASTContext &ASTCtx) {
397         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
398         const Environment &Env = Results[0].second.Env;
399 
400         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
401         ASSERT_THAT(FooDecl, NotNull());
402 
403         const StorageLocation *FooLoc =
404             Env.getStorageLocation(*FooDecl, SkipPast::None);
405         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
406 
407         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
408         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
409         EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc));
410 
411         const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
412         EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal));
413       });
414 }
415 
416 TEST_F(TransferTest, SelfReferentialPointerVarDecl) {
417   std::string Code = R"(
418     struct A;
419 
420     struct B {};
421 
422     struct C {
423       A &FooRef;
424       A *FooPtr;
425       B &BazRef;
426       B *BazPtr;
427     };
428 
429     struct A {
430       C *Bar;
431     };
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         ASSERT_TRUE(FooDecl->getType()->isPointerType());
452         ASSERT_TRUE(FooDecl->getType()
453                         ->getAs<PointerType>()
454                         ->getPointeeType()
455                         ->isStructureType());
456         const auto FooFields = FooDecl->getType()
457                                    ->getAs<PointerType>()
458                                    ->getPointeeType()
459                                    ->getAsRecordDecl()
460                                    ->fields();
461 
462         FieldDecl *BarDecl = nullptr;
463         for (FieldDecl *Field : FooFields) {
464           if (Field->getNameAsString() == "Bar") {
465             BarDecl = Field;
466           } else {
467             FAIL() << "Unexpected field: " << Field->getNameAsString();
468           }
469         }
470         ASSERT_THAT(BarDecl, NotNull());
471 
472         ASSERT_TRUE(BarDecl->getType()->isPointerType());
473         ASSERT_TRUE(BarDecl->getType()
474                         ->getAs<PointerType>()
475                         ->getPointeeType()
476                         ->isStructureType());
477         const auto BarFields = BarDecl->getType()
478                                    ->getAs<PointerType>()
479                                    ->getPointeeType()
480                                    ->getAsRecordDecl()
481                                    ->fields();
482 
483         FieldDecl *FooRefDecl = nullptr;
484         FieldDecl *FooPtrDecl = nullptr;
485         FieldDecl *BazRefDecl = nullptr;
486         FieldDecl *BazPtrDecl = nullptr;
487         for (FieldDecl *Field : BarFields) {
488           if (Field->getNameAsString() == "FooRef") {
489             FooRefDecl = Field;
490           } else if (Field->getNameAsString() == "FooPtr") {
491             FooPtrDecl = Field;
492           } else if (Field->getNameAsString() == "BazRef") {
493             BazRefDecl = Field;
494           } else if (Field->getNameAsString() == "BazPtr") {
495             BazPtrDecl = Field;
496           } else {
497             FAIL() << "Unexpected field: " << Field->getNameAsString();
498           }
499         }
500         ASSERT_THAT(FooRefDecl, NotNull());
501         ASSERT_THAT(FooPtrDecl, NotNull());
502         ASSERT_THAT(BazRefDecl, NotNull());
503         ASSERT_THAT(BazPtrDecl, NotNull());
504 
505         const auto *FooLoc = cast<ScalarStorageLocation>(
506             Env.getStorageLocation(*FooDecl, SkipPast::None));
507         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
508         const auto *FooPointeeVal =
509             cast<StructValue>(Env.getValue(FooVal->getPointeeLoc()));
510 
511         const auto *BarVal =
512             cast<PointerValue>(FooPointeeVal->getChild(*BarDecl));
513         const auto *BarPointeeVal =
514             cast<StructValue>(Env.getValue(BarVal->getPointeeLoc()));
515 
516         const auto *FooRefVal =
517             cast<ReferenceValue>(BarPointeeVal->getChild(*FooRefDecl));
518         const StorageLocation &FooRefPointeeLoc = FooRefVal->getPointeeLoc();
519         EXPECT_THAT(Env.getValue(FooRefPointeeLoc), IsNull());
520 
521         const auto *FooPtrVal =
522             cast<PointerValue>(BarPointeeVal->getChild(*FooPtrDecl));
523         const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc();
524         EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull());
525 
526         const auto *BazRefVal =
527             cast<ReferenceValue>(BarPointeeVal->getChild(*BazRefDecl));
528         const StorageLocation &BazRefPointeeLoc = BazRefVal->getPointeeLoc();
529         EXPECT_THAT(Env.getValue(BazRefPointeeLoc), NotNull());
530 
531         const auto *BazPtrVal =
532             cast<PointerValue>(BarPointeeVal->getChild(*BazPtrDecl));
533         const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc();
534         EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull());
535       });
536 }
537 
538 TEST_F(TransferTest, MultipleVarsDecl) {
539   std::string Code = R"(
540     void target() {
541       int Foo, Bar;
542       (void)0;
543       // [[p]]
544     }
545   )";
546   runDataflow(Code,
547               [](llvm::ArrayRef<
548                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
549                      Results,
550                  ASTContext &ASTCtx) {
551                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
552                 const Environment &Env = Results[0].second.Env;
553 
554                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
555                 ASSERT_THAT(FooDecl, NotNull());
556 
557                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
558                 ASSERT_THAT(BarDecl, NotNull());
559 
560                 const StorageLocation *FooLoc =
561                     Env.getStorageLocation(*FooDecl, SkipPast::None);
562                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
563 
564                 const StorageLocation *BarLoc =
565                     Env.getStorageLocation(*BarDecl, SkipPast::None);
566                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
567 
568                 const Value *FooVal = Env.getValue(*FooLoc);
569                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
570 
571                 const Value *BarVal = Env.getValue(*BarLoc);
572                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
573               });
574 }
575 
576 TEST_F(TransferTest, JoinVarDecl) {
577   std::string Code = R"(
578     void target(bool B) {
579       int Foo;
580       // [[p1]]
581       if (B) {
582         int Bar;
583         // [[p2]]
584       } else {
585         int Baz;
586         // [[p3]]
587       }
588       (void)0;
589       // [[p4]]
590     }
591   )";
592   runDataflow(Code, [](llvm::ArrayRef<std::pair<
593                            std::string, DataflowAnalysisState<NoopLattice>>>
594                            Results,
595                        ASTContext &ASTCtx) {
596     ASSERT_THAT(Results, ElementsAre(Pair("p4", _), Pair("p3", _),
597                                      Pair("p2", _), Pair("p1", _)));
598     const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
599     ASSERT_THAT(FooDecl, NotNull());
600 
601     const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
602     ASSERT_THAT(BarDecl, NotNull());
603 
604     const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
605     ASSERT_THAT(BazDecl, NotNull());
606 
607     const Environment &Env1 = Results[3].second.Env;
608     const StorageLocation *FooLoc =
609         Env1.getStorageLocation(*FooDecl, SkipPast::None);
610     EXPECT_THAT(FooLoc, NotNull());
611     EXPECT_THAT(Env1.getStorageLocation(*BarDecl, SkipPast::None), IsNull());
612     EXPECT_THAT(Env1.getStorageLocation(*BazDecl, SkipPast::None), IsNull());
613 
614     const Environment &Env2 = Results[2].second.Env;
615     EXPECT_EQ(Env2.getStorageLocation(*FooDecl, SkipPast::None), FooLoc);
616     EXPECT_THAT(Env2.getStorageLocation(*BarDecl, SkipPast::None), NotNull());
617     EXPECT_THAT(Env2.getStorageLocation(*BazDecl, SkipPast::None), IsNull());
618 
619     const Environment &Env3 = Results[1].second.Env;
620     EXPECT_EQ(Env3.getStorageLocation(*FooDecl, SkipPast::None), FooLoc);
621     EXPECT_THAT(Env3.getStorageLocation(*BarDecl, SkipPast::None), IsNull());
622     EXPECT_THAT(Env3.getStorageLocation(*BazDecl, SkipPast::None), NotNull());
623 
624     const Environment &Env4 = Results[0].second.Env;
625     EXPECT_EQ(Env4.getStorageLocation(*FooDecl, SkipPast::None), FooLoc);
626     EXPECT_THAT(Env4.getStorageLocation(*BarDecl, SkipPast::None), IsNull());
627     EXPECT_THAT(Env4.getStorageLocation(*BazDecl, SkipPast::None), IsNull());
628   });
629 }
630 
631 TEST_F(TransferTest, BinaryOperatorAssign) {
632   std::string Code = R"(
633     void target() {
634       int Foo;
635       int Bar;
636       (Bar) = (Foo);
637       // [[p]]
638     }
639   )";
640   runDataflow(Code,
641               [](llvm::ArrayRef<
642                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
643                      Results,
644                  ASTContext &ASTCtx) {
645                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
646                 const Environment &Env = Results[0].second.Env;
647 
648                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
649                 ASSERT_THAT(FooDecl, NotNull());
650 
651                 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None);
652                 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
653 
654                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
655                 ASSERT_THAT(BarDecl, NotNull());
656 
657                 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal);
658               });
659 }
660 
661 TEST_F(TransferTest, VarDeclInitAssign) {
662   std::string Code = R"(
663     void target() {
664       int Foo;
665       int Bar = Foo;
666       // [[p]]
667     }
668   )";
669   runDataflow(Code,
670               [](llvm::ArrayRef<
671                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
672                      Results,
673                  ASTContext &ASTCtx) {
674                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
675                 const Environment &Env = Results[0].second.Env;
676 
677                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
678                 ASSERT_THAT(FooDecl, NotNull());
679 
680                 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None);
681                 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
682 
683                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
684                 ASSERT_THAT(BarDecl, NotNull());
685 
686                 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal);
687               });
688 }
689 
690 TEST_F(TransferTest, VarDeclInitAssignChained) {
691   std::string Code = R"(
692     void target() {
693       int Foo;
694       int Bar;
695       int Baz = (Bar = Foo);
696       // [[p]]
697     }
698   )";
699   runDataflow(Code,
700               [](llvm::ArrayRef<
701                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
702                      Results,
703                  ASTContext &ASTCtx) {
704                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
705                 const Environment &Env = Results[0].second.Env;
706 
707                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
708                 ASSERT_THAT(FooDecl, NotNull());
709 
710                 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None);
711                 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
712 
713                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
714                 ASSERT_THAT(BarDecl, NotNull());
715 
716                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
717                 ASSERT_THAT(BazDecl, NotNull());
718 
719                 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal);
720                 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), FooVal);
721               });
722 }
723 
724 TEST_F(TransferTest, VarDeclInitAssignPtrDeref) {
725   std::string Code = R"(
726     void target() {
727       int Foo;
728       int *Bar;
729       *(Bar) = Foo;
730       int Baz = *(Bar);
731       // [[p]]
732     }
733   )";
734   runDataflow(Code,
735               [](llvm::ArrayRef<
736                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
737                      Results,
738                  ASTContext &ASTCtx) {
739                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
740                 const Environment &Env = Results[0].second.Env;
741 
742                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
743                 ASSERT_THAT(FooDecl, NotNull());
744 
745                 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None);
746                 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
747 
748                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
749                 ASSERT_THAT(BarDecl, NotNull());
750 
751                 const auto *BarVal =
752                     cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
753                 EXPECT_EQ(Env.getValue(BarVal->getPointeeLoc()), FooVal);
754 
755                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
756                 ASSERT_THAT(BazDecl, NotNull());
757 
758                 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), FooVal);
759               });
760 }
761 
762 TEST_F(TransferTest, AssignToAndFromReference) {
763   std::string Code = R"(
764     void target() {
765       int Foo;
766       int Bar;
767       int &Baz = Foo;
768       // [[p1]]
769       Baz = Bar;
770       int Qux = Baz;
771       int &Quux = Baz;
772       // [[p2]]
773     }
774   )";
775   runDataflow(
776       Code, [](llvm::ArrayRef<
777                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
778                    Results,
779                ASTContext &ASTCtx) {
780         ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
781         const Environment &Env1 = Results[0].second.Env;
782         const Environment &Env2 = Results[1].second.Env;
783 
784         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
785         ASSERT_THAT(FooDecl, NotNull());
786 
787         const Value *FooVal = Env1.getValue(*FooDecl, SkipPast::None);
788         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
789 
790         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
791         ASSERT_THAT(BarDecl, NotNull());
792 
793         const Value *BarVal = Env1.getValue(*BarDecl, SkipPast::None);
794         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
795 
796         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
797         ASSERT_THAT(BazDecl, NotNull());
798 
799         EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), FooVal);
800 
801         EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BarVal);
802         EXPECT_EQ(Env2.getValue(*FooDecl, SkipPast::None), BarVal);
803 
804         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
805         ASSERT_THAT(QuxDecl, NotNull());
806         EXPECT_EQ(Env2.getValue(*QuxDecl, SkipPast::None), BarVal);
807 
808         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
809         ASSERT_THAT(QuuxDecl, NotNull());
810         EXPECT_EQ(Env2.getValue(*QuuxDecl, SkipPast::Reference), BarVal);
811       });
812 }
813 
814 TEST_F(TransferTest, MultipleParamDecls) {
815   std::string Code = R"(
816     void target(int Foo, int Bar) {
817       (void)0;
818       // [[p]]
819     }
820   )";
821   runDataflow(Code,
822               [](llvm::ArrayRef<
823                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
824                      Results,
825                  ASTContext &ASTCtx) {
826                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
827                 const Environment &Env = Results[0].second.Env;
828 
829                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
830                 ASSERT_THAT(FooDecl, NotNull());
831 
832                 const StorageLocation *FooLoc =
833                     Env.getStorageLocation(*FooDecl, SkipPast::None);
834                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
835 
836                 const Value *FooVal = Env.getValue(*FooLoc);
837                 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
838 
839                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
840                 ASSERT_THAT(BarDecl, NotNull());
841 
842                 const StorageLocation *BarLoc =
843                     Env.getStorageLocation(*BarDecl, SkipPast::None);
844                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
845 
846                 const Value *BarVal = Env.getValue(*BarLoc);
847                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
848               });
849 }
850 
851 TEST_F(TransferTest, StructParamDecl) {
852   std::string Code = R"(
853     struct A {
854       int Bar;
855     };
856 
857     void target(A Foo) {
858       (void)0;
859       // [[p]]
860     }
861   )";
862   runDataflow(
863       Code, [](llvm::ArrayRef<
864                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
865                    Results,
866                ASTContext &ASTCtx) {
867         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
868         const Environment &Env = Results[0].second.Env;
869 
870         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
871         ASSERT_THAT(FooDecl, NotNull());
872 
873         ASSERT_TRUE(FooDecl->getType()->isStructureType());
874         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
875 
876         FieldDecl *BarDecl = nullptr;
877         for (FieldDecl *Field : FooFields) {
878           if (Field->getNameAsString() == "Bar") {
879             BarDecl = Field;
880           } else {
881             FAIL() << "Unexpected field: " << Field->getNameAsString();
882           }
883         }
884         ASSERT_THAT(BarDecl, NotNull());
885 
886         const auto *FooLoc = cast<AggregateStorageLocation>(
887             Env.getStorageLocation(*FooDecl, SkipPast::None));
888         const auto *BarLoc =
889             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
890 
891         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
892         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
893         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
894       });
895 }
896 
897 TEST_F(TransferTest, ReferenceParamDecl) {
898   std::string Code = R"(
899     struct A {};
900 
901     void target(A &Foo) {
902       (void)0;
903       // [[p]]
904     }
905   )";
906   runDataflow(Code,
907               [](llvm::ArrayRef<
908                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
909                      Results,
910                  ASTContext &ASTCtx) {
911                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
912                 const Environment &Env = Results[0].second.Env;
913 
914                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
915                 ASSERT_THAT(FooDecl, NotNull());
916 
917                 const StorageLocation *FooLoc =
918                     Env.getStorageLocation(*FooDecl, SkipPast::None);
919                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
920 
921                 const ReferenceValue *FooVal =
922                     dyn_cast<ReferenceValue>(Env.getValue(*FooLoc));
923                 ASSERT_THAT(FooVal, NotNull());
924 
925                 const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
926                 EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc));
927 
928                 const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
929                 EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal));
930               });
931 }
932 
933 TEST_F(TransferTest, PointerParamDecl) {
934   std::string Code = R"(
935     struct A {};
936 
937     void target(A *Foo) {
938       (void)0;
939       // [[p]]
940     }
941   )";
942   runDataflow(
943       Code, [](llvm::ArrayRef<
944                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
945                    Results,
946                ASTContext &ASTCtx) {
947         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
948         const Environment &Env = Results[0].second.Env;
949 
950         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
951         ASSERT_THAT(FooDecl, NotNull());
952 
953         const StorageLocation *FooLoc =
954             Env.getStorageLocation(*FooDecl, SkipPast::None);
955         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
956 
957         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
958         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
959         EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc));
960 
961         const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
962         EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal));
963       });
964 }
965 
966 TEST_F(TransferTest, StructMember) {
967   std::string Code = R"(
968     struct A {
969       int Bar;
970     };
971 
972     void target(A Foo) {
973       int Baz = Foo.Bar;
974       // [[p]]
975     }
976   )";
977   runDataflow(
978       Code, [](llvm::ArrayRef<
979                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
980                    Results,
981                ASTContext &ASTCtx) {
982         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
983         const Environment &Env = Results[0].second.Env;
984 
985         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
986         ASSERT_THAT(FooDecl, NotNull());
987 
988         ASSERT_TRUE(FooDecl->getType()->isStructureType());
989         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
990 
991         FieldDecl *BarDecl = nullptr;
992         for (FieldDecl *Field : FooFields) {
993           if (Field->getNameAsString() == "Bar") {
994             BarDecl = Field;
995           } else {
996             FAIL() << "Unexpected field: " << Field->getNameAsString();
997           }
998         }
999         ASSERT_THAT(BarDecl, NotNull());
1000 
1001         const auto *FooLoc = cast<AggregateStorageLocation>(
1002             Env.getStorageLocation(*FooDecl, SkipPast::None));
1003         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1004         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1005 
1006         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1007         ASSERT_THAT(BazDecl, NotNull());
1008 
1009         EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal);
1010       });
1011 }
1012 
1013 TEST_F(TransferTest, DerivedBaseMemberClass) {
1014   std::string Code = R"(
1015     class A {
1016       int ADefault;
1017     protected:
1018       int AProtected;
1019     private:
1020       int APrivate;
1021     public:
1022       int APublic;
1023     };
1024 
1025     class B : public A {
1026       int BDefault;
1027     protected:
1028       int BProtected;
1029     private:
1030       int BPrivate;
1031     };
1032 
1033     void target() {
1034       B Foo;
1035       // [[p]]
1036     }
1037   )";
1038   runDataflow(
1039       Code, [](llvm::ArrayRef<
1040                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1041                    Results,
1042                ASTContext &ASTCtx) {
1043         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1044         const Environment &Env = Results[0].second.Env;
1045 
1046         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1047         ASSERT_THAT(FooDecl, NotNull());
1048         ASSERT_TRUE(FooDecl->getType()->isRecordType());
1049 
1050         // Derived-class fields.
1051         const FieldDecl *BDefaultDecl = nullptr;
1052         const FieldDecl *BProtectedDecl = nullptr;
1053         const FieldDecl *BPrivateDecl = nullptr;
1054         for (const FieldDecl *Field :
1055              FooDecl->getType()->getAsRecordDecl()->fields()) {
1056           if (Field->getNameAsString() == "BDefault") {
1057             BDefaultDecl = Field;
1058           } else if (Field->getNameAsString() == "BProtected") {
1059             BProtectedDecl = Field;
1060           } else if (Field->getNameAsString() == "BPrivate") {
1061             BPrivateDecl = Field;
1062           } else {
1063             FAIL() << "Unexpected field: " << Field->getNameAsString();
1064           }
1065         }
1066         ASSERT_THAT(BDefaultDecl, NotNull());
1067         ASSERT_THAT(BProtectedDecl, NotNull());
1068         ASSERT_THAT(BPrivateDecl, NotNull());
1069 
1070         // Base-class fields.
1071         const FieldDecl *ADefaultDecl = nullptr;
1072         const FieldDecl *APrivateDecl = nullptr;
1073         const FieldDecl *AProtectedDecl = nullptr;
1074         const FieldDecl *APublicDecl = nullptr;
1075         for (const clang::CXXBaseSpecifier &Base :
1076              FooDecl->getType()->getAsCXXRecordDecl()->bases()) {
1077           QualType BaseType = Base.getType();
1078           ASSERT_TRUE(BaseType->isRecordType());
1079           for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) {
1080             if (Field->getNameAsString() == "ADefault") {
1081               ADefaultDecl = Field;
1082             } else if (Field->getNameAsString() == "AProtected") {
1083               AProtectedDecl = Field;
1084             } else if (Field->getNameAsString() == "APrivate") {
1085               APrivateDecl = Field;
1086             } else if (Field->getNameAsString() == "APublic") {
1087               APublicDecl = Field;
1088             } else {
1089               FAIL() << "Unexpected field: " << Field->getNameAsString();
1090             }
1091           }
1092         }
1093         ASSERT_THAT(ADefaultDecl, NotNull());
1094         ASSERT_THAT(AProtectedDecl, NotNull());
1095         ASSERT_THAT(APrivateDecl, NotNull());
1096         ASSERT_THAT(APublicDecl, NotNull());
1097 
1098         const auto &FooLoc = *cast<AggregateStorageLocation>(
1099             Env.getStorageLocation(*FooDecl, SkipPast::None));
1100         const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc));
1101 
1102         // Note: we can't test presence of children in `FooLoc`, because
1103         // `getChild` requires its argument be present (or fails an assert). So,
1104         // we limit to testing presence in `FooVal` and coherence between the
1105         // two.
1106 
1107         // Base-class fields.
1108         EXPECT_THAT(FooVal.getChild(*ADefaultDecl), IsNull());
1109         EXPECT_THAT(FooVal.getChild(*APrivateDecl), IsNull());
1110 
1111         EXPECT_THAT(FooVal.getChild(*AProtectedDecl), NotNull());
1112         EXPECT_EQ(Env.getValue(FooLoc.getChild(*APublicDecl)),
1113                   FooVal.getChild(*APublicDecl));
1114         EXPECT_THAT(FooVal.getChild(*APublicDecl), NotNull());
1115         EXPECT_EQ(Env.getValue(FooLoc.getChild(*AProtectedDecl)),
1116                   FooVal.getChild(*AProtectedDecl));
1117 
1118         // Derived-class fields.
1119         EXPECT_THAT(FooVal.getChild(*BDefaultDecl), NotNull());
1120         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BDefaultDecl)),
1121                   FooVal.getChild(*BDefaultDecl));
1122         EXPECT_THAT(FooVal.getChild(*BProtectedDecl), NotNull());
1123         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BProtectedDecl)),
1124                   FooVal.getChild(*BProtectedDecl));
1125         EXPECT_THAT(FooVal.getChild(*BPrivateDecl), NotNull());
1126         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BPrivateDecl)),
1127                   FooVal.getChild(*BPrivateDecl));
1128       });
1129 }
1130 
1131 TEST_F(TransferTest, DerivedBaseMemberStructDefault) {
1132   std::string Code = R"(
1133     struct A {
1134       int Bar;
1135     };
1136     struct B : public A {
1137     };
1138 
1139     void target() {
1140       B Foo;
1141       // [[p]]
1142     }
1143   )";
1144   runDataflow(
1145       Code, [](llvm::ArrayRef<
1146                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1147                    Results,
1148                ASTContext &ASTCtx) {
1149         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1150         const Environment &Env = Results[0].second.Env;
1151 
1152         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1153         ASSERT_THAT(FooDecl, NotNull());
1154 
1155         ASSERT_TRUE(FooDecl->getType()->isRecordType());
1156         const FieldDecl *BarDecl = nullptr;
1157         for (const clang::CXXBaseSpecifier &Base :
1158              FooDecl->getType()->getAsCXXRecordDecl()->bases()) {
1159           QualType BaseType = Base.getType();
1160           ASSERT_TRUE(BaseType->isStructureType());
1161 
1162           for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) {
1163             if (Field->getNameAsString() == "Bar") {
1164               BarDecl = Field;
1165             } else {
1166               FAIL() << "Unexpected field: " << Field->getNameAsString();
1167             }
1168           }
1169         }
1170         ASSERT_THAT(BarDecl, NotNull());
1171 
1172         const auto &FooLoc = *cast<AggregateStorageLocation>(
1173             Env.getStorageLocation(*FooDecl, SkipPast::None));
1174         const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc));
1175         EXPECT_THAT(FooVal.getChild(*BarDecl), NotNull());
1176         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BarDecl)),
1177                   FooVal.getChild(*BarDecl));
1178       });
1179 }
1180 
1181 TEST_F(TransferTest, ClassMember) {
1182   std::string Code = R"(
1183     class A {
1184     public:
1185       int Bar;
1186     };
1187 
1188     void target(A Foo) {
1189       int Baz = Foo.Bar;
1190       // [[p]]
1191     }
1192   )";
1193   runDataflow(
1194       Code, [](llvm::ArrayRef<
1195                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1196                    Results,
1197                ASTContext &ASTCtx) {
1198         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1199         const Environment &Env = Results[0].second.Env;
1200 
1201         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1202         ASSERT_THAT(FooDecl, NotNull());
1203 
1204         ASSERT_TRUE(FooDecl->getType()->isClassType());
1205         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1206 
1207         FieldDecl *BarDecl = nullptr;
1208         for (FieldDecl *Field : FooFields) {
1209           if (Field->getNameAsString() == "Bar") {
1210             BarDecl = Field;
1211           } else {
1212             FAIL() << "Unexpected field: " << Field->getNameAsString();
1213           }
1214         }
1215         ASSERT_THAT(BarDecl, NotNull());
1216 
1217         const auto *FooLoc = cast<AggregateStorageLocation>(
1218             Env.getStorageLocation(*FooDecl, SkipPast::None));
1219         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1220         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1221 
1222         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1223         ASSERT_THAT(BazDecl, NotNull());
1224 
1225         EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal);
1226       });
1227 }
1228 
1229 TEST_F(TransferTest, ReferenceMember) {
1230   std::string Code = R"(
1231     struct A {
1232       int &Bar;
1233     };
1234 
1235     void target(A Foo) {
1236       int Baz = Foo.Bar;
1237       // [[p]]
1238     }
1239   )";
1240   runDataflow(
1241       Code, [](llvm::ArrayRef<
1242                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1243                    Results,
1244                ASTContext &ASTCtx) {
1245         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1246         const Environment &Env = Results[0].second.Env;
1247 
1248         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1249         ASSERT_THAT(FooDecl, NotNull());
1250 
1251         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1252         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1253 
1254         FieldDecl *BarDecl = nullptr;
1255         for (FieldDecl *Field : FooFields) {
1256           if (Field->getNameAsString() == "Bar") {
1257             BarDecl = Field;
1258           } else {
1259             FAIL() << "Unexpected field: " << Field->getNameAsString();
1260           }
1261         }
1262         ASSERT_THAT(BarDecl, NotNull());
1263 
1264         const auto *FooLoc = cast<AggregateStorageLocation>(
1265             Env.getStorageLocation(*FooDecl, SkipPast::None));
1266         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1267         const auto *BarVal = cast<ReferenceValue>(FooVal->getChild(*BarDecl));
1268         const auto *BarPointeeVal =
1269             cast<IntegerValue>(Env.getValue(BarVal->getPointeeLoc()));
1270 
1271         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1272         ASSERT_THAT(BazDecl, NotNull());
1273 
1274         EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarPointeeVal);
1275       });
1276 }
1277 
1278 TEST_F(TransferTest, StructThisMember) {
1279   std::string Code = R"(
1280     struct A {
1281       int Bar;
1282 
1283       struct B {
1284         int Baz;
1285       };
1286 
1287       B Qux;
1288 
1289       void target() {
1290         int Foo = Bar;
1291         int Quux = Qux.Baz;
1292         // [[p]]
1293       }
1294     };
1295   )";
1296   runDataflow(
1297       Code, [](llvm::ArrayRef<
1298                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1299                    Results,
1300                ASTContext &ASTCtx) {
1301         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1302         const Environment &Env = Results[0].second.Env;
1303 
1304         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1305             Env.getThisPointeeStorageLocation());
1306         ASSERT_THAT(ThisLoc, NotNull());
1307 
1308         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1309         ASSERT_THAT(BarDecl, NotNull());
1310 
1311         const auto *BarLoc =
1312             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1313         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1314 
1315         const Value *BarVal = Env.getValue(*BarLoc);
1316         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1317 
1318         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1319         ASSERT_THAT(FooDecl, NotNull());
1320         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1321 
1322         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1323         ASSERT_THAT(QuxDecl, NotNull());
1324 
1325         ASSERT_TRUE(QuxDecl->getType()->isStructureType());
1326         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1327 
1328         FieldDecl *BazDecl = nullptr;
1329         for (FieldDecl *Field : QuxFields) {
1330           if (Field->getNameAsString() == "Baz") {
1331             BazDecl = Field;
1332           } else {
1333             FAIL() << "Unexpected field: " << Field->getNameAsString();
1334           }
1335         }
1336         ASSERT_THAT(BazDecl, NotNull());
1337 
1338         const auto *QuxLoc =
1339             cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl));
1340         const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc));
1341         ASSERT_THAT(QuxVal, NotNull());
1342 
1343         const auto *BazLoc =
1344             cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl));
1345         const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl));
1346         EXPECT_EQ(Env.getValue(*BazLoc), BazVal);
1347 
1348         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1349         ASSERT_THAT(QuuxDecl, NotNull());
1350         EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal);
1351       });
1352 }
1353 
1354 TEST_F(TransferTest, ClassThisMember) {
1355   std::string Code = R"(
1356     class A {
1357       int Bar;
1358 
1359       class B {
1360       public:
1361         int Baz;
1362       };
1363 
1364       B Qux;
1365 
1366       void target() {
1367         int Foo = Bar;
1368         int Quux = Qux.Baz;
1369         // [[p]]
1370       }
1371     };
1372   )";
1373   runDataflow(
1374       Code, [](llvm::ArrayRef<
1375                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1376                    Results,
1377                ASTContext &ASTCtx) {
1378         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1379         const Environment &Env = Results[0].second.Env;
1380 
1381         const auto *ThisLoc =
1382             cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation());
1383 
1384         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1385         ASSERT_THAT(BarDecl, NotNull());
1386 
1387         const auto *BarLoc =
1388             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1389         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1390 
1391         const Value *BarVal = Env.getValue(*BarLoc);
1392         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1393 
1394         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1395         ASSERT_THAT(FooDecl, NotNull());
1396         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1397 
1398         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1399         ASSERT_THAT(QuxDecl, NotNull());
1400 
1401         ASSERT_TRUE(QuxDecl->getType()->isClassType());
1402         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1403 
1404         FieldDecl *BazDecl = nullptr;
1405         for (FieldDecl *Field : QuxFields) {
1406           if (Field->getNameAsString() == "Baz") {
1407             BazDecl = Field;
1408           } else {
1409             FAIL() << "Unexpected field: " << Field->getNameAsString();
1410           }
1411         }
1412         ASSERT_THAT(BazDecl, NotNull());
1413 
1414         const auto *QuxLoc =
1415             cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl));
1416         const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc));
1417         ASSERT_THAT(QuxVal, NotNull());
1418 
1419         const auto *BazLoc =
1420             cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl));
1421         const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl));
1422         EXPECT_EQ(Env.getValue(*BazLoc), BazVal);
1423 
1424         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1425         ASSERT_THAT(QuuxDecl, NotNull());
1426         EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal);
1427       });
1428 }
1429 
1430 TEST_F(TransferTest, ConstructorInitializer) {
1431   std::string Code = R"(
1432     struct target {
1433       int Bar;
1434 
1435       target(int Foo) : Bar(Foo) {
1436         int Qux = Bar;
1437         // [[p]]
1438       }
1439     };
1440   )";
1441   runDataflow(Code,
1442               [](llvm::ArrayRef<
1443                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1444                      Results,
1445                  ASTContext &ASTCtx) {
1446                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1447                 const Environment &Env = Results[0].second.Env;
1448 
1449                 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1450                     Env.getThisPointeeStorageLocation());
1451                 ASSERT_THAT(ThisLoc, NotNull());
1452 
1453                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1454                 ASSERT_THAT(FooDecl, NotNull());
1455 
1456                 const auto *FooVal =
1457                     cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None));
1458 
1459                 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1460                 ASSERT_THAT(QuxDecl, NotNull());
1461                 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal);
1462               });
1463 }
1464 
1465 TEST_F(TransferTest, DefaultInitializer) {
1466   std::string Code = R"(
1467     struct target {
1468       int Bar;
1469       int Baz = Bar;
1470 
1471       target(int Foo) : Bar(Foo) {
1472         int Qux = Baz;
1473         // [[p]]
1474       }
1475     };
1476   )";
1477   runDataflow(Code,
1478               [](llvm::ArrayRef<
1479                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1480                      Results,
1481                  ASTContext &ASTCtx) {
1482                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1483                 const Environment &Env = Results[0].second.Env;
1484 
1485                 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1486                     Env.getThisPointeeStorageLocation());
1487                 ASSERT_THAT(ThisLoc, NotNull());
1488 
1489                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1490                 ASSERT_THAT(FooDecl, NotNull());
1491 
1492                 const auto *FooVal =
1493                     cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None));
1494 
1495                 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1496                 ASSERT_THAT(QuxDecl, NotNull());
1497                 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal);
1498               });
1499 }
1500 
1501 TEST_F(TransferTest, DefaultInitializerReference) {
1502   std::string Code = R"(
1503     struct target {
1504       int &Bar;
1505       int &Baz = Bar;
1506 
1507       target(int &Foo) : Bar(Foo) {
1508         int &Qux = Baz;
1509         // [[p]]
1510       }
1511     };
1512   )";
1513   runDataflow(
1514       Code, [](llvm::ArrayRef<
1515                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1516                    Results,
1517                ASTContext &ASTCtx) {
1518         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1519         const Environment &Env = Results[0].second.Env;
1520 
1521         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1522             Env.getThisPointeeStorageLocation());
1523         ASSERT_THAT(ThisLoc, NotNull());
1524 
1525         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1526         ASSERT_THAT(FooDecl, NotNull());
1527 
1528         const auto *FooVal =
1529             cast<ReferenceValue>(Env.getValue(*FooDecl, SkipPast::None));
1530 
1531         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1532         ASSERT_THAT(QuxDecl, NotNull());
1533 
1534         const auto *QuxVal =
1535             cast<ReferenceValue>(Env.getValue(*QuxDecl, SkipPast::None));
1536         EXPECT_EQ(&QuxVal->getPointeeLoc(), &FooVal->getPointeeLoc());
1537       });
1538 }
1539 
1540 TEST_F(TransferTest, TemporaryObject) {
1541   std::string Code = R"(
1542     struct A {
1543       int Bar;
1544     };
1545 
1546     void target() {
1547       A Foo = A();
1548       // [[p]]
1549     }
1550   )";
1551   runDataflow(
1552       Code, [](llvm::ArrayRef<
1553                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1554                    Results,
1555                ASTContext &ASTCtx) {
1556         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1557         const Environment &Env = Results[0].second.Env;
1558 
1559         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1560         ASSERT_THAT(FooDecl, NotNull());
1561 
1562         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1563         ASSERT_THAT(BarDecl, NotNull());
1564 
1565         const auto *FooLoc = cast<AggregateStorageLocation>(
1566             Env.getStorageLocation(*FooDecl, SkipPast::None));
1567         const auto *BarLoc =
1568             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
1569 
1570         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1571         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1572         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
1573       });
1574 }
1575 
1576 TEST_F(TransferTest, ElidableConstructor) {
1577   // This test is effectively the same as TransferTest.TemporaryObject, but
1578   // the code is compiled as C++ 14.
1579   std::string Code = R"(
1580     struct A {
1581       int Bar;
1582     };
1583 
1584     void target() {
1585       A Foo = A();
1586       // [[p]]
1587     }
1588   )";
1589   runDataflow(
1590       Code,
1591       [](llvm::ArrayRef<
1592              std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1593              Results,
1594          ASTContext &ASTCtx) {
1595         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1596         const Environment &Env = Results[0].second.Env;
1597 
1598         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1599         ASSERT_THAT(FooDecl, NotNull());
1600 
1601         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1602         ASSERT_THAT(BarDecl, NotNull());
1603 
1604         const auto *FooLoc = cast<AggregateStorageLocation>(
1605             Env.getStorageLocation(*FooDecl, SkipPast::None));
1606         const auto *BarLoc =
1607             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
1608 
1609         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1610         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1611         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
1612       },
1613       LangStandard::lang_cxx14);
1614 }
1615 
1616 TEST_F(TransferTest, AssignmentOperator) {
1617   std::string Code = R"(
1618     struct A {
1619       int Baz;
1620     };
1621 
1622     void target() {
1623       A Foo;
1624       A Bar;
1625       // [[p1]]
1626       Foo = Bar;
1627       // [[p2]]
1628     }
1629   )";
1630   runDataflow(
1631       Code, [](llvm::ArrayRef<
1632                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1633                    Results,
1634                ASTContext &ASTCtx) {
1635         ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
1636         const Environment &Env1 = Results[0].second.Env;
1637         const Environment &Env2 = Results[1].second.Env;
1638 
1639         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1640         ASSERT_THAT(FooDecl, NotNull());
1641 
1642         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1643         ASSERT_THAT(BarDecl, NotNull());
1644 
1645         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1646         ASSERT_THAT(BazDecl, NotNull());
1647 
1648         const auto *FooLoc1 = cast<AggregateStorageLocation>(
1649             Env1.getStorageLocation(*FooDecl, SkipPast::None));
1650         const auto *BarLoc1 = cast<AggregateStorageLocation>(
1651             Env1.getStorageLocation(*BarDecl, SkipPast::None));
1652 
1653         const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1));
1654         const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1));
1655         EXPECT_NE(FooVal1, BarVal1);
1656 
1657         const auto *FooBazVal1 =
1658             cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl)));
1659         const auto *BarBazVal1 =
1660             cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl)));
1661         EXPECT_NE(FooBazVal1, BarBazVal1);
1662 
1663         const auto *FooLoc2 = cast<AggregateStorageLocation>(
1664             Env2.getStorageLocation(*FooDecl, SkipPast::None));
1665         const auto *BarLoc2 = cast<AggregateStorageLocation>(
1666             Env2.getStorageLocation(*BarDecl, SkipPast::None));
1667 
1668         const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2));
1669         const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2));
1670         EXPECT_EQ(FooVal2, BarVal2);
1671 
1672         const auto *FooBazVal2 =
1673             cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl)));
1674         const auto *BarBazVal2 =
1675             cast<IntegerValue>(Env2.getValue(BarLoc1->getChild(*BazDecl)));
1676         EXPECT_EQ(FooBazVal2, BarBazVal2);
1677       });
1678 }
1679 
1680 TEST_F(TransferTest, CopyConstructor) {
1681   std::string Code = R"(
1682     struct A {
1683       int Baz;
1684     };
1685 
1686     void target() {
1687       A Foo;
1688       A Bar = Foo;
1689       // [[p]]
1690     }
1691   )";
1692   runDataflow(
1693       Code, [](llvm::ArrayRef<
1694                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1695                    Results,
1696                ASTContext &ASTCtx) {
1697         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1698         const Environment &Env = Results[0].second.Env;
1699 
1700         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1701         ASSERT_THAT(FooDecl, NotNull());
1702 
1703         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1704         ASSERT_THAT(BarDecl, NotNull());
1705 
1706         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1707         ASSERT_THAT(BazDecl, NotNull());
1708 
1709         const auto *FooLoc = cast<AggregateStorageLocation>(
1710             Env.getStorageLocation(*FooDecl, SkipPast::None));
1711         const auto *BarLoc = cast<AggregateStorageLocation>(
1712             Env.getStorageLocation(*BarDecl, SkipPast::None));
1713 
1714         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1715         const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc));
1716         EXPECT_EQ(FooVal, BarVal);
1717 
1718         const auto *FooBazVal =
1719             cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl)));
1720         const auto *BarBazVal =
1721             cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl)));
1722         EXPECT_EQ(FooBazVal, BarBazVal);
1723       });
1724 }
1725 
1726 TEST_F(TransferTest, CopyConstructorWithParens) {
1727   std::string Code = R"(
1728     struct A {
1729       int Baz;
1730     };
1731 
1732     void target() {
1733       A Foo;
1734       A Bar((A(Foo)));
1735       // [[p]]
1736     }
1737   )";
1738   runDataflow(
1739       Code, [](llvm::ArrayRef<
1740                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1741                    Results,
1742                ASTContext &ASTCtx) {
1743         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1744         const Environment &Env = Results[0].second.Env;
1745 
1746         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1747         ASSERT_THAT(FooDecl, NotNull());
1748 
1749         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1750         ASSERT_THAT(BarDecl, NotNull());
1751 
1752         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1753         ASSERT_THAT(BazDecl, NotNull());
1754 
1755         const auto *FooLoc = cast<AggregateStorageLocation>(
1756             Env.getStorageLocation(*FooDecl, SkipPast::None));
1757         const auto *BarLoc = cast<AggregateStorageLocation>(
1758             Env.getStorageLocation(*BarDecl, SkipPast::None));
1759 
1760         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1761         const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc));
1762         EXPECT_EQ(FooVal, BarVal);
1763 
1764         const auto *FooBazVal =
1765             cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl)));
1766         const auto *BarBazVal =
1767             cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl)));
1768         EXPECT_EQ(FooBazVal, BarBazVal);
1769       });
1770 }
1771 
1772 TEST_F(TransferTest, MoveConstructor) {
1773   std::string Code = R"(
1774     namespace std {
1775 
1776     template <typename T> struct remove_reference      { using type = T; };
1777     template <typename T> struct remove_reference<T&>  { using type = T; };
1778     template <typename T> struct remove_reference<T&&> { using type = T; };
1779 
1780     template <typename T>
1781     using remove_reference_t = typename remove_reference<T>::type;
1782 
1783     template <typename T>
1784     std::remove_reference_t<T>&& move(T&& x);
1785 
1786     } // namespace std
1787 
1788     struct A {
1789       int Baz;
1790     };
1791 
1792     void target() {
1793       A Foo;
1794       A Bar;
1795       // [[p1]]
1796       Foo = std::move(Bar);
1797       // [[p2]]
1798     }
1799   )";
1800   runDataflow(
1801       Code, [](llvm::ArrayRef<
1802                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1803                    Results,
1804                ASTContext &ASTCtx) {
1805         ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
1806         const Environment &Env1 = Results[0].second.Env;
1807         const Environment &Env2 = Results[1].second.Env;
1808 
1809         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1810         ASSERT_THAT(FooDecl, NotNull());
1811 
1812         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1813         ASSERT_THAT(BarDecl, NotNull());
1814 
1815         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1816         ASSERT_THAT(BazDecl, NotNull());
1817 
1818         const auto *FooLoc1 = cast<AggregateStorageLocation>(
1819             Env1.getStorageLocation(*FooDecl, SkipPast::None));
1820         const auto *BarLoc1 = cast<AggregateStorageLocation>(
1821             Env1.getStorageLocation(*BarDecl, SkipPast::None));
1822 
1823         const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1));
1824         const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1));
1825         EXPECT_NE(FooVal1, BarVal1);
1826 
1827         const auto *FooBazVal1 =
1828             cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl)));
1829         const auto *BarBazVal1 =
1830             cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl)));
1831         EXPECT_NE(FooBazVal1, BarBazVal1);
1832 
1833         const auto *FooLoc2 = cast<AggregateStorageLocation>(
1834             Env2.getStorageLocation(*FooDecl, SkipPast::None));
1835         const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2));
1836         EXPECT_EQ(FooVal2, BarVal1);
1837 
1838         const auto *FooBazVal2 =
1839             cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl)));
1840         EXPECT_EQ(FooBazVal2, BarBazVal1);
1841       });
1842 }
1843 
1844 TEST_F(TransferTest, BindTemporary) {
1845   std::string Code = R"(
1846     struct A {
1847       virtual ~A() = default;
1848 
1849       int Baz;
1850     };
1851 
1852     void target(A Foo) {
1853       int Bar = A(Foo).Baz;
1854       // [[p]]
1855     }
1856   )";
1857   runDataflow(Code,
1858               [](llvm::ArrayRef<
1859                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1860                      Results,
1861                  ASTContext &ASTCtx) {
1862                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1863                 const Environment &Env = Results[0].second.Env;
1864 
1865                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1866                 ASSERT_THAT(FooDecl, NotNull());
1867 
1868                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1869                 ASSERT_THAT(BarDecl, NotNull());
1870 
1871                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1872                 ASSERT_THAT(BazDecl, NotNull());
1873 
1874                 const auto &FooVal =
1875                     *cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None));
1876                 const auto *BarVal =
1877                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
1878                 EXPECT_EQ(BarVal, FooVal.getChild(*BazDecl));
1879               });
1880 }
1881 
1882 TEST_F(TransferTest, StaticCast) {
1883   std::string Code = R"(
1884     void target(int Foo) {
1885       int Bar = static_cast<int>(Foo);
1886       // [[p]]
1887     }
1888   )";
1889   runDataflow(Code,
1890               [](llvm::ArrayRef<
1891                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1892                      Results,
1893                  ASTContext &ASTCtx) {
1894                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1895                 const Environment &Env = Results[0].second.Env;
1896 
1897                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1898                 ASSERT_THAT(FooDecl, NotNull());
1899 
1900                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1901                 ASSERT_THAT(BarDecl, NotNull());
1902 
1903                 const auto *FooVal =
1904                     cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None));
1905                 const auto *BarVal =
1906                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
1907                 EXPECT_EQ(FooVal, BarVal);
1908               });
1909 }
1910 
1911 TEST_F(TransferTest, AddrOfValue) {
1912   std::string Code = R"(
1913     void target() {
1914       int Foo;
1915       int *Bar = &Foo;
1916       // [[p]]
1917     }
1918   )";
1919   runDataflow(Code,
1920               [](llvm::ArrayRef<
1921                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1922                      Results,
1923                  ASTContext &ASTCtx) {
1924                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1925                 const Environment &Env = Results[0].second.Env;
1926 
1927                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1928                 ASSERT_THAT(FooDecl, NotNull());
1929 
1930                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1931                 ASSERT_THAT(BarDecl, NotNull());
1932 
1933                 const auto *FooLoc = cast<ScalarStorageLocation>(
1934                     Env.getStorageLocation(*FooDecl, SkipPast::None));
1935                 const auto *BarVal =
1936                     cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
1937                 EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
1938               });
1939 }
1940 
1941 TEST_F(TransferTest, AddrOfReference) {
1942   std::string Code = R"(
1943     void target(int *Foo) {
1944       int *Bar = &(*Foo);
1945       // [[p]]
1946     }
1947   )";
1948   runDataflow(Code,
1949               [](llvm::ArrayRef<
1950                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1951                      Results,
1952                  ASTContext &ASTCtx) {
1953                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1954                 const Environment &Env = Results[0].second.Env;
1955 
1956                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1957                 ASSERT_THAT(FooDecl, NotNull());
1958 
1959                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1960                 ASSERT_THAT(BarDecl, NotNull());
1961 
1962                 const auto *FooVal =
1963                     cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
1964                 const auto *BarVal =
1965                     cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
1966                 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
1967               });
1968 }
1969 
1970 TEST_F(TransferTest, DerefDependentPtr) {
1971   std::string Code = R"(
1972     template <typename T>
1973     void target(T *Foo) {
1974       T &Bar = *Foo;
1975       /*[[p]]*/
1976     }
1977   )";
1978   runDataflow(
1979       Code, [](llvm::ArrayRef<
1980                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1981                    Results,
1982                ASTContext &ASTCtx) {
1983         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1984         const Environment &Env = Results[0].second.Env;
1985 
1986         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1987         ASSERT_THAT(FooDecl, NotNull());
1988 
1989         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1990         ASSERT_THAT(BarDecl, NotNull());
1991 
1992         const auto *FooVal =
1993             cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
1994         const auto *BarVal =
1995             cast<ReferenceValue>(Env.getValue(*BarDecl, SkipPast::None));
1996         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
1997       });
1998 }
1999 
2000 TEST_F(TransferTest, VarDeclInitAssignConditionalOperator) {
2001   std::string Code = R"(
2002     struct A {};
2003 
2004     void target(A Foo, A Bar, bool Cond) {
2005       A Baz = Cond ?  Foo : Bar;
2006       /*[[p]]*/
2007     }
2008   )";
2009   runDataflow(
2010       Code, [](llvm::ArrayRef<
2011                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2012                    Results,
2013                ASTContext &ASTCtx) {
2014         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2015         const Environment &Env = Results[0].second.Env;
2016 
2017         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2018         ASSERT_THAT(FooDecl, NotNull());
2019 
2020         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2021         ASSERT_THAT(BarDecl, NotNull());
2022 
2023         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2024         ASSERT_THAT(BazDecl, NotNull());
2025 
2026         const auto *FooVal =
2027             cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None));
2028         const auto *BarVal =
2029             cast<StructValue>(Env.getValue(*BarDecl, SkipPast::None));
2030 
2031         const auto *BazVal =
2032             dyn_cast<StructValue>(Env.getValue(*BazDecl, SkipPast::None));
2033         ASSERT_THAT(BazVal, NotNull());
2034 
2035         EXPECT_NE(BazVal, FooVal);
2036         EXPECT_NE(BazVal, BarVal);
2037       });
2038 }
2039 
2040 TEST_F(TransferTest, VarDeclInDoWhile) {
2041   std::string Code = R"(
2042     void target(int *Foo) {
2043       do {
2044         int Bar = *Foo;
2045       } while (true);
2046       (void)0;
2047       /*[[p]]*/
2048     }
2049   )";
2050   runDataflow(Code,
2051               [](llvm::ArrayRef<
2052                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2053                      Results,
2054                  ASTContext &ASTCtx) {
2055                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2056                 const Environment &Env = Results[0].second.Env;
2057 
2058                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2059                 ASSERT_THAT(FooDecl, NotNull());
2060 
2061                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2062                 ASSERT_THAT(BarDecl, NotNull());
2063 
2064                 const auto *FooVal =
2065                     cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2066                 const auto *FooPointeeVal =
2067                     cast<IntegerValue>(Env.getValue(FooVal->getPointeeLoc()));
2068 
2069                 const auto *BarVal = dyn_cast_or_null<IntegerValue>(
2070                     Env.getValue(*BarDecl, SkipPast::None));
2071                 ASSERT_THAT(BarVal, NotNull());
2072 
2073                 EXPECT_EQ(BarVal, FooPointeeVal);
2074               });
2075 }
2076 
2077 TEST_F(TransferTest, AggregateInitialization) {
2078   std::string BracesCode = R"(
2079     struct A {
2080       int Foo;
2081     };
2082 
2083     struct B {
2084       int Bar;
2085       A Baz;
2086       int Qux;
2087     };
2088 
2089     void target(int BarArg, int FooArg, int QuxArg) {
2090       B Quux{BarArg, {FooArg}, QuxArg};
2091       /*[[p]]*/
2092     }
2093   )";
2094   std::string BraceEllisionCode = R"(
2095     struct A {
2096       int Foo;
2097     };
2098 
2099     struct B {
2100       int Bar;
2101       A Baz;
2102       int Qux;
2103     };
2104 
2105     void target(int BarArg, int FooArg, int QuxArg) {
2106       B Quux = {BarArg, FooArg, QuxArg};
2107       /*[[p]]*/
2108     }
2109   )";
2110   for (const std::string &Code : {BracesCode, BraceEllisionCode}) {
2111     runDataflow(
2112         Code, [](llvm::ArrayRef<
2113                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2114                      Results,
2115                  ASTContext &ASTCtx) {
2116           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2117           const Environment &Env = Results[0].second.Env;
2118 
2119           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2120           ASSERT_THAT(FooDecl, NotNull());
2121 
2122           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2123           ASSERT_THAT(BarDecl, NotNull());
2124 
2125           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2126           ASSERT_THAT(BazDecl, NotNull());
2127 
2128           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2129           ASSERT_THAT(QuxDecl, NotNull());
2130 
2131           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
2132           ASSERT_THAT(FooArgDecl, NotNull());
2133 
2134           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
2135           ASSERT_THAT(BarArgDecl, NotNull());
2136 
2137           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
2138           ASSERT_THAT(QuxArgDecl, NotNull());
2139 
2140           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
2141           ASSERT_THAT(QuuxDecl, NotNull());
2142 
2143           const auto *FooArgVal =
2144               cast<IntegerValue>(Env.getValue(*FooArgDecl, SkipPast::None));
2145           const auto *BarArgVal =
2146               cast<IntegerValue>(Env.getValue(*BarArgDecl, SkipPast::None));
2147           const auto *QuxArgVal =
2148               cast<IntegerValue>(Env.getValue(*QuxArgDecl, SkipPast::None));
2149 
2150           const auto *QuuxVal =
2151               cast<StructValue>(Env.getValue(*QuuxDecl, SkipPast::None));
2152           ASSERT_THAT(QuuxVal, NotNull());
2153 
2154           const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl));
2155           ASSERT_THAT(BazVal, NotNull());
2156 
2157           EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal);
2158           EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal);
2159           EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal);
2160         });
2161   }
2162 }
2163 
2164 TEST_F(TransferTest, AssignToUnionMember) {
2165   std::string Code = R"(
2166     union A {
2167       int Foo;
2168     };
2169 
2170     void target(int Bar) {
2171       A Baz;
2172       Baz.Foo = Bar;
2173       // [[p]]
2174     }
2175   )";
2176   runDataflow(Code,
2177               [](llvm::ArrayRef<
2178                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2179                      Results,
2180                  ASTContext &ASTCtx) {
2181                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2182                 const Environment &Env = Results[0].second.Env;
2183 
2184                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2185                 ASSERT_THAT(BazDecl, NotNull());
2186                 ASSERT_TRUE(BazDecl->getType()->isUnionType());
2187 
2188                 const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>(
2189                     Env.getStorageLocation(*BazDecl, SkipPast::None));
2190                 ASSERT_THAT(BazLoc, NotNull());
2191 
2192                 // FIXME: Add support for union types.
2193                 EXPECT_THAT(Env.getValue(*BazLoc), IsNull());
2194               });
2195 }
2196 
2197 TEST_F(TransferTest, AssignFromBoolLiteral) {
2198   std::string Code = R"(
2199     void target() {
2200       bool Foo = true;
2201       bool Bar = false;
2202       // [[p]]
2203     }
2204   )";
2205   runDataflow(Code,
2206               [](llvm::ArrayRef<
2207                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2208                      Results,
2209                  ASTContext &ASTCtx) {
2210                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2211                 const Environment &Env = Results[0].second.Env;
2212 
2213                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2214                 ASSERT_THAT(FooDecl, NotNull());
2215 
2216                 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>(
2217                     Env.getValue(*FooDecl, SkipPast::None));
2218                 ASSERT_THAT(FooVal, NotNull());
2219 
2220                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2221                 ASSERT_THAT(BarDecl, NotNull());
2222 
2223                 const auto *BarVal = dyn_cast_or_null<AtomicBoolValue>(
2224                     Env.getValue(*BarDecl, SkipPast::None));
2225                 ASSERT_THAT(BarVal, NotNull());
2226 
2227                 EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
2228                 EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
2229               });
2230 }
2231 
2232 TEST_F(TransferTest, AssignFromCompositeBoolExpression) {
2233   {
2234     std::string Code = R"(
2235     void target(bool Foo, bool Bar, bool Qux) {
2236       bool Baz = (Foo) && (Bar || Qux);
2237       // [[p]]
2238     }
2239   )";
2240     runDataflow(
2241         Code, [](llvm::ArrayRef<
2242                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2243                      Results,
2244                  ASTContext &ASTCtx) {
2245           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2246           const Environment &Env = Results[0].second.Env;
2247 
2248           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2249           ASSERT_THAT(FooDecl, NotNull());
2250 
2251           const auto *FooVal = dyn_cast_or_null<BoolValue>(
2252               Env.getValue(*FooDecl, SkipPast::None));
2253           ASSERT_THAT(FooVal, NotNull());
2254 
2255           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2256           ASSERT_THAT(BarDecl, NotNull());
2257 
2258           const auto *BarVal = dyn_cast_or_null<BoolValue>(
2259               Env.getValue(*BarDecl, SkipPast::None));
2260           ASSERT_THAT(BarVal, NotNull());
2261 
2262           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2263           ASSERT_THAT(QuxDecl, NotNull());
2264 
2265           const auto *QuxVal = dyn_cast_or_null<BoolValue>(
2266               Env.getValue(*QuxDecl, SkipPast::None));
2267           ASSERT_THAT(QuxVal, NotNull());
2268 
2269           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2270           ASSERT_THAT(BazDecl, NotNull());
2271 
2272           const auto *BazVal = dyn_cast_or_null<ConjunctionValue>(
2273               Env.getValue(*BazDecl, SkipPast::None));
2274           ASSERT_THAT(BazVal, NotNull());
2275           EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
2276 
2277           const auto *BazRightSubValVal =
2278               cast<DisjunctionValue>(&BazVal->getRightSubValue());
2279           EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal);
2280           EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal);
2281         });
2282   }
2283 
2284   {
2285     std::string Code = R"(
2286     void target(bool Foo, bool Bar, bool Qux) {
2287       bool Baz = (Foo && Qux) || (Bar);
2288       // [[p]]
2289     }
2290   )";
2291     runDataflow(
2292         Code, [](llvm::ArrayRef<
2293                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2294                      Results,
2295                  ASTContext &ASTCtx) {
2296           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2297           const Environment &Env = Results[0].second.Env;
2298 
2299           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2300           ASSERT_THAT(FooDecl, NotNull());
2301 
2302           const auto *FooVal = dyn_cast_or_null<BoolValue>(
2303               Env.getValue(*FooDecl, SkipPast::None));
2304           ASSERT_THAT(FooVal, NotNull());
2305 
2306           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2307           ASSERT_THAT(BarDecl, NotNull());
2308 
2309           const auto *BarVal = dyn_cast_or_null<BoolValue>(
2310               Env.getValue(*BarDecl, SkipPast::None));
2311           ASSERT_THAT(BarVal, NotNull());
2312 
2313           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2314           ASSERT_THAT(QuxDecl, NotNull());
2315 
2316           const auto *QuxVal = dyn_cast_or_null<BoolValue>(
2317               Env.getValue(*QuxDecl, SkipPast::None));
2318           ASSERT_THAT(QuxVal, NotNull());
2319 
2320           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2321           ASSERT_THAT(BazDecl, NotNull());
2322 
2323           const auto *BazVal = dyn_cast_or_null<DisjunctionValue>(
2324               Env.getValue(*BazDecl, SkipPast::None));
2325           ASSERT_THAT(BazVal, NotNull());
2326 
2327           const auto *BazLeftSubValVal =
2328               cast<ConjunctionValue>(&BazVal->getLeftSubValue());
2329           EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal);
2330           EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal);
2331 
2332           EXPECT_EQ(&BazVal->getRightSubValue(), BarVal);
2333         });
2334   }
2335 }
2336 
2337 TEST_F(TransferTest, AssignFromBoolNegation) {
2338   std::string Code = R"(
2339     void target() {
2340       bool Foo = true;
2341       bool Bar = !(Foo);
2342       // [[p]]
2343     }
2344   )";
2345   runDataflow(Code,
2346               [](llvm::ArrayRef<
2347                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2348                      Results,
2349                  ASTContext &ASTCtx) {
2350                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2351                 const Environment &Env = Results[0].second.Env;
2352 
2353                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2354                 ASSERT_THAT(FooDecl, NotNull());
2355 
2356                 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>(
2357                     Env.getValue(*FooDecl, SkipPast::None));
2358                 ASSERT_THAT(FooVal, NotNull());
2359 
2360                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2361                 ASSERT_THAT(BarDecl, NotNull());
2362 
2363                 const auto *BarVal = dyn_cast_or_null<NegationValue>(
2364                     Env.getValue(*BarDecl, SkipPast::None));
2365                 ASSERT_THAT(BarVal, NotNull());
2366 
2367                 EXPECT_EQ(&BarVal->getSubVal(), FooVal);
2368               });
2369 }
2370 
2371 TEST_F(TransferTest, StaticIntSingleVarDecl) {
2372   std::string Code = R"(
2373     void target() {
2374       static int Foo;
2375       // [[p]]
2376     }
2377   )";
2378   runDataflow(Code,
2379               [](llvm::ArrayRef<
2380                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2381                      Results,
2382                  ASTContext &ASTCtx) {
2383                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2384                 const Environment &Env = Results[0].second.Env;
2385 
2386                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2387                 ASSERT_THAT(FooDecl, NotNull());
2388 
2389                 const StorageLocation *FooLoc =
2390                     Env.getStorageLocation(*FooDecl, SkipPast::None);
2391                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
2392 
2393                 const Value *FooVal = Env.getValue(*FooLoc);
2394                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
2395               });
2396 }
2397 
2398 TEST_F(TransferTest, StaticIntGroupVarDecl) {
2399   std::string Code = R"(
2400     void target() {
2401       static int Foo, Bar;
2402       (void)0;
2403       // [[p]]
2404     }
2405   )";
2406   runDataflow(Code,
2407               [](llvm::ArrayRef<
2408                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2409                      Results,
2410                  ASTContext &ASTCtx) {
2411                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2412                 const Environment &Env = Results[0].second.Env;
2413 
2414                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2415                 ASSERT_THAT(FooDecl, NotNull());
2416 
2417                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2418                 ASSERT_THAT(BarDecl, NotNull());
2419 
2420                 const StorageLocation *FooLoc =
2421                     Env.getStorageLocation(*FooDecl, SkipPast::None);
2422                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
2423 
2424                 const StorageLocation *BarLoc =
2425                     Env.getStorageLocation(*BarDecl, SkipPast::None);
2426                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2427 
2428                 const Value *FooVal = Env.getValue(*FooLoc);
2429                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
2430 
2431                 const Value *BarVal = Env.getValue(*BarLoc);
2432                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
2433 
2434                 EXPECT_NE(FooVal, BarVal);
2435               });
2436 }
2437 
2438 TEST_F(TransferTest, GlobalIntVarDecl) {
2439   std::string Code = R"(
2440     static int Foo;
2441 
2442     void target() {
2443       int Bar = Foo;
2444       int Baz = Foo;
2445       // [[p]]
2446     }
2447   )";
2448   runDataflow(Code,
2449               [](llvm::ArrayRef<
2450                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2451                      Results,
2452                  ASTContext &ASTCtx) {
2453                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2454                 const Environment &Env = Results[0].second.Env;
2455 
2456                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2457                 ASSERT_THAT(BarDecl, NotNull());
2458 
2459                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2460                 ASSERT_THAT(BazDecl, NotNull());
2461 
2462                 const Value *BarVal =
2463                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2464                 const Value *BazVal =
2465                     cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
2466                 EXPECT_EQ(BarVal, BazVal);
2467               });
2468 }
2469 
2470 TEST_F(TransferTest, StaticMemberIntVarDecl) {
2471   std::string Code = R"(
2472     struct A {
2473       static int Foo;
2474     };
2475 
2476     void target(A a) {
2477       int Bar = a.Foo;
2478       int Baz = a.Foo;
2479       // [[p]]
2480     }
2481   )";
2482   runDataflow(Code,
2483               [](llvm::ArrayRef<
2484                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2485                      Results,
2486                  ASTContext &ASTCtx) {
2487                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2488                 const Environment &Env = Results[0].second.Env;
2489 
2490                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2491                 ASSERT_THAT(BarDecl, NotNull());
2492 
2493                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2494                 ASSERT_THAT(BazDecl, NotNull());
2495 
2496                 const Value *BarVal =
2497                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2498                 const Value *BazVal =
2499                     cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
2500                 EXPECT_EQ(BarVal, BazVal);
2501               });
2502 }
2503 
2504 TEST_F(TransferTest, StaticMemberRefVarDecl) {
2505   std::string Code = R"(
2506     struct A {
2507       static int &Foo;
2508     };
2509 
2510     void target(A a) {
2511       int Bar = a.Foo;
2512       int Baz = a.Foo;
2513       // [[p]]
2514     }
2515   )";
2516   runDataflow(Code,
2517               [](llvm::ArrayRef<
2518                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2519                      Results,
2520                  ASTContext &ASTCtx) {
2521                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2522                 const Environment &Env = Results[0].second.Env;
2523 
2524                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2525                 ASSERT_THAT(BarDecl, NotNull());
2526 
2527                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2528                 ASSERT_THAT(BazDecl, NotNull());
2529 
2530                 const Value *BarVal =
2531                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2532                 const Value *BazVal =
2533                     cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
2534                 EXPECT_EQ(BarVal, BazVal);
2535               });
2536 }
2537 
2538 TEST_F(TransferTest, AssignMemberBeforeCopy) {
2539   std::string Code = R"(
2540     struct A {
2541       int Foo;
2542     };
2543 
2544     void target() {
2545       A A1;
2546       A A2;
2547       int Bar;
2548       A1.Foo = Bar;
2549       A2 = A1;
2550       // [[p]]
2551     }
2552   )";
2553   runDataflow(Code,
2554               [](llvm::ArrayRef<
2555                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2556                      Results,
2557                  ASTContext &ASTCtx) {
2558                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2559                 const Environment &Env = Results[0].second.Env;
2560 
2561                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2562                 ASSERT_THAT(FooDecl, NotNull());
2563 
2564                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2565                 ASSERT_THAT(BarDecl, NotNull());
2566 
2567                 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
2568                 ASSERT_THAT(A1Decl, NotNull());
2569 
2570                 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
2571                 ASSERT_THAT(A2Decl, NotNull());
2572 
2573                 const auto *BarVal =
2574                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2575 
2576                 const auto *A2Val =
2577                     cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None));
2578                 EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal);
2579               });
2580 }
2581 
2582 TEST_F(TransferTest, BooleanEquality) {
2583   std::string Code = R"(
2584     void target(bool Bar) {
2585       bool Foo = true;
2586       if (Bar == Foo) {
2587         (void)0;
2588         /*[[p-then]]*/
2589       } else {
2590         (void)0;
2591         /*[[p-else]]*/
2592       }
2593     }
2594   )";
2595   runDataflow(
2596       Code, [](llvm::ArrayRef<
2597                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2598                    Results,
2599                ASTContext &ASTCtx) {
2600         ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _)));
2601         const Environment &EnvElse = Results[0].second.Env;
2602         const Environment &EnvThen = Results[1].second.Env;
2603 
2604         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2605         ASSERT_THAT(BarDecl, NotNull());
2606 
2607         auto &BarValThen =
2608             *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None));
2609         EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen));
2610 
2611         auto &BarValElse =
2612             *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None));
2613         EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse));
2614       });
2615 }
2616 
2617 TEST_F(TransferTest, BooleanInequality) {
2618   std::string Code = R"(
2619     void target(bool Bar) {
2620       bool Foo = true;
2621       if (Bar != Foo) {
2622         (void)0;
2623         /*[[p-then]]*/
2624       } else {
2625         (void)0;
2626         /*[[p-else]]*/
2627       }
2628     }
2629   )";
2630   runDataflow(
2631       Code, [](llvm::ArrayRef<
2632                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2633                    Results,
2634                ASTContext &ASTCtx) {
2635         ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _)));
2636         const Environment &EnvElse = Results[0].second.Env;
2637         const Environment &EnvThen = Results[1].second.Env;
2638 
2639         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2640         ASSERT_THAT(BarDecl, NotNull());
2641 
2642         auto &BarValThen =
2643             *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None));
2644         EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen));
2645 
2646         auto &BarValElse =
2647             *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None));
2648         EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse));
2649       });
2650 }
2651 
2652 TEST_F(TransferTest, CorrelatedBranches) {
2653   std::string Code = R"(
2654     void target(bool B, bool C) {
2655       if (B) {
2656         return;
2657       }
2658       (void)0;
2659       /*[[p0]]*/
2660       if (C) {
2661         B = true;
2662         /*[[p1]]*/
2663       }
2664       if (B) {
2665         (void)0;
2666         /*[[p2]]*/
2667       }
2668     }
2669   )";
2670   runDataflow(
2671       Code, [](llvm::ArrayRef<
2672                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2673                    Results,
2674                ASTContext &ASTCtx) {
2675         ASSERT_THAT(Results, SizeIs(3));
2676 
2677         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
2678         ASSERT_THAT(CDecl, NotNull());
2679 
2680         {
2681           ASSERT_THAT(Results[2], Pair("p0", _));
2682           const Environment &Env = Results[2].second.Env;
2683           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
2684           ASSERT_THAT(BDecl, NotNull());
2685           auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl, SkipPast::None));
2686 
2687           EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal)));
2688         }
2689 
2690         {
2691           ASSERT_THAT(Results[1], Pair("p1", _));
2692           const Environment &Env = Results[1].second.Env;
2693           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
2694           EXPECT_TRUE(Env.flowConditionImplies(CVal));
2695         }
2696 
2697         {
2698           ASSERT_THAT(Results[0], Pair("p2", _));
2699           const Environment &Env = Results[0].second.Env;
2700           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
2701           EXPECT_TRUE(Env.flowConditionImplies(CVal));
2702         }
2703       });
2704 }
2705 
2706 } // namespace
2707