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