xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision 5520c5839016d1d98d8e01789eb17c910381bd6f)
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, StructThisInLambda) {
1480   std::string ThisCaptureCode = R"(
1481     struct A {
1482       void frob() {
1483         [this]() {
1484           int Foo = Bar;
1485           // [[p1]]
1486         }();
1487       }
1488 
1489       int Bar;
1490     };
1491   )";
1492   runDataflow(
1493       ThisCaptureCode,
1494       [](llvm::ArrayRef<
1495              std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1496              Results,
1497          ASTContext &ASTCtx) {
1498         ASSERT_THAT(Results, ElementsAre(Pair("p1", _)));
1499         const Environment &Env = Results[0].second.Env;
1500 
1501         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1502             Env.getThisPointeeStorageLocation());
1503         ASSERT_THAT(ThisLoc, NotNull());
1504 
1505         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1506         ASSERT_THAT(BarDecl, NotNull());
1507 
1508         const auto *BarLoc =
1509             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1510         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1511 
1512         const Value *BarVal = Env.getValue(*BarLoc);
1513         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1514 
1515         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1516         ASSERT_THAT(FooDecl, NotNull());
1517         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1518       },
1519       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1520 
1521   std::string RefCaptureDefaultCode = R"(
1522     struct A {
1523       void frob() {
1524         [&]() {
1525           int Foo = Bar;
1526           // [[p2]]
1527         }();
1528       }
1529 
1530       int Bar;
1531     };
1532   )";
1533   runDataflow(
1534       RefCaptureDefaultCode,
1535       [](llvm::ArrayRef<
1536              std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1537              Results,
1538          ASTContext &ASTCtx) {
1539         ASSERT_THAT(Results, ElementsAre(Pair("p2", _)));
1540         const Environment &Env = Results[0].second.Env;
1541 
1542         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1543             Env.getThisPointeeStorageLocation());
1544         ASSERT_THAT(ThisLoc, NotNull());
1545 
1546         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1547         ASSERT_THAT(BarDecl, NotNull());
1548 
1549         const auto *BarLoc =
1550             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1551         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1552 
1553         const Value *BarVal = Env.getValue(*BarLoc);
1554         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1555 
1556         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1557         ASSERT_THAT(FooDecl, NotNull());
1558         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1559       },
1560       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1561 
1562   std::string FreeFunctionLambdaCode = R"(
1563     void foo() {
1564       int Bar;
1565       [&]() {
1566         int Foo = Bar;
1567         // [[p3]]
1568       }();
1569     }
1570   )";
1571   runDataflow(
1572       FreeFunctionLambdaCode,
1573       [](llvm::ArrayRef<
1574              std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1575              Results,
1576          ASTContext &ASTCtx) {
1577         ASSERT_THAT(Results, ElementsAre(Pair("p3", _)));
1578         const Environment &Env = Results[0].second.Env;
1579 
1580         EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull());
1581       },
1582       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1583 }
1584 
1585 TEST_F(TransferTest, ConstructorInitializer) {
1586   std::string Code = R"(
1587     struct target {
1588       int Bar;
1589 
1590       target(int Foo) : Bar(Foo) {
1591         int Qux = Bar;
1592         // [[p]]
1593       }
1594     };
1595   )";
1596   runDataflow(Code,
1597               [](llvm::ArrayRef<
1598                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1599                      Results,
1600                  ASTContext &ASTCtx) {
1601                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1602                 const Environment &Env = Results[0].second.Env;
1603 
1604                 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1605                     Env.getThisPointeeStorageLocation());
1606                 ASSERT_THAT(ThisLoc, NotNull());
1607 
1608                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1609                 ASSERT_THAT(FooDecl, NotNull());
1610 
1611                 const auto *FooVal =
1612                     cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None));
1613 
1614                 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1615                 ASSERT_THAT(QuxDecl, NotNull());
1616                 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal);
1617               });
1618 }
1619 
1620 TEST_F(TransferTest, DefaultInitializer) {
1621   std::string Code = R"(
1622     struct target {
1623       int Bar;
1624       int Baz = Bar;
1625 
1626       target(int Foo) : Bar(Foo) {
1627         int Qux = Baz;
1628         // [[p]]
1629       }
1630     };
1631   )";
1632   runDataflow(Code,
1633               [](llvm::ArrayRef<
1634                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1635                      Results,
1636                  ASTContext &ASTCtx) {
1637                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1638                 const Environment &Env = Results[0].second.Env;
1639 
1640                 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1641                     Env.getThisPointeeStorageLocation());
1642                 ASSERT_THAT(ThisLoc, NotNull());
1643 
1644                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1645                 ASSERT_THAT(FooDecl, NotNull());
1646 
1647                 const auto *FooVal =
1648                     cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None));
1649 
1650                 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1651                 ASSERT_THAT(QuxDecl, NotNull());
1652                 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal);
1653               });
1654 }
1655 
1656 TEST_F(TransferTest, DefaultInitializerReference) {
1657   std::string Code = R"(
1658     struct target {
1659       int &Bar;
1660       int &Baz = Bar;
1661 
1662       target(int &Foo) : Bar(Foo) {
1663         int &Qux = Baz;
1664         // [[p]]
1665       }
1666     };
1667   )";
1668   runDataflow(
1669       Code, [](llvm::ArrayRef<
1670                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1671                    Results,
1672                ASTContext &ASTCtx) {
1673         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1674         const Environment &Env = Results[0].second.Env;
1675 
1676         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1677             Env.getThisPointeeStorageLocation());
1678         ASSERT_THAT(ThisLoc, NotNull());
1679 
1680         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1681         ASSERT_THAT(FooDecl, NotNull());
1682 
1683         const auto *FooVal =
1684             cast<ReferenceValue>(Env.getValue(*FooDecl, SkipPast::None));
1685 
1686         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1687         ASSERT_THAT(QuxDecl, NotNull());
1688 
1689         const auto *QuxVal =
1690             cast<ReferenceValue>(Env.getValue(*QuxDecl, SkipPast::None));
1691         EXPECT_EQ(&QuxVal->getPointeeLoc(), &FooVal->getPointeeLoc());
1692       });
1693 }
1694 
1695 TEST_F(TransferTest, TemporaryObject) {
1696   std::string Code = R"(
1697     struct A {
1698       int Bar;
1699     };
1700 
1701     void target() {
1702       A Foo = A();
1703       // [[p]]
1704     }
1705   )";
1706   runDataflow(
1707       Code, [](llvm::ArrayRef<
1708                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1709                    Results,
1710                ASTContext &ASTCtx) {
1711         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1712         const Environment &Env = Results[0].second.Env;
1713 
1714         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1715         ASSERT_THAT(FooDecl, NotNull());
1716 
1717         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1718         ASSERT_THAT(BarDecl, NotNull());
1719 
1720         const auto *FooLoc = cast<AggregateStorageLocation>(
1721             Env.getStorageLocation(*FooDecl, SkipPast::None));
1722         const auto *BarLoc =
1723             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
1724 
1725         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1726         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1727         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
1728       });
1729 }
1730 
1731 TEST_F(TransferTest, ElidableConstructor) {
1732   // This test is effectively the same as TransferTest.TemporaryObject, but
1733   // the code is compiled as C++ 14.
1734   std::string Code = R"(
1735     struct A {
1736       int Bar;
1737     };
1738 
1739     void target() {
1740       A Foo = A();
1741       // [[p]]
1742     }
1743   )";
1744   runDataflow(
1745       Code,
1746       [](llvm::ArrayRef<
1747              std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1748              Results,
1749          ASTContext &ASTCtx) {
1750         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1751         const Environment &Env = Results[0].second.Env;
1752 
1753         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1754         ASSERT_THAT(FooDecl, NotNull());
1755 
1756         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1757         ASSERT_THAT(BarDecl, NotNull());
1758 
1759         const auto *FooLoc = cast<AggregateStorageLocation>(
1760             Env.getStorageLocation(*FooDecl, SkipPast::None));
1761         const auto *BarLoc =
1762             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
1763 
1764         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1765         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1766         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
1767       },
1768       LangStandard::lang_cxx14);
1769 }
1770 
1771 TEST_F(TransferTest, AssignmentOperator) {
1772   std::string Code = R"(
1773     struct A {
1774       int Baz;
1775     };
1776 
1777     void target() {
1778       A Foo;
1779       A Bar;
1780       // [[p1]]
1781       Foo = Bar;
1782       // [[p2]]
1783     }
1784   )";
1785   runDataflow(
1786       Code, [](llvm::ArrayRef<
1787                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1788                    Results,
1789                ASTContext &ASTCtx) {
1790         ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
1791         const Environment &Env1 = Results[0].second.Env;
1792         const Environment &Env2 = Results[1].second.Env;
1793 
1794         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1795         ASSERT_THAT(FooDecl, NotNull());
1796 
1797         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1798         ASSERT_THAT(BarDecl, NotNull());
1799 
1800         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1801         ASSERT_THAT(BazDecl, NotNull());
1802 
1803         const auto *FooLoc1 = cast<AggregateStorageLocation>(
1804             Env1.getStorageLocation(*FooDecl, SkipPast::None));
1805         const auto *BarLoc1 = cast<AggregateStorageLocation>(
1806             Env1.getStorageLocation(*BarDecl, SkipPast::None));
1807 
1808         const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1));
1809         const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1));
1810         EXPECT_NE(FooVal1, BarVal1);
1811 
1812         const auto *FooBazVal1 =
1813             cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl)));
1814         const auto *BarBazVal1 =
1815             cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl)));
1816         EXPECT_NE(FooBazVal1, BarBazVal1);
1817 
1818         const auto *FooLoc2 = cast<AggregateStorageLocation>(
1819             Env2.getStorageLocation(*FooDecl, SkipPast::None));
1820         const auto *BarLoc2 = cast<AggregateStorageLocation>(
1821             Env2.getStorageLocation(*BarDecl, SkipPast::None));
1822 
1823         const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2));
1824         const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2));
1825         EXPECT_EQ(FooVal2, BarVal2);
1826 
1827         const auto *FooBazVal2 =
1828             cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl)));
1829         const auto *BarBazVal2 =
1830             cast<IntegerValue>(Env2.getValue(BarLoc1->getChild(*BazDecl)));
1831         EXPECT_EQ(FooBazVal2, BarBazVal2);
1832       });
1833 }
1834 
1835 TEST_F(TransferTest, CopyConstructor) {
1836   std::string Code = R"(
1837     struct A {
1838       int Baz;
1839     };
1840 
1841     void target() {
1842       A Foo;
1843       A Bar = Foo;
1844       // [[p]]
1845     }
1846   )";
1847   runDataflow(
1848       Code, [](llvm::ArrayRef<
1849                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1850                    Results,
1851                ASTContext &ASTCtx) {
1852         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1853         const Environment &Env = Results[0].second.Env;
1854 
1855         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1856         ASSERT_THAT(FooDecl, NotNull());
1857 
1858         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1859         ASSERT_THAT(BarDecl, NotNull());
1860 
1861         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1862         ASSERT_THAT(BazDecl, NotNull());
1863 
1864         const auto *FooLoc = cast<AggregateStorageLocation>(
1865             Env.getStorageLocation(*FooDecl, SkipPast::None));
1866         const auto *BarLoc = cast<AggregateStorageLocation>(
1867             Env.getStorageLocation(*BarDecl, SkipPast::None));
1868 
1869         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1870         const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc));
1871         EXPECT_EQ(FooVal, BarVal);
1872 
1873         const auto *FooBazVal =
1874             cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl)));
1875         const auto *BarBazVal =
1876             cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl)));
1877         EXPECT_EQ(FooBazVal, BarBazVal);
1878       });
1879 }
1880 
1881 TEST_F(TransferTest, CopyConstructorWithParens) {
1882   std::string Code = R"(
1883     struct A {
1884       int Baz;
1885     };
1886 
1887     void target() {
1888       A Foo;
1889       A Bar((A(Foo)));
1890       // [[p]]
1891     }
1892   )";
1893   runDataflow(
1894       Code, [](llvm::ArrayRef<
1895                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1896                    Results,
1897                ASTContext &ASTCtx) {
1898         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1899         const Environment &Env = Results[0].second.Env;
1900 
1901         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1902         ASSERT_THAT(FooDecl, NotNull());
1903 
1904         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1905         ASSERT_THAT(BarDecl, NotNull());
1906 
1907         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1908         ASSERT_THAT(BazDecl, NotNull());
1909 
1910         const auto *FooLoc = cast<AggregateStorageLocation>(
1911             Env.getStorageLocation(*FooDecl, SkipPast::None));
1912         const auto *BarLoc = cast<AggregateStorageLocation>(
1913             Env.getStorageLocation(*BarDecl, SkipPast::None));
1914 
1915         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1916         const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc));
1917         EXPECT_EQ(FooVal, BarVal);
1918 
1919         const auto *FooBazVal =
1920             cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl)));
1921         const auto *BarBazVal =
1922             cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl)));
1923         EXPECT_EQ(FooBazVal, BarBazVal);
1924       });
1925 }
1926 
1927 TEST_F(TransferTest, MoveConstructor) {
1928   std::string Code = R"(
1929     namespace std {
1930 
1931     template <typename T> struct remove_reference      { using type = T; };
1932     template <typename T> struct remove_reference<T&>  { using type = T; };
1933     template <typename T> struct remove_reference<T&&> { using type = T; };
1934 
1935     template <typename T>
1936     using remove_reference_t = typename remove_reference<T>::type;
1937 
1938     template <typename T>
1939     std::remove_reference_t<T>&& move(T&& x);
1940 
1941     } // namespace std
1942 
1943     struct A {
1944       int Baz;
1945     };
1946 
1947     void target() {
1948       A Foo;
1949       A Bar;
1950       // [[p1]]
1951       Foo = std::move(Bar);
1952       // [[p2]]
1953     }
1954   )";
1955   runDataflow(
1956       Code, [](llvm::ArrayRef<
1957                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1958                    Results,
1959                ASTContext &ASTCtx) {
1960         ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
1961         const Environment &Env1 = Results[0].second.Env;
1962         const Environment &Env2 = Results[1].second.Env;
1963 
1964         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1965         ASSERT_THAT(FooDecl, NotNull());
1966 
1967         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1968         ASSERT_THAT(BarDecl, NotNull());
1969 
1970         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1971         ASSERT_THAT(BazDecl, NotNull());
1972 
1973         const auto *FooLoc1 = cast<AggregateStorageLocation>(
1974             Env1.getStorageLocation(*FooDecl, SkipPast::None));
1975         const auto *BarLoc1 = cast<AggregateStorageLocation>(
1976             Env1.getStorageLocation(*BarDecl, SkipPast::None));
1977 
1978         const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1));
1979         const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1));
1980         EXPECT_NE(FooVal1, BarVal1);
1981 
1982         const auto *FooBazVal1 =
1983             cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl)));
1984         const auto *BarBazVal1 =
1985             cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl)));
1986         EXPECT_NE(FooBazVal1, BarBazVal1);
1987 
1988         const auto *FooLoc2 = cast<AggregateStorageLocation>(
1989             Env2.getStorageLocation(*FooDecl, SkipPast::None));
1990         const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2));
1991         EXPECT_EQ(FooVal2, BarVal1);
1992 
1993         const auto *FooBazVal2 =
1994             cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl)));
1995         EXPECT_EQ(FooBazVal2, BarBazVal1);
1996       });
1997 }
1998 
1999 TEST_F(TransferTest, BindTemporary) {
2000   std::string Code = R"(
2001     struct A {
2002       virtual ~A() = default;
2003 
2004       int Baz;
2005     };
2006 
2007     void target(A Foo) {
2008       int Bar = A(Foo).Baz;
2009       // [[p]]
2010     }
2011   )";
2012   runDataflow(Code,
2013               [](llvm::ArrayRef<
2014                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2015                      Results,
2016                  ASTContext &ASTCtx) {
2017                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2018                 const Environment &Env = Results[0].second.Env;
2019 
2020                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2021                 ASSERT_THAT(FooDecl, NotNull());
2022 
2023                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2024                 ASSERT_THAT(BarDecl, NotNull());
2025 
2026                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2027                 ASSERT_THAT(BazDecl, NotNull());
2028 
2029                 const auto &FooVal =
2030                     *cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None));
2031                 const auto *BarVal =
2032                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2033                 EXPECT_EQ(BarVal, FooVal.getChild(*BazDecl));
2034               });
2035 }
2036 
2037 TEST_F(TransferTest, StaticCast) {
2038   std::string Code = R"(
2039     void target(int Foo) {
2040       int Bar = static_cast<int>(Foo);
2041       // [[p]]
2042     }
2043   )";
2044   runDataflow(Code,
2045               [](llvm::ArrayRef<
2046                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2047                      Results,
2048                  ASTContext &ASTCtx) {
2049                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2050                 const Environment &Env = Results[0].second.Env;
2051 
2052                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2053                 ASSERT_THAT(FooDecl, NotNull());
2054 
2055                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2056                 ASSERT_THAT(BarDecl, NotNull());
2057 
2058                 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2059                 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2060                 EXPECT_TRUE(isa<IntegerValue>(FooVal));
2061                 EXPECT_TRUE(isa<IntegerValue>(BarVal));
2062                 EXPECT_EQ(FooVal, BarVal);
2063               });
2064 }
2065 
2066 TEST_F(TransferTest, IntegralCast) {
2067   std::string Code = R"(
2068     void target(int Foo) {
2069       long Bar = Foo;
2070       // [[p]]
2071     }
2072   )";
2073   runDataflow(Code,
2074               [](llvm::ArrayRef<
2075                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2076                      Results,
2077                  ASTContext &ASTCtx) {
2078                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2079                 const Environment &Env = Results[0].second.Env;
2080 
2081                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2082                 ASSERT_THAT(FooDecl, NotNull());
2083 
2084                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2085                 ASSERT_THAT(BarDecl, NotNull());
2086 
2087                 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2088                 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2089                 EXPECT_TRUE(isa<IntegerValue>(FooVal));
2090                 EXPECT_TRUE(isa<IntegerValue>(BarVal));
2091                 EXPECT_EQ(FooVal, BarVal);
2092               });
2093 }
2094 
2095 TEST_F(TransferTest, IntegraltoBooleanCast) {
2096   std::string Code = R"(
2097     void target(int Foo) {
2098       bool Bar = Foo;
2099       // [[p]]
2100     }
2101   )";
2102   runDataflow(Code,
2103               [](llvm::ArrayRef<
2104                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2105                      Results,
2106                  ASTContext &ASTCtx) {
2107                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2108                 const Environment &Env = Results[0].second.Env;
2109 
2110                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2111                 ASSERT_THAT(FooDecl, NotNull());
2112 
2113                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2114                 ASSERT_THAT(BarDecl, NotNull());
2115 
2116                 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2117                 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2118                 EXPECT_TRUE(isa<IntegerValue>(FooVal));
2119                 EXPECT_TRUE(isa<BoolValue>(BarVal));
2120               });
2121 }
2122 
2123 TEST_F(TransferTest, IntegralToBooleanCastFromBool) {
2124   std::string Code = R"(
2125     void target(bool Foo) {
2126       int Zab = Foo;
2127       bool Bar = Zab;
2128       // [[p]]
2129     }
2130   )";
2131   runDataflow(Code,
2132               [](llvm::ArrayRef<
2133                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2134                      Results,
2135                  ASTContext &ASTCtx) {
2136                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2137                 const Environment &Env = Results[0].second.Env;
2138 
2139                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2140                 ASSERT_THAT(FooDecl, NotNull());
2141 
2142                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2143                 ASSERT_THAT(BarDecl, NotNull());
2144 
2145                 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2146                 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2147                 EXPECT_TRUE(isa<BoolValue>(FooVal));
2148                 EXPECT_TRUE(isa<BoolValue>(BarVal));
2149                 EXPECT_EQ(FooVal, BarVal);
2150               });
2151 }
2152 
2153 TEST_F(TransferTest, AddrOfValue) {
2154   std::string Code = R"(
2155     void target() {
2156       int Foo;
2157       int *Bar = &Foo;
2158       // [[p]]
2159     }
2160   )";
2161   runDataflow(Code,
2162               [](llvm::ArrayRef<
2163                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2164                      Results,
2165                  ASTContext &ASTCtx) {
2166                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2167                 const Environment &Env = Results[0].second.Env;
2168 
2169                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2170                 ASSERT_THAT(FooDecl, NotNull());
2171 
2172                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2173                 ASSERT_THAT(BarDecl, NotNull());
2174 
2175                 const auto *FooLoc = cast<ScalarStorageLocation>(
2176                     Env.getStorageLocation(*FooDecl, SkipPast::None));
2177                 const auto *BarVal =
2178                     cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
2179                 EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
2180               });
2181 }
2182 
2183 TEST_F(TransferTest, AddrOfReference) {
2184   std::string Code = R"(
2185     void target(int *Foo) {
2186       int *Bar = &(*Foo);
2187       // [[p]]
2188     }
2189   )";
2190   runDataflow(Code,
2191               [](llvm::ArrayRef<
2192                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2193                      Results,
2194                  ASTContext &ASTCtx) {
2195                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2196                 const Environment &Env = Results[0].second.Env;
2197 
2198                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2199                 ASSERT_THAT(FooDecl, NotNull());
2200 
2201                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2202                 ASSERT_THAT(BarDecl, NotNull());
2203 
2204                 const auto *FooVal =
2205                     cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2206                 const auto *BarVal =
2207                     cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
2208                 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
2209               });
2210 }
2211 
2212 TEST_F(TransferTest, DerefDependentPtr) {
2213   std::string Code = R"(
2214     template <typename T>
2215     void target(T *Foo) {
2216       T &Bar = *Foo;
2217       /*[[p]]*/
2218     }
2219   )";
2220   runDataflow(
2221       Code, [](llvm::ArrayRef<
2222                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2223                    Results,
2224                ASTContext &ASTCtx) {
2225         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2226         const Environment &Env = Results[0].second.Env;
2227 
2228         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2229         ASSERT_THAT(FooDecl, NotNull());
2230 
2231         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2232         ASSERT_THAT(BarDecl, NotNull());
2233 
2234         const auto *FooVal =
2235             cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2236         const auto *BarVal =
2237             cast<ReferenceValue>(Env.getValue(*BarDecl, SkipPast::None));
2238         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
2239       });
2240 }
2241 
2242 TEST_F(TransferTest, VarDeclInitAssignConditionalOperator) {
2243   std::string Code = R"(
2244     struct A {};
2245 
2246     void target(A Foo, A Bar, bool Cond) {
2247       A Baz = Cond ?  Foo : Bar;
2248       /*[[p]]*/
2249     }
2250   )";
2251   runDataflow(
2252       Code, [](llvm::ArrayRef<
2253                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2254                    Results,
2255                ASTContext &ASTCtx) {
2256         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2257         const Environment &Env = Results[0].second.Env;
2258 
2259         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2260         ASSERT_THAT(FooDecl, NotNull());
2261 
2262         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2263         ASSERT_THAT(BarDecl, NotNull());
2264 
2265         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2266         ASSERT_THAT(BazDecl, NotNull());
2267 
2268         const auto *FooVal =
2269             cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None));
2270         const auto *BarVal =
2271             cast<StructValue>(Env.getValue(*BarDecl, SkipPast::None));
2272 
2273         const auto *BazVal =
2274             dyn_cast<StructValue>(Env.getValue(*BazDecl, SkipPast::None));
2275         ASSERT_THAT(BazVal, NotNull());
2276 
2277         EXPECT_NE(BazVal, FooVal);
2278         EXPECT_NE(BazVal, BarVal);
2279       });
2280 }
2281 
2282 TEST_F(TransferTest, VarDeclInDoWhile) {
2283   std::string Code = R"(
2284     void target(int *Foo) {
2285       do {
2286         int Bar = *Foo;
2287       } while (true);
2288       (void)0;
2289       /*[[p]]*/
2290     }
2291   )";
2292   runDataflow(Code,
2293               [](llvm::ArrayRef<
2294                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2295                      Results,
2296                  ASTContext &ASTCtx) {
2297                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2298                 const Environment &Env = Results[0].second.Env;
2299 
2300                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2301                 ASSERT_THAT(FooDecl, NotNull());
2302 
2303                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2304                 ASSERT_THAT(BarDecl, NotNull());
2305 
2306                 const auto *FooVal =
2307                     cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2308                 const auto *FooPointeeVal =
2309                     cast<IntegerValue>(Env.getValue(FooVal->getPointeeLoc()));
2310 
2311                 const auto *BarVal = dyn_cast_or_null<IntegerValue>(
2312                     Env.getValue(*BarDecl, SkipPast::None));
2313                 ASSERT_THAT(BarVal, NotNull());
2314 
2315                 EXPECT_EQ(BarVal, FooPointeeVal);
2316               });
2317 }
2318 
2319 TEST_F(TransferTest, AggregateInitialization) {
2320   std::string BracesCode = R"(
2321     struct A {
2322       int Foo;
2323     };
2324 
2325     struct B {
2326       int Bar;
2327       A Baz;
2328       int Qux;
2329     };
2330 
2331     void target(int BarArg, int FooArg, int QuxArg) {
2332       B Quux{BarArg, {FooArg}, QuxArg};
2333       /*[[p]]*/
2334     }
2335   )";
2336   std::string BraceEllisionCode = R"(
2337     struct A {
2338       int Foo;
2339     };
2340 
2341     struct B {
2342       int Bar;
2343       A Baz;
2344       int Qux;
2345     };
2346 
2347     void target(int BarArg, int FooArg, int QuxArg) {
2348       B Quux = {BarArg, FooArg, QuxArg};
2349       /*[[p]]*/
2350     }
2351   )";
2352   for (const std::string &Code : {BracesCode, BraceEllisionCode}) {
2353     runDataflow(
2354         Code, [](llvm::ArrayRef<
2355                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2356                      Results,
2357                  ASTContext &ASTCtx) {
2358           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2359           const Environment &Env = Results[0].second.Env;
2360 
2361           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2362           ASSERT_THAT(FooDecl, NotNull());
2363 
2364           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2365           ASSERT_THAT(BarDecl, NotNull());
2366 
2367           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2368           ASSERT_THAT(BazDecl, NotNull());
2369 
2370           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2371           ASSERT_THAT(QuxDecl, NotNull());
2372 
2373           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
2374           ASSERT_THAT(FooArgDecl, NotNull());
2375 
2376           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
2377           ASSERT_THAT(BarArgDecl, NotNull());
2378 
2379           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
2380           ASSERT_THAT(QuxArgDecl, NotNull());
2381 
2382           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
2383           ASSERT_THAT(QuuxDecl, NotNull());
2384 
2385           const auto *FooArgVal =
2386               cast<IntegerValue>(Env.getValue(*FooArgDecl, SkipPast::None));
2387           const auto *BarArgVal =
2388               cast<IntegerValue>(Env.getValue(*BarArgDecl, SkipPast::None));
2389           const auto *QuxArgVal =
2390               cast<IntegerValue>(Env.getValue(*QuxArgDecl, SkipPast::None));
2391 
2392           const auto *QuuxVal =
2393               cast<StructValue>(Env.getValue(*QuuxDecl, SkipPast::None));
2394           ASSERT_THAT(QuuxVal, NotNull());
2395 
2396           const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl));
2397           ASSERT_THAT(BazVal, NotNull());
2398 
2399           EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal);
2400           EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal);
2401           EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal);
2402         });
2403   }
2404 }
2405 
2406 TEST_F(TransferTest, AssignToUnionMember) {
2407   std::string Code = R"(
2408     union A {
2409       int Foo;
2410     };
2411 
2412     void target(int Bar) {
2413       A Baz;
2414       Baz.Foo = Bar;
2415       // [[p]]
2416     }
2417   )";
2418   runDataflow(Code,
2419               [](llvm::ArrayRef<
2420                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2421                      Results,
2422                  ASTContext &ASTCtx) {
2423                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2424                 const Environment &Env = Results[0].second.Env;
2425 
2426                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2427                 ASSERT_THAT(BazDecl, NotNull());
2428                 ASSERT_TRUE(BazDecl->getType()->isUnionType());
2429 
2430                 const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>(
2431                     Env.getStorageLocation(*BazDecl, SkipPast::None));
2432                 ASSERT_THAT(BazLoc, NotNull());
2433 
2434                 // FIXME: Add support for union types.
2435                 EXPECT_THAT(Env.getValue(*BazLoc), IsNull());
2436               });
2437 }
2438 
2439 TEST_F(TransferTest, AssignFromBoolLiteral) {
2440   std::string Code = R"(
2441     void target() {
2442       bool Foo = true;
2443       bool Bar = false;
2444       // [[p]]
2445     }
2446   )";
2447   runDataflow(Code,
2448               [](llvm::ArrayRef<
2449                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2450                      Results,
2451                  ASTContext &ASTCtx) {
2452                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2453                 const Environment &Env = Results[0].second.Env;
2454 
2455                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2456                 ASSERT_THAT(FooDecl, NotNull());
2457 
2458                 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>(
2459                     Env.getValue(*FooDecl, SkipPast::None));
2460                 ASSERT_THAT(FooVal, NotNull());
2461 
2462                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2463                 ASSERT_THAT(BarDecl, NotNull());
2464 
2465                 const auto *BarVal = dyn_cast_or_null<AtomicBoolValue>(
2466                     Env.getValue(*BarDecl, SkipPast::None));
2467                 ASSERT_THAT(BarVal, NotNull());
2468 
2469                 EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
2470                 EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
2471               });
2472 }
2473 
2474 TEST_F(TransferTest, AssignFromCompositeBoolExpression) {
2475   {
2476     std::string Code = R"(
2477     void target(bool Foo, bool Bar, bool Qux) {
2478       bool Baz = (Foo) && (Bar || Qux);
2479       // [[p]]
2480     }
2481   )";
2482     runDataflow(
2483         Code, [](llvm::ArrayRef<
2484                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2485                      Results,
2486                  ASTContext &ASTCtx) {
2487           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2488           const Environment &Env = Results[0].second.Env;
2489 
2490           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2491           ASSERT_THAT(FooDecl, NotNull());
2492 
2493           const auto *FooVal = dyn_cast_or_null<BoolValue>(
2494               Env.getValue(*FooDecl, SkipPast::None));
2495           ASSERT_THAT(FooVal, NotNull());
2496 
2497           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2498           ASSERT_THAT(BarDecl, NotNull());
2499 
2500           const auto *BarVal = dyn_cast_or_null<BoolValue>(
2501               Env.getValue(*BarDecl, SkipPast::None));
2502           ASSERT_THAT(BarVal, NotNull());
2503 
2504           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2505           ASSERT_THAT(QuxDecl, NotNull());
2506 
2507           const auto *QuxVal = dyn_cast_or_null<BoolValue>(
2508               Env.getValue(*QuxDecl, SkipPast::None));
2509           ASSERT_THAT(QuxVal, NotNull());
2510 
2511           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2512           ASSERT_THAT(BazDecl, NotNull());
2513 
2514           const auto *BazVal = dyn_cast_or_null<ConjunctionValue>(
2515               Env.getValue(*BazDecl, SkipPast::None));
2516           ASSERT_THAT(BazVal, NotNull());
2517           EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
2518 
2519           const auto *BazRightSubValVal =
2520               cast<DisjunctionValue>(&BazVal->getRightSubValue());
2521           EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal);
2522           EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal);
2523         });
2524   }
2525 
2526   {
2527     std::string Code = R"(
2528     void target(bool Foo, bool Bar, bool Qux) {
2529       bool Baz = (Foo && Qux) || (Bar);
2530       // [[p]]
2531     }
2532   )";
2533     runDataflow(
2534         Code, [](llvm::ArrayRef<
2535                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2536                      Results,
2537                  ASTContext &ASTCtx) {
2538           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2539           const Environment &Env = Results[0].second.Env;
2540 
2541           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2542           ASSERT_THAT(FooDecl, NotNull());
2543 
2544           const auto *FooVal = dyn_cast_or_null<BoolValue>(
2545               Env.getValue(*FooDecl, SkipPast::None));
2546           ASSERT_THAT(FooVal, NotNull());
2547 
2548           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2549           ASSERT_THAT(BarDecl, NotNull());
2550 
2551           const auto *BarVal = dyn_cast_or_null<BoolValue>(
2552               Env.getValue(*BarDecl, SkipPast::None));
2553           ASSERT_THAT(BarVal, NotNull());
2554 
2555           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2556           ASSERT_THAT(QuxDecl, NotNull());
2557 
2558           const auto *QuxVal = dyn_cast_or_null<BoolValue>(
2559               Env.getValue(*QuxDecl, SkipPast::None));
2560           ASSERT_THAT(QuxVal, NotNull());
2561 
2562           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2563           ASSERT_THAT(BazDecl, NotNull());
2564 
2565           const auto *BazVal = dyn_cast_or_null<DisjunctionValue>(
2566               Env.getValue(*BazDecl, SkipPast::None));
2567           ASSERT_THAT(BazVal, NotNull());
2568 
2569           const auto *BazLeftSubValVal =
2570               cast<ConjunctionValue>(&BazVal->getLeftSubValue());
2571           EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal);
2572           EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal);
2573 
2574           EXPECT_EQ(&BazVal->getRightSubValue(), BarVal);
2575         });
2576   }
2577 
2578   {
2579     std::string Code = R"(
2580       void target(bool A, bool B, bool C, bool D) {
2581         bool Foo = ((A && B) && C) && D;
2582         // [[p]]
2583       }
2584     )";
2585     runDataflow(
2586         Code, [](llvm::ArrayRef<
2587                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2588                      Results,
2589                  ASTContext &ASTCtx) {
2590           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2591           const Environment &Env = Results[0].second.Env;
2592 
2593           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
2594           ASSERT_THAT(ADecl, NotNull());
2595 
2596           const auto *AVal =
2597               dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl, SkipPast::None));
2598           ASSERT_THAT(AVal, NotNull());
2599 
2600           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
2601           ASSERT_THAT(BDecl, NotNull());
2602 
2603           const auto *BVal =
2604               dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl, SkipPast::None));
2605           ASSERT_THAT(BVal, NotNull());
2606 
2607           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
2608           ASSERT_THAT(CDecl, NotNull());
2609 
2610           const auto *CVal =
2611               dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
2612           ASSERT_THAT(CVal, NotNull());
2613 
2614           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
2615           ASSERT_THAT(DDecl, NotNull());
2616 
2617           const auto *DVal =
2618               dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl, SkipPast::None));
2619           ASSERT_THAT(DVal, NotNull());
2620 
2621           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2622           ASSERT_THAT(FooDecl, NotNull());
2623 
2624           const auto *FooVal = dyn_cast_or_null<ConjunctionValue>(
2625               Env.getValue(*FooDecl, SkipPast::None));
2626           ASSERT_THAT(FooVal, NotNull());
2627 
2628           const auto &FooLeftSubVal =
2629               cast<ConjunctionValue>(FooVal->getLeftSubValue());
2630           const auto &FooLeftLeftSubVal =
2631               cast<ConjunctionValue>(FooLeftSubVal.getLeftSubValue());
2632           EXPECT_EQ(&FooLeftLeftSubVal.getLeftSubValue(), AVal);
2633           EXPECT_EQ(&FooLeftLeftSubVal.getRightSubValue(), BVal);
2634           EXPECT_EQ(&FooLeftSubVal.getRightSubValue(), CVal);
2635           EXPECT_EQ(&FooVal->getRightSubValue(), DVal);
2636         });
2637   }
2638 }
2639 
2640 TEST_F(TransferTest, AssignFromBoolNegation) {
2641   std::string Code = R"(
2642     void target() {
2643       bool Foo = true;
2644       bool Bar = !(Foo);
2645       // [[p]]
2646     }
2647   )";
2648   runDataflow(Code,
2649               [](llvm::ArrayRef<
2650                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2651                      Results,
2652                  ASTContext &ASTCtx) {
2653                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2654                 const Environment &Env = Results[0].second.Env;
2655 
2656                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2657                 ASSERT_THAT(FooDecl, NotNull());
2658 
2659                 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>(
2660                     Env.getValue(*FooDecl, SkipPast::None));
2661                 ASSERT_THAT(FooVal, NotNull());
2662 
2663                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2664                 ASSERT_THAT(BarDecl, NotNull());
2665 
2666                 const auto *BarVal = dyn_cast_or_null<NegationValue>(
2667                     Env.getValue(*BarDecl, SkipPast::None));
2668                 ASSERT_THAT(BarVal, NotNull());
2669 
2670                 EXPECT_EQ(&BarVal->getSubVal(), FooVal);
2671               });
2672 }
2673 
2674 TEST_F(TransferTest, BuiltinExpect) {
2675   std::string Code = R"(
2676     void target(long Foo) {
2677       long Bar = __builtin_expect(Foo, true);
2678       /*[[p]]*/
2679     }
2680   )";
2681   runDataflow(Code,
2682               [](llvm::ArrayRef<
2683                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2684                      Results,
2685                  ASTContext &ASTCtx) {
2686                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2687                 const auto &Env = Results[0].second.Env;
2688 
2689                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2690                 ASSERT_THAT(FooDecl, NotNull());
2691 
2692                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2693                 ASSERT_THAT(BarDecl, NotNull());
2694 
2695                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2696                           Env.getValue(*BarDecl, SkipPast::None));
2697               });
2698 }
2699 
2700 // `__builtin_expect` takes and returns a `long` argument, so other types
2701 // involve casts. This verifies that we identify the input and output in that
2702 // case.
2703 TEST_F(TransferTest, BuiltinExpectBoolArg) {
2704   std::string Code = R"(
2705     void target(bool Foo) {
2706       bool Bar = __builtin_expect(Foo, true);
2707       /*[[p]]*/
2708     }
2709   )";
2710   runDataflow(Code,
2711               [](llvm::ArrayRef<
2712                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2713                      Results,
2714                  ASTContext &ASTCtx) {
2715                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2716                 const auto &Env = Results[0].second.Env;
2717 
2718                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2719                 ASSERT_THAT(FooDecl, NotNull());
2720 
2721                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2722                 ASSERT_THAT(BarDecl, NotNull());
2723 
2724                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2725                           Env.getValue(*BarDecl, SkipPast::None));
2726               });
2727 }
2728 
2729 TEST_F(TransferTest, BuiltinUnreachable) {
2730   std::string Code = R"(
2731     void target(bool Foo) {
2732       bool Bar = false;
2733       if (Foo)
2734         Bar = Foo;
2735       else
2736         __builtin_unreachable();
2737       (void)0;
2738       /*[[p]]*/
2739     }
2740   )";
2741   runDataflow(Code,
2742               [](llvm::ArrayRef<
2743                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2744                      Results,
2745                  ASTContext &ASTCtx) {
2746                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2747                 const auto &Env = Results[0].second.Env;
2748 
2749                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2750                 ASSERT_THAT(FooDecl, NotNull());
2751 
2752                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2753                 ASSERT_THAT(BarDecl, NotNull());
2754 
2755                 // `__builtin_unreachable` promises that the code is
2756                 // unreachable, so the compiler treats the "then" branch as the
2757                 // only possible predecessor of this statement.
2758                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2759                           Env.getValue(*BarDecl, SkipPast::None));
2760               });
2761 }
2762 
2763 TEST_F(TransferTest, BuiltinTrap) {
2764   std::string Code = R"(
2765     void target(bool Foo) {
2766       bool Bar = false;
2767       if (Foo)
2768         Bar = Foo;
2769       else
2770         __builtin_trap();
2771       (void)0;
2772       /*[[p]]*/
2773     }
2774   )";
2775   runDataflow(Code,
2776               [](llvm::ArrayRef<
2777                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2778                      Results,
2779                  ASTContext &ASTCtx) {
2780                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2781                 const auto &Env = Results[0].second.Env;
2782 
2783                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2784                 ASSERT_THAT(FooDecl, NotNull());
2785 
2786                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2787                 ASSERT_THAT(BarDecl, NotNull());
2788 
2789                 // `__builtin_trap` ensures program termination, so only the
2790                 // "then" branch is a predecessor of this statement.
2791                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2792                           Env.getValue(*BarDecl, SkipPast::None));
2793               });
2794 }
2795 
2796 TEST_F(TransferTest, BuiltinDebugTrap) {
2797   std::string Code = R"(
2798     void target(bool Foo) {
2799       bool Bar = false;
2800       if (Foo)
2801         Bar = Foo;
2802       else
2803         __builtin_debugtrap();
2804       (void)0;
2805       /*[[p]]*/
2806     }
2807   )";
2808   runDataflow(Code,
2809               [](llvm::ArrayRef<
2810                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2811                      Results,
2812                  ASTContext &ASTCtx) {
2813                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2814                 const auto &Env = Results[0].second.Env;
2815 
2816                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2817                 ASSERT_THAT(FooDecl, NotNull());
2818 
2819                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2820                 ASSERT_THAT(BarDecl, NotNull());
2821 
2822                 // `__builtin_debugtrap` doesn't ensure program termination.
2823                 EXPECT_NE(Env.getValue(*FooDecl, SkipPast::None),
2824                           Env.getValue(*BarDecl, SkipPast::None));
2825               });
2826 }
2827 
2828 TEST_F(TransferTest, StaticIntSingleVarDecl) {
2829   std::string Code = R"(
2830     void target() {
2831       static int Foo;
2832       // [[p]]
2833     }
2834   )";
2835   runDataflow(Code,
2836               [](llvm::ArrayRef<
2837                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2838                      Results,
2839                  ASTContext &ASTCtx) {
2840                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2841                 const Environment &Env = Results[0].second.Env;
2842 
2843                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2844                 ASSERT_THAT(FooDecl, NotNull());
2845 
2846                 const StorageLocation *FooLoc =
2847                     Env.getStorageLocation(*FooDecl, SkipPast::None);
2848                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
2849 
2850                 const Value *FooVal = Env.getValue(*FooLoc);
2851                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
2852               });
2853 }
2854 
2855 TEST_F(TransferTest, StaticIntGroupVarDecl) {
2856   std::string Code = R"(
2857     void target() {
2858       static int Foo, Bar;
2859       (void)0;
2860       // [[p]]
2861     }
2862   )";
2863   runDataflow(Code,
2864               [](llvm::ArrayRef<
2865                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2866                      Results,
2867                  ASTContext &ASTCtx) {
2868                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2869                 const Environment &Env = Results[0].second.Env;
2870 
2871                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2872                 ASSERT_THAT(FooDecl, NotNull());
2873 
2874                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2875                 ASSERT_THAT(BarDecl, NotNull());
2876 
2877                 const StorageLocation *FooLoc =
2878                     Env.getStorageLocation(*FooDecl, SkipPast::None);
2879                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
2880 
2881                 const StorageLocation *BarLoc =
2882                     Env.getStorageLocation(*BarDecl, SkipPast::None);
2883                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2884 
2885                 const Value *FooVal = Env.getValue(*FooLoc);
2886                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
2887 
2888                 const Value *BarVal = Env.getValue(*BarLoc);
2889                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
2890 
2891                 EXPECT_NE(FooVal, BarVal);
2892               });
2893 }
2894 
2895 TEST_F(TransferTest, GlobalIntVarDecl) {
2896   std::string Code = R"(
2897     static int Foo;
2898 
2899     void target() {
2900       int Bar = Foo;
2901       int Baz = Foo;
2902       // [[p]]
2903     }
2904   )";
2905   runDataflow(Code,
2906               [](llvm::ArrayRef<
2907                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2908                      Results,
2909                  ASTContext &ASTCtx) {
2910                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2911                 const Environment &Env = Results[0].second.Env;
2912 
2913                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2914                 ASSERT_THAT(BarDecl, NotNull());
2915 
2916                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2917                 ASSERT_THAT(BazDecl, NotNull());
2918 
2919                 const Value *BarVal =
2920                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2921                 const Value *BazVal =
2922                     cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
2923                 EXPECT_EQ(BarVal, BazVal);
2924               });
2925 }
2926 
2927 TEST_F(TransferTest, StaticMemberIntVarDecl) {
2928   std::string Code = R"(
2929     struct A {
2930       static int Foo;
2931     };
2932 
2933     void target(A a) {
2934       int Bar = a.Foo;
2935       int Baz = a.Foo;
2936       // [[p]]
2937     }
2938   )";
2939   runDataflow(Code,
2940               [](llvm::ArrayRef<
2941                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2942                      Results,
2943                  ASTContext &ASTCtx) {
2944                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2945                 const Environment &Env = Results[0].second.Env;
2946 
2947                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2948                 ASSERT_THAT(BarDecl, NotNull());
2949 
2950                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2951                 ASSERT_THAT(BazDecl, NotNull());
2952 
2953                 const Value *BarVal =
2954                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2955                 const Value *BazVal =
2956                     cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
2957                 EXPECT_EQ(BarVal, BazVal);
2958               });
2959 }
2960 
2961 TEST_F(TransferTest, StaticMemberRefVarDecl) {
2962   std::string Code = R"(
2963     struct A {
2964       static int &Foo;
2965     };
2966 
2967     void target(A a) {
2968       int Bar = a.Foo;
2969       int Baz = a.Foo;
2970       // [[p]]
2971     }
2972   )";
2973   runDataflow(Code,
2974               [](llvm::ArrayRef<
2975                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2976                      Results,
2977                  ASTContext &ASTCtx) {
2978                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2979                 const Environment &Env = Results[0].second.Env;
2980 
2981                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2982                 ASSERT_THAT(BarDecl, NotNull());
2983 
2984                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2985                 ASSERT_THAT(BazDecl, NotNull());
2986 
2987                 const Value *BarVal =
2988                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2989                 const Value *BazVal =
2990                     cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
2991                 EXPECT_EQ(BarVal, BazVal);
2992               });
2993 }
2994 
2995 TEST_F(TransferTest, AssignMemberBeforeCopy) {
2996   std::string Code = R"(
2997     struct A {
2998       int Foo;
2999     };
3000 
3001     void target() {
3002       A A1;
3003       A A2;
3004       int Bar;
3005       A1.Foo = Bar;
3006       A2 = A1;
3007       // [[p]]
3008     }
3009   )";
3010   runDataflow(Code,
3011               [](llvm::ArrayRef<
3012                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3013                      Results,
3014                  ASTContext &ASTCtx) {
3015                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3016                 const Environment &Env = Results[0].second.Env;
3017 
3018                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3019                 ASSERT_THAT(FooDecl, NotNull());
3020 
3021                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3022                 ASSERT_THAT(BarDecl, NotNull());
3023 
3024                 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
3025                 ASSERT_THAT(A1Decl, NotNull());
3026 
3027                 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
3028                 ASSERT_THAT(A2Decl, NotNull());
3029 
3030                 const auto *BarVal =
3031                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3032 
3033                 const auto *A2Val =
3034                     cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None));
3035                 EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal);
3036               });
3037 }
3038 
3039 TEST_F(TransferTest, BooleanEquality) {
3040   std::string Code = R"(
3041     void target(bool Bar) {
3042       bool Foo = true;
3043       if (Bar == Foo) {
3044         (void)0;
3045         /*[[p-then]]*/
3046       } else {
3047         (void)0;
3048         /*[[p-else]]*/
3049       }
3050     }
3051   )";
3052   runDataflow(
3053       Code, [](llvm::ArrayRef<
3054                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3055                    Results,
3056                ASTContext &ASTCtx) {
3057         ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _)));
3058         const Environment &EnvElse = Results[0].second.Env;
3059         const Environment &EnvThen = Results[1].second.Env;
3060 
3061         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3062         ASSERT_THAT(BarDecl, NotNull());
3063 
3064         auto &BarValThen =
3065             *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None));
3066         EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen));
3067 
3068         auto &BarValElse =
3069             *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None));
3070         EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse));
3071       });
3072 }
3073 
3074 TEST_F(TransferTest, BooleanInequality) {
3075   std::string Code = R"(
3076     void target(bool Bar) {
3077       bool Foo = true;
3078       if (Bar != Foo) {
3079         (void)0;
3080         /*[[p-then]]*/
3081       } else {
3082         (void)0;
3083         /*[[p-else]]*/
3084       }
3085     }
3086   )";
3087   runDataflow(
3088       Code, [](llvm::ArrayRef<
3089                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3090                    Results,
3091                ASTContext &ASTCtx) {
3092         ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _)));
3093         const Environment &EnvElse = Results[0].second.Env;
3094         const Environment &EnvThen = Results[1].second.Env;
3095 
3096         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3097         ASSERT_THAT(BarDecl, NotNull());
3098 
3099         auto &BarValThen =
3100             *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None));
3101         EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen));
3102 
3103         auto &BarValElse =
3104             *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None));
3105         EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse));
3106       });
3107 }
3108 
3109 TEST_F(TransferTest, CorrelatedBranches) {
3110   std::string Code = R"(
3111     void target(bool B, bool C) {
3112       if (B) {
3113         return;
3114       }
3115       (void)0;
3116       /*[[p0]]*/
3117       if (C) {
3118         B = true;
3119         /*[[p1]]*/
3120       }
3121       if (B) {
3122         (void)0;
3123         /*[[p2]]*/
3124       }
3125     }
3126   )";
3127   runDataflow(
3128       Code, [](llvm::ArrayRef<
3129                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3130                    Results,
3131                ASTContext &ASTCtx) {
3132         ASSERT_THAT(Results, SizeIs(3));
3133 
3134         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3135         ASSERT_THAT(CDecl, NotNull());
3136 
3137         {
3138           ASSERT_THAT(Results[2], Pair("p0", _));
3139           const Environment &Env = Results[2].second.Env;
3140           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3141           ASSERT_THAT(BDecl, NotNull());
3142           auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl, SkipPast::None));
3143 
3144           EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal)));
3145         }
3146 
3147         {
3148           ASSERT_THAT(Results[1], Pair("p1", _));
3149           const Environment &Env = Results[1].second.Env;
3150           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
3151           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3152         }
3153 
3154         {
3155           ASSERT_THAT(Results[0], Pair("p2", _));
3156           const Environment &Env = Results[0].second.Env;
3157           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
3158           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3159         }
3160       });
3161 }
3162 
3163 TEST_F(TransferTest, LoopWithAssignmentConverges) {
3164   std::string Code = R"(
3165 
3166     bool &foo();
3167 
3168     void target() {
3169        do {
3170         bool Bar = foo();
3171         if (Bar) break;
3172         (void)Bar;
3173         /*[[p]]*/
3174       } while (true);
3175     }
3176   )";
3177   // The key property that we are verifying is implicit in `runDataflow` --
3178   // namely, that the analysis succeeds, rather than hitting the maximum number
3179   // of iterations.
3180   runDataflow(
3181       Code, [](llvm::ArrayRef<
3182                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3183                    Results,
3184                ASTContext &ASTCtx) {
3185         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3186         const Environment &Env = Results[0].second.Env;
3187 
3188         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3189         ASSERT_THAT(BarDecl, NotNull());
3190 
3191         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
3192         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3193       });
3194 }
3195 
3196 TEST_F(TransferTest, LoopWithReferenceAssignmentConverges) {
3197   std::string Code = R"(
3198 
3199     bool &foo();
3200 
3201     void target() {
3202        do {
3203         bool& Bar = foo();
3204         if (Bar) break;
3205         (void)Bar;
3206         /*[[p]]*/
3207       } while (true);
3208     }
3209   )";
3210   // The key property that we are verifying is implicit in `runDataflow` --
3211   // namely, that the analysis succeeds, rather than hitting the maximum number
3212   // of iterations.
3213   runDataflow(
3214       Code, [](llvm::ArrayRef<
3215                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3216                    Results,
3217                ASTContext &ASTCtx) {
3218         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3219         const Environment &Env = Results[0].second.Env;
3220 
3221         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3222         ASSERT_THAT(BarDecl, NotNull());
3223 
3224         auto &BarVal =
3225             *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::Reference));
3226         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3227       });
3228 }
3229 
3230 TEST_F(TransferTest, LoopWithStructReferenceAssignmentConverges) {
3231   std::string Code = R"(
3232     struct Lookup {
3233       int x;
3234     };
3235 
3236     void target(Lookup val, bool b) {
3237       const Lookup* l = nullptr;
3238       while (b) {
3239         l = &val;
3240         /*[[p-inner]]*/
3241       }
3242       (void)0;
3243       /*[[p-outer]]*/
3244     }
3245   )";
3246   // The key property that we are verifying is implicit in `runDataflow` --
3247   // namely, that the analysis succeeds, rather than hitting the maximum number
3248   // of iterations.
3249   runDataflow(
3250       Code, [](llvm::ArrayRef<
3251                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3252                    Results,
3253                ASTContext &ASTCtx) {
3254         ASSERT_THAT(Results,
3255                     ElementsAre(Pair("p-outer", _), Pair("p-inner", _)));
3256         const Environment &OuterEnv = Results[0].second.Env;
3257         const Environment &InnerEnv = Results[1].second.Env;
3258 
3259         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
3260         ASSERT_THAT(ValDecl, NotNull());
3261 
3262         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
3263         ASSERT_THAT(LDecl, NotNull());
3264 
3265         // Inner.
3266         auto *LVal = dyn_cast<IndirectionValue>(
3267             InnerEnv.getValue(*LDecl, SkipPast::None));
3268         ASSERT_THAT(LVal, NotNull());
3269 
3270         EXPECT_EQ(&LVal->getPointeeLoc(),
3271                   InnerEnv.getStorageLocation(*ValDecl, SkipPast::Reference));
3272 
3273         // Outer.
3274         LVal = dyn_cast<IndirectionValue>(
3275             OuterEnv.getValue(*LDecl, SkipPast::None));
3276         ASSERT_THAT(LVal, NotNull());
3277 
3278         // The loop body may not have been executed, so we should not conclude
3279         // that `l` points to `val`.
3280         EXPECT_NE(&LVal->getPointeeLoc(),
3281                   OuterEnv.getStorageLocation(*ValDecl, SkipPast::Reference));
3282 });
3283 }
3284 
3285 TEST_F(TransferTest, DoesNotCrashOnUnionThisExpr) {
3286   std::string Code = R"(
3287     union Union {
3288       int A;
3289       float B;
3290     };
3291 
3292     void foo() {
3293       Union A;
3294       Union B;
3295       A = B;
3296     }
3297   )";
3298   // This is a crash regression test when calling the transfer function on a
3299   // `CXXThisExpr` that refers to a union.
3300   runDataflow(
3301       Code,
3302       [](llvm::ArrayRef<
3303              std::pair<std::string, DataflowAnalysisState<NoopLattice>>>,
3304          ASTContext &) {},
3305       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
3306 }
3307 
3308 } // namespace
3309