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