xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision fa2b83d07ecab3b24b4c5ee2e7dc4b6bbc895317)
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 "TestingSupport.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/AST/Decl.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/ASTMatchers/ASTMatchers.h"
14 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
15 #include "clang/Analysis/FlowSensitive/NoopAnalysis.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 template <typename Matcher>
41 void runDataflow(llvm::StringRef Code, Matcher Match,
42                  DataflowAnalysisOptions Options,
43                  LangStandard::Kind Std = LangStandard::lang_cxx17,
44                  llvm::StringRef TargetFun = "target") {
45   ASSERT_THAT_ERROR(
46       test::checkDataflow<NoopAnalysis>(
47           Code, TargetFun,
48           [Options](ASTContext &C, Environment &) {
49             return NoopAnalysis(C, Options);
50           },
51           [&Match](
52               llvm::ArrayRef<
53                   std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
54                   Results,
55               ASTContext &ASTCtx) { Match(Results, ASTCtx); },
56           {"-fsyntax-only", "-fno-delayed-template-parsing",
57            "-std=" + std::string(
58                          LangStandard::getLangStandardForKind(Std).getName())}),
59       llvm::Succeeded());
60 }
61 
62 template <typename Matcher>
63 void runDataflow(llvm::StringRef Code, Matcher Match,
64                  LangStandard::Kind Std = LangStandard::lang_cxx17,
65                  bool ApplyBuiltinTransfer = true,
66                  llvm::StringRef TargetFun = "target") {
67   runDataflow(Code, Match, {ApplyBuiltinTransfer, {}}, Std, TargetFun);
68 }
69 
70 TEST(TransferTest, IntVarDeclNotTrackedWhenTransferDisabled) {
71   std::string Code = R"(
72     void target() {
73       int Foo;
74       // [[p]]
75     }
76   )";
77   runDataflow(
78       Code,
79       [](llvm::ArrayRef<
80              std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
81              Results,
82          ASTContext &ASTCtx) {
83         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
84         const Environment &Env = Results[0].second.Env;
85 
86         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
87         ASSERT_THAT(FooDecl, NotNull());
88 
89         EXPECT_EQ(Env.getStorageLocation(*FooDecl, SkipPast::None), nullptr);
90       },
91       LangStandard::lang_cxx17,
92       /*ApplyBuiltinTransfer=*/false);
93 }
94 
95 TEST(TransferTest, BoolVarDecl) {
96   std::string Code = R"(
97     void target() {
98       bool Foo;
99       // [[p]]
100     }
101   )";
102   runDataflow(Code,
103               [](llvm::ArrayRef<
104                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
105                      Results,
106                  ASTContext &ASTCtx) {
107                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
108                 const Environment &Env = Results[0].second.Env;
109 
110                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
111                 ASSERT_THAT(FooDecl, NotNull());
112 
113                 const StorageLocation *FooLoc =
114                     Env.getStorageLocation(*FooDecl, SkipPast::None);
115                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
116 
117                 const Value *FooVal = Env.getValue(*FooLoc);
118                 EXPECT_TRUE(isa_and_nonnull<BoolValue>(FooVal));
119               });
120 }
121 
122 TEST(TransferTest, IntVarDecl) {
123   std::string Code = R"(
124     void target() {
125       int Foo;
126       // [[p]]
127     }
128   )";
129   runDataflow(Code,
130               [](llvm::ArrayRef<
131                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
132                      Results,
133                  ASTContext &ASTCtx) {
134                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
135                 const Environment &Env = Results[0].second.Env;
136 
137                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
138                 ASSERT_THAT(FooDecl, NotNull());
139 
140                 const StorageLocation *FooLoc =
141                     Env.getStorageLocation(*FooDecl, SkipPast::None);
142                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
143 
144                 const Value *FooVal = Env.getValue(*FooLoc);
145                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
146               });
147 }
148 
149 TEST(TransferTest, StructVarDecl) {
150   std::string Code = R"(
151     struct A {
152       int Bar;
153     };
154 
155     void target() {
156       A Foo;
157       // [[p]]
158     }
159   )";
160   runDataflow(
161       Code, [](llvm::ArrayRef<
162                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
163                    Results,
164                ASTContext &ASTCtx) {
165         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
166         const Environment &Env = Results[0].second.Env;
167 
168         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
169         ASSERT_THAT(FooDecl, NotNull());
170 
171         ASSERT_TRUE(FooDecl->getType()->isStructureType());
172         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
173 
174         FieldDecl *BarDecl = nullptr;
175         for (FieldDecl *Field : FooFields) {
176           if (Field->getNameAsString() == "Bar") {
177             BarDecl = Field;
178           } else {
179             FAIL() << "Unexpected field: " << Field->getNameAsString();
180           }
181         }
182         ASSERT_THAT(BarDecl, NotNull());
183 
184         const auto *FooLoc = cast<AggregateStorageLocation>(
185             Env.getStorageLocation(*FooDecl, SkipPast::None));
186         const auto *BarLoc =
187             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
188 
189         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
190         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
191         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
192       });
193 }
194 
195 TEST(TransferTest, StructVarDeclWithInit) {
196   std::string Code = R"(
197     struct A {
198       int Bar;
199     };
200 
201     A Gen();
202 
203     void target() {
204       A Foo = Gen();
205       // [[p]]
206     }
207   )";
208   runDataflow(
209       Code, [](llvm::ArrayRef<
210                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
211                    Results,
212                ASTContext &ASTCtx) {
213         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
214         const Environment &Env = Results[0].second.Env;
215 
216         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
217         ASSERT_THAT(FooDecl, NotNull());
218 
219         ASSERT_TRUE(FooDecl->getType()->isStructureType());
220         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
221 
222         FieldDecl *BarDecl = nullptr;
223         for (FieldDecl *Field : FooFields) {
224           if (Field->getNameAsString() == "Bar") {
225             BarDecl = Field;
226           } else {
227             FAIL() << "Unexpected field: " << Field->getNameAsString();
228           }
229         }
230         ASSERT_THAT(BarDecl, NotNull());
231 
232         const auto *FooLoc = cast<AggregateStorageLocation>(
233             Env.getStorageLocation(*FooDecl, SkipPast::None));
234         const auto *BarLoc =
235             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
236 
237         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
238         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
239         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
240       });
241 }
242 
243 TEST(TransferTest, ClassVarDecl) {
244   std::string Code = R"(
245     class A {
246       int Bar;
247     };
248 
249     void target() {
250       A Foo;
251       // [[p]]
252     }
253   )";
254   runDataflow(
255       Code, [](llvm::ArrayRef<
256                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
257                    Results,
258                ASTContext &ASTCtx) {
259         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
260         const Environment &Env = Results[0].second.Env;
261 
262         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
263         ASSERT_THAT(FooDecl, NotNull());
264 
265         ASSERT_TRUE(FooDecl->getType()->isClassType());
266         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
267 
268         FieldDecl *BarDecl = nullptr;
269         for (FieldDecl *Field : FooFields) {
270           if (Field->getNameAsString() == "Bar") {
271             BarDecl = Field;
272           } else {
273             FAIL() << "Unexpected field: " << Field->getNameAsString();
274           }
275         }
276         ASSERT_THAT(BarDecl, NotNull());
277 
278         const auto *FooLoc = cast<AggregateStorageLocation>(
279             Env.getStorageLocation(*FooDecl, SkipPast::None));
280         const auto *BarLoc =
281             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
282 
283         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
284         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
285         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
286       });
287 }
288 
289 TEST(TransferTest, ReferenceVarDecl) {
290   std::string Code = R"(
291     struct A {};
292 
293     A &getA();
294 
295     void target() {
296       A &Foo = getA();
297       // [[p]]
298     }
299   )";
300   runDataflow(
301       Code, [](llvm::ArrayRef<
302                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
303                    Results,
304                ASTContext &ASTCtx) {
305         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
306         const Environment &Env = Results[0].second.Env;
307 
308         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
309         ASSERT_THAT(FooDecl, NotNull());
310 
311         const StorageLocation *FooLoc =
312             Env.getStorageLocation(*FooDecl, SkipPast::None);
313         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
314 
315         const ReferenceValue *FooVal =
316             cast<ReferenceValue>(Env.getValue(*FooLoc));
317         const StorageLocation &FooReferentLoc = FooVal->getReferentLoc();
318         EXPECT_TRUE(isa<AggregateStorageLocation>(&FooReferentLoc));
319 
320         const Value *FooReferentVal = Env.getValue(FooReferentLoc);
321         EXPECT_TRUE(isa_and_nonnull<StructValue>(FooReferentVal));
322       });
323 }
324 
325 TEST(TransferTest, SelfReferentialReferenceVarDecl) {
326   std::string Code = R"(
327     struct A;
328 
329     struct B {};
330 
331     struct C {
332       A &FooRef;
333       A *FooPtr;
334       B &BazRef;
335       B *BazPtr;
336     };
337 
338     struct A {
339       C &Bar;
340     };
341 
342     A &getA();
343 
344     void target() {
345       A &Foo = getA();
346       // [[p]]
347     }
348   )";
349   runDataflow(Code, [](llvm::ArrayRef<std::pair<
350                            std::string, DataflowAnalysisState<NoopLattice>>>
351                            Results,
352                        ASTContext &ASTCtx) {
353     ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
354     const Environment &Env = Results[0].second.Env;
355 
356     const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
357     ASSERT_THAT(FooDecl, NotNull());
358 
359     ASSERT_TRUE(FooDecl->getType()->isReferenceType());
360     ASSERT_TRUE(FooDecl->getType().getNonReferenceType()->isStructureType());
361     const auto FooFields =
362         FooDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields();
363 
364     FieldDecl *BarDecl = nullptr;
365     for (FieldDecl *Field : FooFields) {
366       if (Field->getNameAsString() == "Bar") {
367         BarDecl = Field;
368       } else {
369         FAIL() << "Unexpected field: " << Field->getNameAsString();
370       }
371     }
372     ASSERT_THAT(BarDecl, NotNull());
373 
374     ASSERT_TRUE(BarDecl->getType()->isReferenceType());
375     ASSERT_TRUE(BarDecl->getType().getNonReferenceType()->isStructureType());
376     const auto BarFields =
377         BarDecl->getType().getNonReferenceType()->getAsRecordDecl()->fields();
378 
379     FieldDecl *FooRefDecl = nullptr;
380     FieldDecl *FooPtrDecl = nullptr;
381     FieldDecl *BazRefDecl = nullptr;
382     FieldDecl *BazPtrDecl = nullptr;
383     for (FieldDecl *Field : BarFields) {
384       if (Field->getNameAsString() == "FooRef") {
385         FooRefDecl = Field;
386       } else if (Field->getNameAsString() == "FooPtr") {
387         FooPtrDecl = Field;
388       } else if (Field->getNameAsString() == "BazRef") {
389         BazRefDecl = Field;
390       } else if (Field->getNameAsString() == "BazPtr") {
391         BazPtrDecl = Field;
392       } else {
393         FAIL() << "Unexpected field: " << Field->getNameAsString();
394       }
395     }
396     ASSERT_THAT(FooRefDecl, NotNull());
397     ASSERT_THAT(FooPtrDecl, NotNull());
398     ASSERT_THAT(BazRefDecl, NotNull());
399     ASSERT_THAT(BazPtrDecl, NotNull());
400 
401     const auto *FooLoc = cast<ScalarStorageLocation>(
402         Env.getStorageLocation(*FooDecl, SkipPast::None));
403     const auto *FooVal = cast<ReferenceValue>(Env.getValue(*FooLoc));
404     const auto *FooReferentVal =
405         cast<StructValue>(Env.getValue(FooVal->getReferentLoc()));
406 
407     const auto *BarVal =
408         cast<ReferenceValue>(FooReferentVal->getChild(*BarDecl));
409     const auto *BarReferentVal =
410         cast<StructValue>(Env.getValue(BarVal->getReferentLoc()));
411 
412     const auto *FooRefVal =
413         cast<ReferenceValue>(BarReferentVal->getChild(*FooRefDecl));
414     const StorageLocation &FooReferentLoc = FooRefVal->getReferentLoc();
415     EXPECT_THAT(Env.getValue(FooReferentLoc), IsNull());
416 
417     const auto *FooPtrVal =
418         cast<PointerValue>(BarReferentVal->getChild(*FooPtrDecl));
419     const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc();
420     EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull());
421 
422     const auto *BazRefVal =
423         cast<ReferenceValue>(BarReferentVal->getChild(*BazRefDecl));
424     const StorageLocation &BazReferentLoc = BazRefVal->getReferentLoc();
425     EXPECT_THAT(Env.getValue(BazReferentLoc), NotNull());
426 
427     const auto *BazPtrVal =
428         cast<PointerValue>(BarReferentVal->getChild(*BazPtrDecl));
429     const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc();
430     EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull());
431   });
432 }
433 
434 TEST(TransferTest, PointerVarDecl) {
435   std::string Code = R"(
436     struct A {};
437 
438     A *getA();
439 
440     void target() {
441       A *Foo = getA();
442       // [[p]]
443     }
444   )";
445   runDataflow(
446       Code, [](llvm::ArrayRef<
447                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
448                    Results,
449                ASTContext &ASTCtx) {
450         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
451         const Environment &Env = Results[0].second.Env;
452 
453         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
454         ASSERT_THAT(FooDecl, NotNull());
455 
456         const StorageLocation *FooLoc =
457             Env.getStorageLocation(*FooDecl, SkipPast::None);
458         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
459 
460         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
461         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
462         EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc));
463 
464         const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
465         EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal));
466       });
467 }
468 
469 TEST(TransferTest, SelfReferentialPointerVarDecl) {
470   std::string Code = R"(
471     struct A;
472 
473     struct B {};
474 
475     struct C {
476       A &FooRef;
477       A *FooPtr;
478       B &BazRef;
479       B *BazPtr;
480     };
481 
482     struct A {
483       C *Bar;
484     };
485 
486     A *getA();
487 
488     void target() {
489       A *Foo = getA();
490       // [[p]]
491     }
492   )";
493   runDataflow(
494       Code, [](llvm::ArrayRef<
495                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
496                    Results,
497                ASTContext &ASTCtx) {
498         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
499         const Environment &Env = Results[0].second.Env;
500 
501         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
502         ASSERT_THAT(FooDecl, NotNull());
503 
504         ASSERT_TRUE(FooDecl->getType()->isPointerType());
505         ASSERT_TRUE(FooDecl->getType()
506                         ->getAs<PointerType>()
507                         ->getPointeeType()
508                         ->isStructureType());
509         const auto FooFields = FooDecl->getType()
510                                    ->getAs<PointerType>()
511                                    ->getPointeeType()
512                                    ->getAsRecordDecl()
513                                    ->fields();
514 
515         FieldDecl *BarDecl = nullptr;
516         for (FieldDecl *Field : FooFields) {
517           if (Field->getNameAsString() == "Bar") {
518             BarDecl = Field;
519           } else {
520             FAIL() << "Unexpected field: " << Field->getNameAsString();
521           }
522         }
523         ASSERT_THAT(BarDecl, NotNull());
524 
525         ASSERT_TRUE(BarDecl->getType()->isPointerType());
526         ASSERT_TRUE(BarDecl->getType()
527                         ->getAs<PointerType>()
528                         ->getPointeeType()
529                         ->isStructureType());
530         const auto BarFields = BarDecl->getType()
531                                    ->getAs<PointerType>()
532                                    ->getPointeeType()
533                                    ->getAsRecordDecl()
534                                    ->fields();
535 
536         FieldDecl *FooRefDecl = nullptr;
537         FieldDecl *FooPtrDecl = nullptr;
538         FieldDecl *BazRefDecl = nullptr;
539         FieldDecl *BazPtrDecl = nullptr;
540         for (FieldDecl *Field : BarFields) {
541           if (Field->getNameAsString() == "FooRef") {
542             FooRefDecl = Field;
543           } else if (Field->getNameAsString() == "FooPtr") {
544             FooPtrDecl = Field;
545           } else if (Field->getNameAsString() == "BazRef") {
546             BazRefDecl = Field;
547           } else if (Field->getNameAsString() == "BazPtr") {
548             BazPtrDecl = Field;
549           } else {
550             FAIL() << "Unexpected field: " << Field->getNameAsString();
551           }
552         }
553         ASSERT_THAT(FooRefDecl, NotNull());
554         ASSERT_THAT(FooPtrDecl, NotNull());
555         ASSERT_THAT(BazRefDecl, NotNull());
556         ASSERT_THAT(BazPtrDecl, NotNull());
557 
558         const auto *FooLoc = cast<ScalarStorageLocation>(
559             Env.getStorageLocation(*FooDecl, SkipPast::None));
560         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
561         const auto *FooPointeeVal =
562             cast<StructValue>(Env.getValue(FooVal->getPointeeLoc()));
563 
564         const auto *BarVal =
565             cast<PointerValue>(FooPointeeVal->getChild(*BarDecl));
566         const auto *BarPointeeVal =
567             cast<StructValue>(Env.getValue(BarVal->getPointeeLoc()));
568 
569         const auto *FooRefVal =
570             cast<ReferenceValue>(BarPointeeVal->getChild(*FooRefDecl));
571         const StorageLocation &FooReferentLoc = FooRefVal->getReferentLoc();
572         EXPECT_THAT(Env.getValue(FooReferentLoc), IsNull());
573 
574         const auto *FooPtrVal =
575             cast<PointerValue>(BarPointeeVal->getChild(*FooPtrDecl));
576         const StorageLocation &FooPtrPointeeLoc = FooPtrVal->getPointeeLoc();
577         EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull());
578 
579         const auto *BazRefVal =
580             cast<ReferenceValue>(BarPointeeVal->getChild(*BazRefDecl));
581         const StorageLocation &BazReferentLoc = BazRefVal->getReferentLoc();
582         EXPECT_THAT(Env.getValue(BazReferentLoc), NotNull());
583 
584         const auto *BazPtrVal =
585             cast<PointerValue>(BarPointeeVal->getChild(*BazPtrDecl));
586         const StorageLocation &BazPtrPointeeLoc = BazPtrVal->getPointeeLoc();
587         EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull());
588       });
589 }
590 
591 TEST(TransferTest, MultipleVarsDecl) {
592   std::string Code = R"(
593     void target() {
594       int Foo, Bar;
595       (void)0;
596       // [[p]]
597     }
598   )";
599   runDataflow(Code,
600               [](llvm::ArrayRef<
601                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
602                      Results,
603                  ASTContext &ASTCtx) {
604                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
605                 const Environment &Env = Results[0].second.Env;
606 
607                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
608                 ASSERT_THAT(FooDecl, NotNull());
609 
610                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
611                 ASSERT_THAT(BarDecl, NotNull());
612 
613                 const StorageLocation *FooLoc =
614                     Env.getStorageLocation(*FooDecl, SkipPast::None);
615                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
616 
617                 const StorageLocation *BarLoc =
618                     Env.getStorageLocation(*BarDecl, SkipPast::None);
619                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
620 
621                 const Value *FooVal = Env.getValue(*FooLoc);
622                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
623 
624                 const Value *BarVal = Env.getValue(*BarLoc);
625                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
626               });
627 }
628 
629 TEST(TransferTest, JoinVarDecl) {
630   std::string Code = R"(
631     void target(bool B) {
632       int Foo;
633       // [[p1]]
634       if (B) {
635         int Bar;
636         // [[p2]]
637       } else {
638         int Baz;
639         // [[p3]]
640       }
641       (void)0;
642       // [[p4]]
643     }
644   )";
645   runDataflow(Code, [](llvm::ArrayRef<std::pair<
646                            std::string, DataflowAnalysisState<NoopLattice>>>
647                            Results,
648                        ASTContext &ASTCtx) {
649     ASSERT_THAT(Results, ElementsAre(Pair("p4", _), Pair("p3", _),
650                                      Pair("p2", _), Pair("p1", _)));
651     const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
652     ASSERT_THAT(FooDecl, NotNull());
653 
654     const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
655     ASSERT_THAT(BarDecl, NotNull());
656 
657     const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
658     ASSERT_THAT(BazDecl, NotNull());
659 
660     const Environment &Env1 = Results[3].second.Env;
661     const StorageLocation *FooLoc =
662         Env1.getStorageLocation(*FooDecl, SkipPast::None);
663     EXPECT_THAT(FooLoc, NotNull());
664     EXPECT_THAT(Env1.getStorageLocation(*BarDecl, SkipPast::None), IsNull());
665     EXPECT_THAT(Env1.getStorageLocation(*BazDecl, SkipPast::None), IsNull());
666 
667     const Environment &Env2 = Results[2].second.Env;
668     EXPECT_EQ(Env2.getStorageLocation(*FooDecl, SkipPast::None), FooLoc);
669     EXPECT_THAT(Env2.getStorageLocation(*BarDecl, SkipPast::None), NotNull());
670     EXPECT_THAT(Env2.getStorageLocation(*BazDecl, SkipPast::None), IsNull());
671 
672     const Environment &Env3 = Results[1].second.Env;
673     EXPECT_EQ(Env3.getStorageLocation(*FooDecl, SkipPast::None), FooLoc);
674     EXPECT_THAT(Env3.getStorageLocation(*BarDecl, SkipPast::None), IsNull());
675     EXPECT_THAT(Env3.getStorageLocation(*BazDecl, SkipPast::None), NotNull());
676 
677     const Environment &Env4 = Results[0].second.Env;
678     EXPECT_EQ(Env4.getStorageLocation(*FooDecl, SkipPast::None), FooLoc);
679     EXPECT_THAT(Env4.getStorageLocation(*BarDecl, SkipPast::None), IsNull());
680     EXPECT_THAT(Env4.getStorageLocation(*BazDecl, SkipPast::None), IsNull());
681   });
682 }
683 
684 TEST(TransferTest, BinaryOperatorAssign) {
685   std::string Code = R"(
686     void target() {
687       int Foo;
688       int Bar;
689       (Bar) = (Foo);
690       // [[p]]
691     }
692   )";
693   runDataflow(Code,
694               [](llvm::ArrayRef<
695                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
696                      Results,
697                  ASTContext &ASTCtx) {
698                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
699                 const Environment &Env = Results[0].second.Env;
700 
701                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
702                 ASSERT_THAT(FooDecl, NotNull());
703 
704                 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None);
705                 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
706 
707                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
708                 ASSERT_THAT(BarDecl, NotNull());
709 
710                 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal);
711               });
712 }
713 
714 TEST(TransferTest, VarDeclInitAssign) {
715   std::string Code = R"(
716     void target() {
717       int Foo;
718       int Bar = Foo;
719       // [[p]]
720     }
721   )";
722   runDataflow(Code,
723               [](llvm::ArrayRef<
724                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
725                      Results,
726                  ASTContext &ASTCtx) {
727                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
728                 const Environment &Env = Results[0].second.Env;
729 
730                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
731                 ASSERT_THAT(FooDecl, NotNull());
732 
733                 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None);
734                 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
735 
736                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
737                 ASSERT_THAT(BarDecl, NotNull());
738 
739                 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal);
740               });
741 }
742 
743 TEST(TransferTest, VarDeclInitAssignChained) {
744   std::string Code = R"(
745     void target() {
746       int Foo;
747       int Bar;
748       int Baz = (Bar = Foo);
749       // [[p]]
750     }
751   )";
752   runDataflow(Code,
753               [](llvm::ArrayRef<
754                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
755                      Results,
756                  ASTContext &ASTCtx) {
757                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
758                 const Environment &Env = Results[0].second.Env;
759 
760                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
761                 ASSERT_THAT(FooDecl, NotNull());
762 
763                 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None);
764                 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
765 
766                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
767                 ASSERT_THAT(BarDecl, NotNull());
768 
769                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
770                 ASSERT_THAT(BazDecl, NotNull());
771 
772                 EXPECT_EQ(Env.getValue(*BarDecl, SkipPast::None), FooVal);
773                 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), FooVal);
774               });
775 }
776 
777 TEST(TransferTest, VarDeclInitAssignPtrDeref) {
778   std::string Code = R"(
779     void target() {
780       int Foo;
781       int *Bar;
782       *(Bar) = Foo;
783       int Baz = *(Bar);
784       // [[p]]
785     }
786   )";
787   runDataflow(Code,
788               [](llvm::ArrayRef<
789                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
790                      Results,
791                  ASTContext &ASTCtx) {
792                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
793                 const Environment &Env = Results[0].second.Env;
794 
795                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
796                 ASSERT_THAT(FooDecl, NotNull());
797 
798                 const Value *FooVal = Env.getValue(*FooDecl, SkipPast::None);
799                 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
800 
801                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
802                 ASSERT_THAT(BarDecl, NotNull());
803 
804                 const auto *BarVal =
805                     cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
806                 EXPECT_EQ(Env.getValue(BarVal->getPointeeLoc()), FooVal);
807 
808                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
809                 ASSERT_THAT(BazDecl, NotNull());
810 
811                 EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), FooVal);
812               });
813 }
814 
815 TEST(TransferTest, AssignToAndFromReference) {
816   std::string Code = R"(
817     void target() {
818       int Foo;
819       int Bar;
820       int &Baz = Foo;
821       // [[p1]]
822       Baz = Bar;
823       int Qux = Baz;
824       int &Quux = Baz;
825       // [[p2]]
826     }
827   )";
828   runDataflow(
829       Code, [](llvm::ArrayRef<
830                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
831                    Results,
832                ASTContext &ASTCtx) {
833         ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
834         const Environment &Env1 = Results[0].second.Env;
835         const Environment &Env2 = Results[1].second.Env;
836 
837         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
838         ASSERT_THAT(FooDecl, NotNull());
839 
840         const Value *FooVal = Env1.getValue(*FooDecl, SkipPast::None);
841         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
842 
843         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
844         ASSERT_THAT(BarDecl, NotNull());
845 
846         const Value *BarVal = Env1.getValue(*BarDecl, SkipPast::None);
847         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
848 
849         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
850         ASSERT_THAT(BazDecl, NotNull());
851 
852         EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), FooVal);
853 
854         EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BarVal);
855         EXPECT_EQ(Env2.getValue(*FooDecl, SkipPast::None), BarVal);
856 
857         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
858         ASSERT_THAT(QuxDecl, NotNull());
859         EXPECT_EQ(Env2.getValue(*QuxDecl, SkipPast::None), BarVal);
860 
861         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
862         ASSERT_THAT(QuuxDecl, NotNull());
863         EXPECT_EQ(Env2.getValue(*QuuxDecl, SkipPast::Reference), BarVal);
864       });
865 }
866 
867 TEST(TransferTest, MultipleParamDecls) {
868   std::string Code = R"(
869     void target(int Foo, int Bar) {
870       (void)0;
871       // [[p]]
872     }
873   )";
874   runDataflow(Code,
875               [](llvm::ArrayRef<
876                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
877                      Results,
878                  ASTContext &ASTCtx) {
879                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
880                 const Environment &Env = Results[0].second.Env;
881 
882                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
883                 ASSERT_THAT(FooDecl, NotNull());
884 
885                 const StorageLocation *FooLoc =
886                     Env.getStorageLocation(*FooDecl, SkipPast::None);
887                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
888 
889                 const Value *FooVal = Env.getValue(*FooLoc);
890                 ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
891 
892                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
893                 ASSERT_THAT(BarDecl, NotNull());
894 
895                 const StorageLocation *BarLoc =
896                     Env.getStorageLocation(*BarDecl, SkipPast::None);
897                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
898 
899                 const Value *BarVal = Env.getValue(*BarLoc);
900                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
901               });
902 }
903 
904 TEST(TransferTest, StructParamDecl) {
905   std::string Code = R"(
906     struct A {
907       int Bar;
908     };
909 
910     void target(A Foo) {
911       (void)0;
912       // [[p]]
913     }
914   )";
915   runDataflow(
916       Code, [](llvm::ArrayRef<
917                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
918                    Results,
919                ASTContext &ASTCtx) {
920         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
921         const Environment &Env = Results[0].second.Env;
922 
923         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
924         ASSERT_THAT(FooDecl, NotNull());
925 
926         ASSERT_TRUE(FooDecl->getType()->isStructureType());
927         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
928 
929         FieldDecl *BarDecl = nullptr;
930         for (FieldDecl *Field : FooFields) {
931           if (Field->getNameAsString() == "Bar") {
932             BarDecl = Field;
933           } else {
934             FAIL() << "Unexpected field: " << Field->getNameAsString();
935           }
936         }
937         ASSERT_THAT(BarDecl, NotNull());
938 
939         const auto *FooLoc = cast<AggregateStorageLocation>(
940             Env.getStorageLocation(*FooDecl, SkipPast::None));
941         const auto *BarLoc =
942             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
943 
944         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
945         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
946         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
947       });
948 }
949 
950 TEST(TransferTest, ReferenceParamDecl) {
951   std::string Code = R"(
952     struct A {};
953 
954     void target(A &Foo) {
955       (void)0;
956       // [[p]]
957     }
958   )";
959   runDataflow(
960       Code, [](llvm::ArrayRef<
961                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
962                    Results,
963                ASTContext &ASTCtx) {
964         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
965         const Environment &Env = Results[0].second.Env;
966 
967         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
968         ASSERT_THAT(FooDecl, NotNull());
969 
970         const StorageLocation *FooLoc =
971             Env.getStorageLocation(*FooDecl, SkipPast::None);
972         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
973 
974         const ReferenceValue *FooVal =
975             dyn_cast<ReferenceValue>(Env.getValue(*FooLoc));
976         ASSERT_THAT(FooVal, NotNull());
977 
978         const StorageLocation &FooReferentLoc = FooVal->getReferentLoc();
979         EXPECT_TRUE(isa<AggregateStorageLocation>(&FooReferentLoc));
980 
981         const Value *FooReferentVal = Env.getValue(FooReferentLoc);
982         EXPECT_TRUE(isa_and_nonnull<StructValue>(FooReferentVal));
983       });
984 }
985 
986 TEST(TransferTest, PointerParamDecl) {
987   std::string Code = R"(
988     struct A {};
989 
990     void target(A *Foo) {
991       (void)0;
992       // [[p]]
993     }
994   )";
995   runDataflow(
996       Code, [](llvm::ArrayRef<
997                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
998                    Results,
999                ASTContext &ASTCtx) {
1000         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1001         const Environment &Env = Results[0].second.Env;
1002 
1003         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1004         ASSERT_THAT(FooDecl, NotNull());
1005 
1006         const StorageLocation *FooLoc =
1007             Env.getStorageLocation(*FooDecl, SkipPast::None);
1008         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1009 
1010         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
1011         const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
1012         EXPECT_TRUE(isa<AggregateStorageLocation>(&FooPointeeLoc));
1013 
1014         const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
1015         EXPECT_TRUE(isa_and_nonnull<StructValue>(FooPointeeVal));
1016       });
1017 }
1018 
1019 TEST(TransferTest, StructMember) {
1020   std::string Code = R"(
1021     struct A {
1022       int Bar;
1023     };
1024 
1025     void target(A Foo) {
1026       int Baz = Foo.Bar;
1027       // [[p]]
1028     }
1029   )";
1030   runDataflow(
1031       Code, [](llvm::ArrayRef<
1032                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1033                    Results,
1034                ASTContext &ASTCtx) {
1035         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1036         const Environment &Env = Results[0].second.Env;
1037 
1038         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1039         ASSERT_THAT(FooDecl, NotNull());
1040 
1041         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1042         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1043 
1044         FieldDecl *BarDecl = nullptr;
1045         for (FieldDecl *Field : FooFields) {
1046           if (Field->getNameAsString() == "Bar") {
1047             BarDecl = Field;
1048           } else {
1049             FAIL() << "Unexpected field: " << Field->getNameAsString();
1050           }
1051         }
1052         ASSERT_THAT(BarDecl, NotNull());
1053 
1054         const auto *FooLoc = cast<AggregateStorageLocation>(
1055             Env.getStorageLocation(*FooDecl, SkipPast::None));
1056         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1057         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1058 
1059         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1060         ASSERT_THAT(BazDecl, NotNull());
1061 
1062         EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal);
1063       });
1064 }
1065 
1066 TEST(TransferTest, DerivedBaseMemberClass) {
1067   std::string Code = R"(
1068     class A {
1069       int ADefault;
1070     protected:
1071       int AProtected;
1072     private:
1073       int APrivate;
1074     public:
1075       int APublic;
1076     };
1077 
1078     class B : public A {
1079       int BDefault;
1080     protected:
1081       int BProtected;
1082     private:
1083       int BPrivate;
1084     };
1085 
1086     void target() {
1087       B Foo;
1088       // [[p]]
1089     }
1090   )";
1091   runDataflow(
1092       Code, [](llvm::ArrayRef<
1093                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1094                    Results,
1095                ASTContext &ASTCtx) {
1096         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1097         const Environment &Env = Results[0].second.Env;
1098 
1099         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1100         ASSERT_THAT(FooDecl, NotNull());
1101         ASSERT_TRUE(FooDecl->getType()->isRecordType());
1102 
1103         // Derived-class fields.
1104         const FieldDecl *BDefaultDecl = nullptr;
1105         const FieldDecl *BProtectedDecl = nullptr;
1106         const FieldDecl *BPrivateDecl = nullptr;
1107         for (const FieldDecl *Field :
1108              FooDecl->getType()->getAsRecordDecl()->fields()) {
1109           if (Field->getNameAsString() == "BDefault") {
1110             BDefaultDecl = Field;
1111           } else if (Field->getNameAsString() == "BProtected") {
1112             BProtectedDecl = Field;
1113           } else if (Field->getNameAsString() == "BPrivate") {
1114             BPrivateDecl = Field;
1115           } else {
1116             FAIL() << "Unexpected field: " << Field->getNameAsString();
1117           }
1118         }
1119         ASSERT_THAT(BDefaultDecl, NotNull());
1120         ASSERT_THAT(BProtectedDecl, NotNull());
1121         ASSERT_THAT(BPrivateDecl, NotNull());
1122 
1123         // Base-class fields.
1124         const FieldDecl *ADefaultDecl = nullptr;
1125         const FieldDecl *APrivateDecl = nullptr;
1126         const FieldDecl *AProtectedDecl = nullptr;
1127         const FieldDecl *APublicDecl = nullptr;
1128         for (const clang::CXXBaseSpecifier &Base :
1129              FooDecl->getType()->getAsCXXRecordDecl()->bases()) {
1130           QualType BaseType = Base.getType();
1131           ASSERT_TRUE(BaseType->isRecordType());
1132           for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) {
1133             if (Field->getNameAsString() == "ADefault") {
1134               ADefaultDecl = Field;
1135             } else if (Field->getNameAsString() == "AProtected") {
1136               AProtectedDecl = Field;
1137             } else if (Field->getNameAsString() == "APrivate") {
1138               APrivateDecl = Field;
1139             } else if (Field->getNameAsString() == "APublic") {
1140               APublicDecl = Field;
1141             } else {
1142               FAIL() << "Unexpected field: " << Field->getNameAsString();
1143             }
1144           }
1145         }
1146         ASSERT_THAT(ADefaultDecl, NotNull());
1147         ASSERT_THAT(AProtectedDecl, NotNull());
1148         ASSERT_THAT(APrivateDecl, NotNull());
1149         ASSERT_THAT(APublicDecl, NotNull());
1150 
1151         const auto &FooLoc = *cast<AggregateStorageLocation>(
1152             Env.getStorageLocation(*FooDecl, SkipPast::None));
1153         const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc));
1154 
1155         // Note: we can't test presence of children in `FooLoc`, because
1156         // `getChild` requires its argument be present (or fails an assert). So,
1157         // we limit to testing presence in `FooVal` and coherence between the
1158         // two.
1159 
1160         // Base-class fields.
1161         EXPECT_THAT(FooVal.getChild(*ADefaultDecl), NotNull());
1162         EXPECT_THAT(FooVal.getChild(*APrivateDecl), NotNull());
1163 
1164         EXPECT_THAT(FooVal.getChild(*AProtectedDecl), NotNull());
1165         EXPECT_EQ(Env.getValue(FooLoc.getChild(*APublicDecl)),
1166                   FooVal.getChild(*APublicDecl));
1167         EXPECT_THAT(FooVal.getChild(*APublicDecl), NotNull());
1168         EXPECT_EQ(Env.getValue(FooLoc.getChild(*AProtectedDecl)),
1169                   FooVal.getChild(*AProtectedDecl));
1170 
1171         // Derived-class fields.
1172         EXPECT_THAT(FooVal.getChild(*BDefaultDecl), NotNull());
1173         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BDefaultDecl)),
1174                   FooVal.getChild(*BDefaultDecl));
1175         EXPECT_THAT(FooVal.getChild(*BProtectedDecl), NotNull());
1176         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BProtectedDecl)),
1177                   FooVal.getChild(*BProtectedDecl));
1178         EXPECT_THAT(FooVal.getChild(*BPrivateDecl), NotNull());
1179         EXPECT_EQ(Env.getValue(FooLoc.getChild(*BPrivateDecl)),
1180                   FooVal.getChild(*BPrivateDecl));
1181       });
1182 }
1183 
1184 static void derivedBaseMemberExpectations(
1185     llvm::ArrayRef<std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1186         Results,
1187     ASTContext &ASTCtx) {
1188   ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1189   const Environment &Env = Results[0].second.Env;
1190 
1191   const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1192   ASSERT_THAT(FooDecl, NotNull());
1193 
1194   ASSERT_TRUE(FooDecl->getType()->isRecordType());
1195   const FieldDecl *BarDecl = nullptr;
1196   for (const clang::CXXBaseSpecifier &Base :
1197        FooDecl->getType()->getAsCXXRecordDecl()->bases()) {
1198     QualType BaseType = Base.getType();
1199     ASSERT_TRUE(BaseType->isStructureType());
1200 
1201     for (const FieldDecl *Field : BaseType->getAsRecordDecl()->fields()) {
1202       if (Field->getNameAsString() == "Bar") {
1203         BarDecl = Field;
1204       } else {
1205         FAIL() << "Unexpected field: " << Field->getNameAsString();
1206       }
1207     }
1208   }
1209   ASSERT_THAT(BarDecl, NotNull());
1210 
1211   const auto &FooLoc = *cast<AggregateStorageLocation>(
1212       Env.getStorageLocation(*FooDecl, SkipPast::None));
1213   const auto &FooVal = *cast<StructValue>(Env.getValue(FooLoc));
1214   EXPECT_THAT(FooVal.getChild(*BarDecl), NotNull());
1215   EXPECT_EQ(Env.getValue(FooLoc.getChild(*BarDecl)), FooVal.getChild(*BarDecl));
1216 }
1217 
1218 TEST(TransferTest, DerivedBaseMemberStructDefault) {
1219   std::string Code = R"(
1220     struct A {
1221       int Bar;
1222     };
1223     struct B : public A {
1224     };
1225 
1226     void target() {
1227       B Foo;
1228       // [[p]]
1229     }
1230   )";
1231   runDataflow(Code, derivedBaseMemberExpectations);
1232 }
1233 
1234 TEST(TransferTest, DerivedBaseMemberPrivateFriend) {
1235   // Include an access to `Foo.Bar` to verify the analysis doesn't crash on that
1236   // access.
1237   std::string Code = R"(
1238     struct A {
1239     private:
1240       friend void target();
1241       int Bar;
1242     };
1243     struct B : public A {
1244     };
1245 
1246     void target() {
1247       B Foo;
1248       (void)Foo.Bar;
1249       // [[p]]
1250     }
1251   )";
1252   runDataflow(Code, derivedBaseMemberExpectations);
1253 }
1254 
1255 TEST(TransferTest, ClassMember) {
1256   std::string Code = R"(
1257     class A {
1258     public:
1259       int Bar;
1260     };
1261 
1262     void target(A Foo) {
1263       int Baz = Foo.Bar;
1264       // [[p]]
1265     }
1266   )";
1267   runDataflow(
1268       Code, [](llvm::ArrayRef<
1269                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1270                    Results,
1271                ASTContext &ASTCtx) {
1272         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1273         const Environment &Env = Results[0].second.Env;
1274 
1275         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1276         ASSERT_THAT(FooDecl, NotNull());
1277 
1278         ASSERT_TRUE(FooDecl->getType()->isClassType());
1279         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1280 
1281         FieldDecl *BarDecl = nullptr;
1282         for (FieldDecl *Field : FooFields) {
1283           if (Field->getNameAsString() == "Bar") {
1284             BarDecl = Field;
1285           } else {
1286             FAIL() << "Unexpected field: " << Field->getNameAsString();
1287           }
1288         }
1289         ASSERT_THAT(BarDecl, NotNull());
1290 
1291         const auto *FooLoc = cast<AggregateStorageLocation>(
1292             Env.getStorageLocation(*FooDecl, SkipPast::None));
1293         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1294         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1295 
1296         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1297         ASSERT_THAT(BazDecl, NotNull());
1298 
1299         EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarVal);
1300       });
1301 }
1302 
1303 TEST(TransferTest, BaseClassInitializer) {
1304   using ast_matchers::cxxConstructorDecl;
1305   using ast_matchers::hasName;
1306   using ast_matchers::ofClass;
1307 
1308   std::string Code = R"(
1309     class A {
1310     public:
1311       A(int I) : Bar(I) {}
1312       int Bar;
1313     };
1314 
1315     class B : public A {
1316     public:
1317       B(int I) : A(I) {
1318         (void)0;
1319         // [[p]]
1320       }
1321     };
1322   )";
1323   ASSERT_THAT_ERROR(
1324       test::checkDataflow<NoopAnalysis>(
1325           Code, cxxConstructorDecl(ofClass(hasName("B"))),
1326           [](ASTContext &C, Environment &) {
1327             return NoopAnalysis(C, /*ApplyBuiltinTransfer=*/true);
1328           },
1329           [](llvm::ArrayRef<
1330                  std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1331                  Results,
1332              ASTContext &ASTCtx) {
1333             // Regression test to verify that base-class initializers do not
1334             // trigger an assertion. If we add support for such initializers in
1335             // the future, we can expand this test to check more specific
1336             // properties.
1337             EXPECT_THAT(Results, ElementsAre(Pair("p", _)));
1338           },
1339           {"-fsyntax-only", "-fno-delayed-template-parsing",
1340            "-std=" + std::string(LangStandard::getLangStandardForKind(
1341                                      LangStandard::lang_cxx17)
1342                                      .getName())}),
1343       llvm::Succeeded());
1344 }
1345 
1346 TEST(TransferTest, ReferenceMember) {
1347   std::string Code = R"(
1348     struct A {
1349       int &Bar;
1350     };
1351 
1352     void target(A Foo) {
1353       int Baz = Foo.Bar;
1354       // [[p]]
1355     }
1356   )";
1357   runDataflow(
1358       Code, [](llvm::ArrayRef<
1359                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1360                    Results,
1361                ASTContext &ASTCtx) {
1362         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1363         const Environment &Env = Results[0].second.Env;
1364 
1365         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1366         ASSERT_THAT(FooDecl, NotNull());
1367 
1368         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1369         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1370 
1371         FieldDecl *BarDecl = nullptr;
1372         for (FieldDecl *Field : FooFields) {
1373           if (Field->getNameAsString() == "Bar") {
1374             BarDecl = Field;
1375           } else {
1376             FAIL() << "Unexpected field: " << Field->getNameAsString();
1377           }
1378         }
1379         ASSERT_THAT(BarDecl, NotNull());
1380 
1381         const auto *FooLoc = cast<AggregateStorageLocation>(
1382             Env.getStorageLocation(*FooDecl, SkipPast::None));
1383         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1384         const auto *BarVal = cast<ReferenceValue>(FooVal->getChild(*BarDecl));
1385         const auto *BarReferentVal =
1386             cast<IntegerValue>(Env.getValue(BarVal->getReferentLoc()));
1387 
1388         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1389         ASSERT_THAT(BazDecl, NotNull());
1390 
1391         EXPECT_EQ(Env.getValue(*BazDecl, SkipPast::None), BarReferentVal);
1392       });
1393 }
1394 
1395 TEST(TransferTest, StructThisMember) {
1396   std::string Code = R"(
1397     struct A {
1398       int Bar;
1399 
1400       struct B {
1401         int Baz;
1402       };
1403 
1404       B Qux;
1405 
1406       void target() {
1407         int Foo = Bar;
1408         int Quux = Qux.Baz;
1409         // [[p]]
1410       }
1411     };
1412   )";
1413   runDataflow(
1414       Code, [](llvm::ArrayRef<
1415                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1416                    Results,
1417                ASTContext &ASTCtx) {
1418         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1419         const Environment &Env = Results[0].second.Env;
1420 
1421         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1422             Env.getThisPointeeStorageLocation());
1423         ASSERT_THAT(ThisLoc, NotNull());
1424 
1425         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1426         ASSERT_THAT(BarDecl, NotNull());
1427 
1428         const auto *BarLoc =
1429             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1430         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1431 
1432         const Value *BarVal = Env.getValue(*BarLoc);
1433         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1434 
1435         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1436         ASSERT_THAT(FooDecl, NotNull());
1437         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1438 
1439         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1440         ASSERT_THAT(QuxDecl, NotNull());
1441 
1442         ASSERT_TRUE(QuxDecl->getType()->isStructureType());
1443         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1444 
1445         FieldDecl *BazDecl = nullptr;
1446         for (FieldDecl *Field : QuxFields) {
1447           if (Field->getNameAsString() == "Baz") {
1448             BazDecl = Field;
1449           } else {
1450             FAIL() << "Unexpected field: " << Field->getNameAsString();
1451           }
1452         }
1453         ASSERT_THAT(BazDecl, NotNull());
1454 
1455         const auto *QuxLoc =
1456             cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl));
1457         const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc));
1458         ASSERT_THAT(QuxVal, NotNull());
1459 
1460         const auto *BazLoc =
1461             cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl));
1462         const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl));
1463         EXPECT_EQ(Env.getValue(*BazLoc), BazVal);
1464 
1465         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1466         ASSERT_THAT(QuuxDecl, NotNull());
1467         EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal);
1468       });
1469 }
1470 
1471 TEST(TransferTest, ClassThisMember) {
1472   std::string Code = R"(
1473     class A {
1474       int Bar;
1475 
1476       class B {
1477       public:
1478         int Baz;
1479       };
1480 
1481       B Qux;
1482 
1483       void target() {
1484         int Foo = Bar;
1485         int Quux = Qux.Baz;
1486         // [[p]]
1487       }
1488     };
1489   )";
1490   runDataflow(
1491       Code, [](llvm::ArrayRef<
1492                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1493                    Results,
1494                ASTContext &ASTCtx) {
1495         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1496         const Environment &Env = Results[0].second.Env;
1497 
1498         const auto *ThisLoc =
1499             cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation());
1500 
1501         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1502         ASSERT_THAT(BarDecl, NotNull());
1503 
1504         const auto *BarLoc =
1505             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1506         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1507 
1508         const Value *BarVal = Env.getValue(*BarLoc);
1509         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1510 
1511         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1512         ASSERT_THAT(FooDecl, NotNull());
1513         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1514 
1515         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1516         ASSERT_THAT(QuxDecl, NotNull());
1517 
1518         ASSERT_TRUE(QuxDecl->getType()->isClassType());
1519         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1520 
1521         FieldDecl *BazDecl = nullptr;
1522         for (FieldDecl *Field : QuxFields) {
1523           if (Field->getNameAsString() == "Baz") {
1524             BazDecl = Field;
1525           } else {
1526             FAIL() << "Unexpected field: " << Field->getNameAsString();
1527           }
1528         }
1529         ASSERT_THAT(BazDecl, NotNull());
1530 
1531         const auto *QuxLoc =
1532             cast<AggregateStorageLocation>(&ThisLoc->getChild(*QuxDecl));
1533         const auto *QuxVal = dyn_cast<StructValue>(Env.getValue(*QuxLoc));
1534         ASSERT_THAT(QuxVal, NotNull());
1535 
1536         const auto *BazLoc =
1537             cast<ScalarStorageLocation>(&QuxLoc->getChild(*BazDecl));
1538         const auto *BazVal = cast<IntegerValue>(QuxVal->getChild(*BazDecl));
1539         EXPECT_EQ(Env.getValue(*BazLoc), BazVal);
1540 
1541         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1542         ASSERT_THAT(QuuxDecl, NotNull());
1543         EXPECT_EQ(Env.getValue(*QuuxDecl, SkipPast::None), BazVal);
1544       });
1545 }
1546 
1547 TEST(TransferTest, StructThisInLambda) {
1548   std::string ThisCaptureCode = R"(
1549     struct A {
1550       void frob() {
1551         [this]() {
1552           int Foo = Bar;
1553           // [[p1]]
1554         }();
1555       }
1556 
1557       int Bar;
1558     };
1559   )";
1560   runDataflow(
1561       ThisCaptureCode,
1562       [](llvm::ArrayRef<
1563              std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1564              Results,
1565          ASTContext &ASTCtx) {
1566         ASSERT_THAT(Results, ElementsAre(Pair("p1", _)));
1567         const Environment &Env = Results[0].second.Env;
1568 
1569         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1570             Env.getThisPointeeStorageLocation());
1571         ASSERT_THAT(ThisLoc, NotNull());
1572 
1573         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1574         ASSERT_THAT(BarDecl, NotNull());
1575 
1576         const auto *BarLoc =
1577             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1578         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1579 
1580         const Value *BarVal = Env.getValue(*BarLoc);
1581         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1582 
1583         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1584         ASSERT_THAT(FooDecl, NotNull());
1585         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1586       },
1587       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1588 
1589   std::string RefCaptureDefaultCode = R"(
1590     struct A {
1591       void frob() {
1592         [&]() {
1593           int Foo = Bar;
1594           // [[p2]]
1595         }();
1596       }
1597 
1598       int Bar;
1599     };
1600   )";
1601   runDataflow(
1602       RefCaptureDefaultCode,
1603       [](llvm::ArrayRef<
1604              std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1605              Results,
1606          ASTContext &ASTCtx) {
1607         ASSERT_THAT(Results, ElementsAre(Pair("p2", _)));
1608         const Environment &Env = Results[0].second.Env;
1609 
1610         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1611             Env.getThisPointeeStorageLocation());
1612         ASSERT_THAT(ThisLoc, NotNull());
1613 
1614         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1615         ASSERT_THAT(BarDecl, NotNull());
1616 
1617         const auto *BarLoc =
1618             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1619         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1620 
1621         const Value *BarVal = Env.getValue(*BarLoc);
1622         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1623 
1624         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1625         ASSERT_THAT(FooDecl, NotNull());
1626         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1627       },
1628       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1629 
1630   std::string FreeFunctionLambdaCode = R"(
1631     void foo() {
1632       int Bar;
1633       [&]() {
1634         int Foo = Bar;
1635         // [[p3]]
1636       }();
1637     }
1638   )";
1639   runDataflow(
1640       FreeFunctionLambdaCode,
1641       [](llvm::ArrayRef<
1642              std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1643              Results,
1644          ASTContext &ASTCtx) {
1645         ASSERT_THAT(Results, ElementsAre(Pair("p3", _)));
1646         const Environment &Env = Results[0].second.Env;
1647 
1648         EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull());
1649       },
1650       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1651 }
1652 
1653 TEST(TransferTest, ConstructorInitializer) {
1654   std::string Code = R"(
1655     struct target {
1656       int Bar;
1657 
1658       target(int Foo) : Bar(Foo) {
1659         int Qux = Bar;
1660         // [[p]]
1661       }
1662     };
1663   )";
1664   runDataflow(Code,
1665               [](llvm::ArrayRef<
1666                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1667                      Results,
1668                  ASTContext &ASTCtx) {
1669                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1670                 const Environment &Env = Results[0].second.Env;
1671 
1672                 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1673                     Env.getThisPointeeStorageLocation());
1674                 ASSERT_THAT(ThisLoc, NotNull());
1675 
1676                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1677                 ASSERT_THAT(FooDecl, NotNull());
1678 
1679                 const auto *FooVal =
1680                     cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None));
1681 
1682                 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1683                 ASSERT_THAT(QuxDecl, NotNull());
1684                 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal);
1685               });
1686 }
1687 
1688 TEST(TransferTest, DefaultInitializer) {
1689   std::string Code = R"(
1690     struct target {
1691       int Bar;
1692       int Baz = Bar;
1693 
1694       target(int Foo) : Bar(Foo) {
1695         int Qux = Baz;
1696         // [[p]]
1697       }
1698     };
1699   )";
1700   runDataflow(Code,
1701               [](llvm::ArrayRef<
1702                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1703                      Results,
1704                  ASTContext &ASTCtx) {
1705                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1706                 const Environment &Env = Results[0].second.Env;
1707 
1708                 const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1709                     Env.getThisPointeeStorageLocation());
1710                 ASSERT_THAT(ThisLoc, NotNull());
1711 
1712                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1713                 ASSERT_THAT(FooDecl, NotNull());
1714 
1715                 const auto *FooVal =
1716                     cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None));
1717 
1718                 const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1719                 ASSERT_THAT(QuxDecl, NotNull());
1720                 EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal);
1721               });
1722 }
1723 
1724 TEST(TransferTest, DefaultInitializerReference) {
1725   std::string Code = R"(
1726     struct target {
1727       int &Bar;
1728       int &Baz = Bar;
1729 
1730       target(int &Foo) : Bar(Foo) {
1731         int &Qux = Baz;
1732         // [[p]]
1733       }
1734     };
1735   )";
1736   runDataflow(
1737       Code, [](llvm::ArrayRef<
1738                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1739                    Results,
1740                ASTContext &ASTCtx) {
1741         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1742         const Environment &Env = Results[0].second.Env;
1743 
1744         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1745             Env.getThisPointeeStorageLocation());
1746         ASSERT_THAT(ThisLoc, NotNull());
1747 
1748         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1749         ASSERT_THAT(FooDecl, NotNull());
1750 
1751         const auto *FooVal =
1752             cast<ReferenceValue>(Env.getValue(*FooDecl, SkipPast::None));
1753 
1754         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1755         ASSERT_THAT(QuxDecl, NotNull());
1756 
1757         const auto *QuxVal =
1758             cast<ReferenceValue>(Env.getValue(*QuxDecl, SkipPast::None));
1759         EXPECT_EQ(&QuxVal->getReferentLoc(), &FooVal->getReferentLoc());
1760       });
1761 }
1762 
1763 TEST(TransferTest, TemporaryObject) {
1764   std::string Code = R"(
1765     struct A {
1766       int Bar;
1767     };
1768 
1769     void target() {
1770       A Foo = A();
1771       // [[p]]
1772     }
1773   )";
1774   runDataflow(
1775       Code, [](llvm::ArrayRef<
1776                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1777                    Results,
1778                ASTContext &ASTCtx) {
1779         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1780         const Environment &Env = Results[0].second.Env;
1781 
1782         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1783         ASSERT_THAT(FooDecl, NotNull());
1784 
1785         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1786         ASSERT_THAT(BarDecl, NotNull());
1787 
1788         const auto *FooLoc = cast<AggregateStorageLocation>(
1789             Env.getStorageLocation(*FooDecl, SkipPast::None));
1790         const auto *BarLoc =
1791             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
1792 
1793         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1794         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1795         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
1796       });
1797 }
1798 
1799 TEST(TransferTest, ElidableConstructor) {
1800   // This test is effectively the same as TransferTest.TemporaryObject, but
1801   // the code is compiled as C++ 14.
1802   std::string Code = R"(
1803     struct A {
1804       int Bar;
1805     };
1806 
1807     void target() {
1808       A Foo = A();
1809       // [[p]]
1810     }
1811   )";
1812   runDataflow(
1813       Code,
1814       [](llvm::ArrayRef<
1815              std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1816              Results,
1817          ASTContext &ASTCtx) {
1818         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1819         const Environment &Env = Results[0].second.Env;
1820 
1821         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1822         ASSERT_THAT(FooDecl, NotNull());
1823 
1824         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1825         ASSERT_THAT(BarDecl, NotNull());
1826 
1827         const auto *FooLoc = cast<AggregateStorageLocation>(
1828             Env.getStorageLocation(*FooDecl, SkipPast::None));
1829         const auto *BarLoc =
1830             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
1831 
1832         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1833         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1834         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
1835       },
1836       LangStandard::lang_cxx14);
1837 }
1838 
1839 TEST(TransferTest, AssignmentOperator) {
1840   std::string Code = R"(
1841     struct A {
1842       int Baz;
1843     };
1844 
1845     void target() {
1846       A Foo;
1847       A Bar;
1848       // [[p1]]
1849       Foo = Bar;
1850       // [[p2]]
1851     }
1852   )";
1853   runDataflow(
1854       Code, [](llvm::ArrayRef<
1855                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1856                    Results,
1857                ASTContext &ASTCtx) {
1858         ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
1859         const Environment &Env1 = Results[0].second.Env;
1860         const Environment &Env2 = Results[1].second.Env;
1861 
1862         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1863         ASSERT_THAT(FooDecl, NotNull());
1864 
1865         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1866         ASSERT_THAT(BarDecl, NotNull());
1867 
1868         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1869         ASSERT_THAT(BazDecl, NotNull());
1870 
1871         const auto *FooLoc1 = cast<AggregateStorageLocation>(
1872             Env1.getStorageLocation(*FooDecl, SkipPast::None));
1873         const auto *BarLoc1 = cast<AggregateStorageLocation>(
1874             Env1.getStorageLocation(*BarDecl, SkipPast::None));
1875 
1876         const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1));
1877         const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1));
1878         EXPECT_NE(FooVal1, BarVal1);
1879 
1880         const auto *FooBazVal1 =
1881             cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl)));
1882         const auto *BarBazVal1 =
1883             cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl)));
1884         EXPECT_NE(FooBazVal1, BarBazVal1);
1885 
1886         const auto *FooLoc2 = cast<AggregateStorageLocation>(
1887             Env2.getStorageLocation(*FooDecl, SkipPast::None));
1888         const auto *BarLoc2 = cast<AggregateStorageLocation>(
1889             Env2.getStorageLocation(*BarDecl, SkipPast::None));
1890 
1891         const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2));
1892         const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2));
1893         EXPECT_EQ(FooVal2, BarVal2);
1894 
1895         const auto *FooBazVal2 =
1896             cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl)));
1897         const auto *BarBazVal2 =
1898             cast<IntegerValue>(Env2.getValue(BarLoc1->getChild(*BazDecl)));
1899         EXPECT_EQ(FooBazVal2, BarBazVal2);
1900       });
1901 }
1902 
1903 TEST(TransferTest, CopyConstructor) {
1904   std::string Code = R"(
1905     struct A {
1906       int Baz;
1907     };
1908 
1909     void target() {
1910       A Foo;
1911       A Bar = Foo;
1912       // [[p]]
1913     }
1914   )";
1915   runDataflow(
1916       Code, [](llvm::ArrayRef<
1917                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1918                    Results,
1919                ASTContext &ASTCtx) {
1920         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1921         const Environment &Env = Results[0].second.Env;
1922 
1923         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1924         ASSERT_THAT(FooDecl, NotNull());
1925 
1926         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1927         ASSERT_THAT(BarDecl, NotNull());
1928 
1929         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1930         ASSERT_THAT(BazDecl, NotNull());
1931 
1932         const auto *FooLoc = cast<AggregateStorageLocation>(
1933             Env.getStorageLocation(*FooDecl, SkipPast::None));
1934         const auto *BarLoc = cast<AggregateStorageLocation>(
1935             Env.getStorageLocation(*BarDecl, SkipPast::None));
1936 
1937         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1938         const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc));
1939         EXPECT_EQ(FooVal, BarVal);
1940 
1941         const auto *FooBazVal =
1942             cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl)));
1943         const auto *BarBazVal =
1944             cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl)));
1945         EXPECT_EQ(FooBazVal, BarBazVal);
1946       });
1947 }
1948 
1949 TEST(TransferTest, CopyConstructorWithParens) {
1950   std::string Code = R"(
1951     struct A {
1952       int Baz;
1953     };
1954 
1955     void target() {
1956       A Foo;
1957       A Bar((A(Foo)));
1958       // [[p]]
1959     }
1960   )";
1961   runDataflow(
1962       Code, [](llvm::ArrayRef<
1963                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
1964                    Results,
1965                ASTContext &ASTCtx) {
1966         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
1967         const Environment &Env = Results[0].second.Env;
1968 
1969         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1970         ASSERT_THAT(FooDecl, NotNull());
1971 
1972         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1973         ASSERT_THAT(BarDecl, NotNull());
1974 
1975         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1976         ASSERT_THAT(BazDecl, NotNull());
1977 
1978         const auto *FooLoc = cast<AggregateStorageLocation>(
1979             Env.getStorageLocation(*FooDecl, SkipPast::None));
1980         const auto *BarLoc = cast<AggregateStorageLocation>(
1981             Env.getStorageLocation(*BarDecl, SkipPast::None));
1982 
1983         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1984         const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc));
1985         EXPECT_EQ(FooVal, BarVal);
1986 
1987         const auto *FooBazVal =
1988             cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl)));
1989         const auto *BarBazVal =
1990             cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl)));
1991         EXPECT_EQ(FooBazVal, BarBazVal);
1992       });
1993 }
1994 
1995 TEST(TransferTest, MoveConstructor) {
1996   std::string Code = R"(
1997     namespace std {
1998 
1999     template <typename T> struct remove_reference      { using type = T; };
2000     template <typename T> struct remove_reference<T&>  { using type = T; };
2001     template <typename T> struct remove_reference<T&&> { using type = T; };
2002 
2003     template <typename T>
2004     using remove_reference_t = typename remove_reference<T>::type;
2005 
2006     template <typename T>
2007     std::remove_reference_t<T>&& move(T&& x);
2008 
2009     } // namespace std
2010 
2011     struct A {
2012       int Baz;
2013     };
2014 
2015     void target() {
2016       A Foo;
2017       A Bar;
2018       // [[p1]]
2019       Foo = std::move(Bar);
2020       // [[p2]]
2021     }
2022   )";
2023   runDataflow(
2024       Code, [](llvm::ArrayRef<
2025                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2026                    Results,
2027                ASTContext &ASTCtx) {
2028         ASSERT_THAT(Results, ElementsAre(Pair("p1", _), Pair("p2", _)));
2029         const Environment &Env1 = Results[0].second.Env;
2030         const Environment &Env2 = Results[1].second.Env;
2031 
2032         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2033         ASSERT_THAT(FooDecl, NotNull());
2034 
2035         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2036         ASSERT_THAT(BarDecl, NotNull());
2037 
2038         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2039         ASSERT_THAT(BazDecl, NotNull());
2040 
2041         const auto *FooLoc1 = cast<AggregateStorageLocation>(
2042             Env1.getStorageLocation(*FooDecl, SkipPast::None));
2043         const auto *BarLoc1 = cast<AggregateStorageLocation>(
2044             Env1.getStorageLocation(*BarDecl, SkipPast::None));
2045 
2046         const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1));
2047         const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1));
2048         EXPECT_NE(FooVal1, BarVal1);
2049 
2050         const auto *FooBazVal1 =
2051             cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl)));
2052         const auto *BarBazVal1 =
2053             cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl)));
2054         EXPECT_NE(FooBazVal1, BarBazVal1);
2055 
2056         const auto *FooLoc2 = cast<AggregateStorageLocation>(
2057             Env2.getStorageLocation(*FooDecl, SkipPast::None));
2058         const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2));
2059         EXPECT_EQ(FooVal2, BarVal1);
2060 
2061         const auto *FooBazVal2 =
2062             cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl)));
2063         EXPECT_EQ(FooBazVal2, BarBazVal1);
2064       });
2065 }
2066 
2067 TEST(TransferTest, BindTemporary) {
2068   std::string Code = R"(
2069     struct A {
2070       virtual ~A() = default;
2071 
2072       int Baz;
2073     };
2074 
2075     void target(A Foo) {
2076       int Bar = A(Foo).Baz;
2077       // [[p]]
2078     }
2079   )";
2080   runDataflow(Code,
2081               [](llvm::ArrayRef<
2082                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2083                      Results,
2084                  ASTContext &ASTCtx) {
2085                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2086                 const Environment &Env = Results[0].second.Env;
2087 
2088                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2089                 ASSERT_THAT(FooDecl, NotNull());
2090 
2091                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2092                 ASSERT_THAT(BarDecl, NotNull());
2093 
2094                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2095                 ASSERT_THAT(BazDecl, NotNull());
2096 
2097                 const auto &FooVal =
2098                     *cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None));
2099                 const auto *BarVal =
2100                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2101                 EXPECT_EQ(BarVal, FooVal.getChild(*BazDecl));
2102               });
2103 }
2104 
2105 TEST(TransferTest, StaticCast) {
2106   std::string Code = R"(
2107     void target(int Foo) {
2108       int Bar = static_cast<int>(Foo);
2109       // [[p]]
2110     }
2111   )";
2112   runDataflow(Code,
2113               [](llvm::ArrayRef<
2114                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2115                      Results,
2116                  ASTContext &ASTCtx) {
2117                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2118                 const Environment &Env = Results[0].second.Env;
2119 
2120                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2121                 ASSERT_THAT(FooDecl, NotNull());
2122 
2123                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2124                 ASSERT_THAT(BarDecl, NotNull());
2125 
2126                 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2127                 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2128                 EXPECT_TRUE(isa<IntegerValue>(FooVal));
2129                 EXPECT_TRUE(isa<IntegerValue>(BarVal));
2130                 EXPECT_EQ(FooVal, BarVal);
2131               });
2132 }
2133 
2134 TEST(TransferTest, IntegralCast) {
2135   std::string Code = R"(
2136     void target(int Foo) {
2137       long Bar = Foo;
2138       // [[p]]
2139     }
2140   )";
2141   runDataflow(Code,
2142               [](llvm::ArrayRef<
2143                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2144                      Results,
2145                  ASTContext &ASTCtx) {
2146                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2147                 const Environment &Env = Results[0].second.Env;
2148 
2149                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2150                 ASSERT_THAT(FooDecl, NotNull());
2151 
2152                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2153                 ASSERT_THAT(BarDecl, NotNull());
2154 
2155                 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2156                 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2157                 EXPECT_TRUE(isa<IntegerValue>(FooVal));
2158                 EXPECT_TRUE(isa<IntegerValue>(BarVal));
2159                 EXPECT_EQ(FooVal, BarVal);
2160               });
2161 }
2162 
2163 TEST(TransferTest, IntegraltoBooleanCast) {
2164   std::string Code = R"(
2165     void target(int Foo) {
2166       bool Bar = Foo;
2167       // [[p]]
2168     }
2169   )";
2170   runDataflow(Code,
2171               [](llvm::ArrayRef<
2172                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2173                      Results,
2174                  ASTContext &ASTCtx) {
2175                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2176                 const Environment &Env = Results[0].second.Env;
2177 
2178                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2179                 ASSERT_THAT(FooDecl, NotNull());
2180 
2181                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2182                 ASSERT_THAT(BarDecl, NotNull());
2183 
2184                 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2185                 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2186                 EXPECT_TRUE(isa<IntegerValue>(FooVal));
2187                 EXPECT_TRUE(isa<BoolValue>(BarVal));
2188               });
2189 }
2190 
2191 TEST(TransferTest, IntegralToBooleanCastFromBool) {
2192   std::string Code = R"(
2193     void target(bool Foo) {
2194       int Zab = Foo;
2195       bool Bar = Zab;
2196       // [[p]]
2197     }
2198   )";
2199   runDataflow(Code,
2200               [](llvm::ArrayRef<
2201                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2202                      Results,
2203                  ASTContext &ASTCtx) {
2204                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2205                 const Environment &Env = Results[0].second.Env;
2206 
2207                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2208                 ASSERT_THAT(FooDecl, NotNull());
2209 
2210                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2211                 ASSERT_THAT(BarDecl, NotNull());
2212 
2213                 const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2214                 const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2215                 EXPECT_TRUE(isa<BoolValue>(FooVal));
2216                 EXPECT_TRUE(isa<BoolValue>(BarVal));
2217                 EXPECT_EQ(FooVal, BarVal);
2218               });
2219 }
2220 
2221 TEST(TransferTest, NullToPointerCast) {
2222   std::string Code = R"(
2223     using my_nullptr_t = decltype(nullptr);
2224     struct Baz {};
2225     void target() {
2226       int *FooX = nullptr;
2227       int *FooY = nullptr;
2228       bool **Bar = nullptr;
2229       Baz *Baz = nullptr;
2230       my_nullptr_t Null = 0;
2231       // [[p]]
2232     }
2233   )";
2234   runDataflow(Code,
2235               [](llvm::ArrayRef<
2236                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2237                      Results,
2238                  ASTContext &ASTCtx) {
2239                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2240                 const Environment &Env = Results[0].second.Env;
2241 
2242                 const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
2243                 ASSERT_THAT(FooXDecl, NotNull());
2244 
2245                 const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
2246                 ASSERT_THAT(FooYDecl, NotNull());
2247 
2248                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2249                 ASSERT_THAT(BarDecl, NotNull());
2250 
2251                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2252                 ASSERT_THAT(BazDecl, NotNull());
2253 
2254                 const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
2255                 ASSERT_THAT(NullDecl, NotNull());
2256 
2257                 const auto *FooXVal =
2258                     cast<PointerValue>(Env.getValue(*FooXDecl, SkipPast::None));
2259                 const auto *FooYVal =
2260                     cast<PointerValue>(Env.getValue(*FooYDecl, SkipPast::None));
2261                 const auto *BarVal =
2262                     cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
2263                 const auto *BazVal =
2264                     cast<PointerValue>(Env.getValue(*BazDecl, SkipPast::None));
2265                 const auto *NullVal =
2266                     cast<PointerValue>(Env.getValue(*NullDecl, SkipPast::None));
2267 
2268                 EXPECT_EQ(FooXVal, FooYVal);
2269                 EXPECT_NE(FooXVal, BarVal);
2270                 EXPECT_NE(FooXVal, BazVal);
2271                 EXPECT_NE(BarVal, BazVal);
2272 
2273                 const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
2274                 EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
2275                 EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
2276 
2277                 const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
2278                 EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
2279                 EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
2280 
2281                 const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
2282                 EXPECT_TRUE(isa<AggregateStorageLocation>(BazPointeeLoc));
2283                 EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull());
2284 
2285                 const StorageLocation &NullPointeeLoc =
2286                     NullVal->getPointeeLoc();
2287                 EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
2288                 EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
2289               });
2290 }
2291 
2292 TEST(TransferTest, NullToMemberPointerCast) {
2293   std::string Code = R"(
2294     struct Foo {};
2295     void target(Foo *Foo) {
2296       int Foo::*MemberPointer = nullptr;
2297       // [[p]]
2298     }
2299   )";
2300   runDataflow(
2301       Code, [](llvm::ArrayRef<
2302                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2303                    Results,
2304                ASTContext &ASTCtx) {
2305         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2306         const Environment &Env = Results[0].second.Env;
2307 
2308         const ValueDecl *MemberPointerDecl =
2309             findValueDecl(ASTCtx, "MemberPointer");
2310         ASSERT_THAT(MemberPointerDecl, NotNull());
2311 
2312         const auto *MemberPointerVal = cast<PointerValue>(
2313             Env.getValue(*MemberPointerDecl, SkipPast::None));
2314 
2315         const StorageLocation &MemberLoc = MemberPointerVal->getPointeeLoc();
2316         EXPECT_THAT(Env.getValue(MemberLoc), IsNull());
2317       });
2318 }
2319 
2320 TEST(TransferTest, AddrOfValue) {
2321   std::string Code = R"(
2322     void target() {
2323       int Foo;
2324       int *Bar = &Foo;
2325       // [[p]]
2326     }
2327   )";
2328   runDataflow(Code,
2329               [](llvm::ArrayRef<
2330                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2331                      Results,
2332                  ASTContext &ASTCtx) {
2333                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2334                 const Environment &Env = Results[0].second.Env;
2335 
2336                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2337                 ASSERT_THAT(FooDecl, NotNull());
2338 
2339                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2340                 ASSERT_THAT(BarDecl, NotNull());
2341 
2342                 const auto *FooLoc = cast<ScalarStorageLocation>(
2343                     Env.getStorageLocation(*FooDecl, SkipPast::None));
2344                 const auto *BarVal =
2345                     cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
2346                 EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
2347               });
2348 }
2349 
2350 TEST(TransferTest, AddrOfReference) {
2351   std::string Code = R"(
2352     void target(int *Foo) {
2353       int *Bar = &(*Foo);
2354       // [[p]]
2355     }
2356   )";
2357   runDataflow(Code,
2358               [](llvm::ArrayRef<
2359                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2360                      Results,
2361                  ASTContext &ASTCtx) {
2362                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2363                 const Environment &Env = Results[0].second.Env;
2364 
2365                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2366                 ASSERT_THAT(FooDecl, NotNull());
2367 
2368                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2369                 ASSERT_THAT(BarDecl, NotNull());
2370 
2371                 const auto *FooVal =
2372                     cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2373                 const auto *BarVal =
2374                     cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
2375                 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
2376               });
2377 }
2378 
2379 TEST(TransferTest, DerefDependentPtr) {
2380   std::string Code = R"(
2381     template <typename T>
2382     void target(T *Foo) {
2383       T &Bar = *Foo;
2384       /*[[p]]*/
2385     }
2386   )";
2387   runDataflow(
2388       Code, [](llvm::ArrayRef<
2389                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2390                    Results,
2391                ASTContext &ASTCtx) {
2392         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2393         const Environment &Env = Results[0].second.Env;
2394 
2395         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2396         ASSERT_THAT(FooDecl, NotNull());
2397 
2398         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2399         ASSERT_THAT(BarDecl, NotNull());
2400 
2401         const auto *FooVal =
2402             cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2403         const auto *BarVal =
2404             cast<ReferenceValue>(Env.getValue(*BarDecl, SkipPast::None));
2405         EXPECT_EQ(&BarVal->getReferentLoc(), &FooVal->getPointeeLoc());
2406       });
2407 }
2408 
2409 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
2410   std::string Code = R"(
2411     struct A {};
2412 
2413     void target(A Foo, A Bar, bool Cond) {
2414       A Baz = Cond ?  Foo : Bar;
2415       /*[[p]]*/
2416     }
2417   )";
2418   runDataflow(
2419       Code, [](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 *FooDecl = findValueDecl(ASTCtx, "Foo");
2427         ASSERT_THAT(FooDecl, NotNull());
2428 
2429         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2430         ASSERT_THAT(BarDecl, NotNull());
2431 
2432         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2433         ASSERT_THAT(BazDecl, NotNull());
2434 
2435         const auto *FooVal =
2436             cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None));
2437         const auto *BarVal =
2438             cast<StructValue>(Env.getValue(*BarDecl, SkipPast::None));
2439 
2440         const auto *BazVal =
2441             dyn_cast<StructValue>(Env.getValue(*BazDecl, SkipPast::None));
2442         ASSERT_THAT(BazVal, NotNull());
2443 
2444         EXPECT_NE(BazVal, FooVal);
2445         EXPECT_NE(BazVal, BarVal);
2446       });
2447 }
2448 
2449 TEST(TransferTest, VarDeclInDoWhile) {
2450   std::string Code = R"(
2451     void target(int *Foo) {
2452       do {
2453         int Bar = *Foo;
2454       } while (true);
2455       (void)0;
2456       /*[[p]]*/
2457     }
2458   )";
2459   runDataflow(Code,
2460               [](llvm::ArrayRef<
2461                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2462                      Results,
2463                  ASTContext &ASTCtx) {
2464                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2465                 const Environment &Env = Results[0].second.Env;
2466 
2467                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2468                 ASSERT_THAT(FooDecl, NotNull());
2469 
2470                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2471                 ASSERT_THAT(BarDecl, NotNull());
2472 
2473                 const auto *FooVal =
2474                     cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2475                 const auto *FooPointeeVal =
2476                     cast<IntegerValue>(Env.getValue(FooVal->getPointeeLoc()));
2477 
2478                 const auto *BarVal = dyn_cast_or_null<IntegerValue>(
2479                     Env.getValue(*BarDecl, SkipPast::None));
2480                 ASSERT_THAT(BarVal, NotNull());
2481 
2482                 EXPECT_EQ(BarVal, FooPointeeVal);
2483               });
2484 }
2485 
2486 TEST(TransferTest, AggregateInitialization) {
2487   std::string BracesCode = R"(
2488     struct A {
2489       int Foo;
2490     };
2491 
2492     struct B {
2493       int Bar;
2494       A Baz;
2495       int Qux;
2496     };
2497 
2498     void target(int BarArg, int FooArg, int QuxArg) {
2499       B Quux{BarArg, {FooArg}, QuxArg};
2500       /*[[p]]*/
2501     }
2502   )";
2503   std::string BraceEllisionCode = R"(
2504     struct A {
2505       int Foo;
2506     };
2507 
2508     struct B {
2509       int Bar;
2510       A Baz;
2511       int Qux;
2512     };
2513 
2514     void target(int BarArg, int FooArg, int QuxArg) {
2515       B Quux = {BarArg, FooArg, QuxArg};
2516       /*[[p]]*/
2517     }
2518   )";
2519   for (const std::string &Code : {BracesCode, BraceEllisionCode}) {
2520     runDataflow(
2521         Code, [](llvm::ArrayRef<
2522                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2523                      Results,
2524                  ASTContext &ASTCtx) {
2525           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2526           const Environment &Env = Results[0].second.Env;
2527 
2528           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2529           ASSERT_THAT(FooDecl, NotNull());
2530 
2531           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2532           ASSERT_THAT(BarDecl, NotNull());
2533 
2534           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2535           ASSERT_THAT(BazDecl, NotNull());
2536 
2537           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2538           ASSERT_THAT(QuxDecl, NotNull());
2539 
2540           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
2541           ASSERT_THAT(FooArgDecl, NotNull());
2542 
2543           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
2544           ASSERT_THAT(BarArgDecl, NotNull());
2545 
2546           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
2547           ASSERT_THAT(QuxArgDecl, NotNull());
2548 
2549           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
2550           ASSERT_THAT(QuuxDecl, NotNull());
2551 
2552           const auto *FooArgVal =
2553               cast<IntegerValue>(Env.getValue(*FooArgDecl, SkipPast::None));
2554           const auto *BarArgVal =
2555               cast<IntegerValue>(Env.getValue(*BarArgDecl, SkipPast::None));
2556           const auto *QuxArgVal =
2557               cast<IntegerValue>(Env.getValue(*QuxArgDecl, SkipPast::None));
2558 
2559           const auto *QuuxVal =
2560               cast<StructValue>(Env.getValue(*QuuxDecl, SkipPast::None));
2561           ASSERT_THAT(QuuxVal, NotNull());
2562 
2563           const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl));
2564           ASSERT_THAT(BazVal, NotNull());
2565 
2566           EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal);
2567           EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal);
2568           EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal);
2569         });
2570   }
2571 }
2572 
2573 TEST(TransferTest, AssignToUnionMember) {
2574   std::string Code = R"(
2575     union A {
2576       int Foo;
2577     };
2578 
2579     void target(int Bar) {
2580       A Baz;
2581       Baz.Foo = Bar;
2582       // [[p]]
2583     }
2584   )";
2585   runDataflow(Code,
2586               [](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 *BazDecl = findValueDecl(ASTCtx, "Baz");
2594                 ASSERT_THAT(BazDecl, NotNull());
2595                 ASSERT_TRUE(BazDecl->getType()->isUnionType());
2596 
2597                 const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>(
2598                     Env.getStorageLocation(*BazDecl, SkipPast::None));
2599                 ASSERT_THAT(BazLoc, NotNull());
2600 
2601                 // FIXME: Add support for union types.
2602                 EXPECT_THAT(Env.getValue(*BazLoc), IsNull());
2603               });
2604 }
2605 
2606 TEST(TransferTest, AssignFromBoolLiteral) {
2607   std::string Code = R"(
2608     void target() {
2609       bool Foo = true;
2610       bool Bar = false;
2611       // [[p]]
2612     }
2613   )";
2614   runDataflow(Code,
2615               [](llvm::ArrayRef<
2616                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2617                      Results,
2618                  ASTContext &ASTCtx) {
2619                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2620                 const Environment &Env = Results[0].second.Env;
2621 
2622                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2623                 ASSERT_THAT(FooDecl, NotNull());
2624 
2625                 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>(
2626                     Env.getValue(*FooDecl, SkipPast::None));
2627                 ASSERT_THAT(FooVal, NotNull());
2628 
2629                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2630                 ASSERT_THAT(BarDecl, NotNull());
2631 
2632                 const auto *BarVal = dyn_cast_or_null<AtomicBoolValue>(
2633                     Env.getValue(*BarDecl, SkipPast::None));
2634                 ASSERT_THAT(BarVal, NotNull());
2635 
2636                 EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
2637                 EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
2638               });
2639 }
2640 
2641 TEST(TransferTest, AssignFromCompositeBoolExpression) {
2642   {
2643     std::string Code = R"(
2644     void target(bool Foo, bool Bar, bool Qux) {
2645       bool Baz = (Foo) && (Bar || Qux);
2646       // [[p]]
2647     }
2648   )";
2649     runDataflow(
2650         Code, [](llvm::ArrayRef<
2651                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2652                      Results,
2653                  ASTContext &ASTCtx) {
2654           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2655           const Environment &Env = Results[0].second.Env;
2656 
2657           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2658           ASSERT_THAT(FooDecl, NotNull());
2659 
2660           const auto *FooVal = dyn_cast_or_null<BoolValue>(
2661               Env.getValue(*FooDecl, SkipPast::None));
2662           ASSERT_THAT(FooVal, NotNull());
2663 
2664           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2665           ASSERT_THAT(BarDecl, NotNull());
2666 
2667           const auto *BarVal = dyn_cast_or_null<BoolValue>(
2668               Env.getValue(*BarDecl, SkipPast::None));
2669           ASSERT_THAT(BarVal, NotNull());
2670 
2671           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2672           ASSERT_THAT(QuxDecl, NotNull());
2673 
2674           const auto *QuxVal = dyn_cast_or_null<BoolValue>(
2675               Env.getValue(*QuxDecl, SkipPast::None));
2676           ASSERT_THAT(QuxVal, NotNull());
2677 
2678           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2679           ASSERT_THAT(BazDecl, NotNull());
2680 
2681           const auto *BazVal = dyn_cast_or_null<ConjunctionValue>(
2682               Env.getValue(*BazDecl, SkipPast::None));
2683           ASSERT_THAT(BazVal, NotNull());
2684           EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
2685 
2686           const auto *BazRightSubValVal =
2687               cast<DisjunctionValue>(&BazVal->getRightSubValue());
2688           EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal);
2689           EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal);
2690         });
2691   }
2692 
2693   {
2694     std::string Code = R"(
2695     void target(bool Foo, bool Bar, bool Qux) {
2696       bool Baz = (Foo && Qux) || (Bar);
2697       // [[p]]
2698     }
2699   )";
2700     runDataflow(
2701         Code, [](llvm::ArrayRef<
2702                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2703                      Results,
2704                  ASTContext &ASTCtx) {
2705           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2706           const Environment &Env = Results[0].second.Env;
2707 
2708           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2709           ASSERT_THAT(FooDecl, NotNull());
2710 
2711           const auto *FooVal = dyn_cast_or_null<BoolValue>(
2712               Env.getValue(*FooDecl, SkipPast::None));
2713           ASSERT_THAT(FooVal, NotNull());
2714 
2715           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2716           ASSERT_THAT(BarDecl, NotNull());
2717 
2718           const auto *BarVal = dyn_cast_or_null<BoolValue>(
2719               Env.getValue(*BarDecl, SkipPast::None));
2720           ASSERT_THAT(BarVal, NotNull());
2721 
2722           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2723           ASSERT_THAT(QuxDecl, NotNull());
2724 
2725           const auto *QuxVal = dyn_cast_or_null<BoolValue>(
2726               Env.getValue(*QuxDecl, SkipPast::None));
2727           ASSERT_THAT(QuxVal, NotNull());
2728 
2729           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2730           ASSERT_THAT(BazDecl, NotNull());
2731 
2732           const auto *BazVal = dyn_cast_or_null<DisjunctionValue>(
2733               Env.getValue(*BazDecl, SkipPast::None));
2734           ASSERT_THAT(BazVal, NotNull());
2735 
2736           const auto *BazLeftSubValVal =
2737               cast<ConjunctionValue>(&BazVal->getLeftSubValue());
2738           EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal);
2739           EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal);
2740 
2741           EXPECT_EQ(&BazVal->getRightSubValue(), BarVal);
2742         });
2743   }
2744 
2745   {
2746     std::string Code = R"(
2747       void target(bool A, bool B, bool C, bool D) {
2748         bool Foo = ((A && B) && C) && D;
2749         // [[p]]
2750       }
2751     )";
2752     runDataflow(
2753         Code, [](llvm::ArrayRef<
2754                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2755                      Results,
2756                  ASTContext &ASTCtx) {
2757           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2758           const Environment &Env = Results[0].second.Env;
2759 
2760           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
2761           ASSERT_THAT(ADecl, NotNull());
2762 
2763           const auto *AVal =
2764               dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl, SkipPast::None));
2765           ASSERT_THAT(AVal, NotNull());
2766 
2767           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
2768           ASSERT_THAT(BDecl, NotNull());
2769 
2770           const auto *BVal =
2771               dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl, SkipPast::None));
2772           ASSERT_THAT(BVal, NotNull());
2773 
2774           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
2775           ASSERT_THAT(CDecl, NotNull());
2776 
2777           const auto *CVal =
2778               dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
2779           ASSERT_THAT(CVal, NotNull());
2780 
2781           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
2782           ASSERT_THAT(DDecl, NotNull());
2783 
2784           const auto *DVal =
2785               dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl, SkipPast::None));
2786           ASSERT_THAT(DVal, NotNull());
2787 
2788           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2789           ASSERT_THAT(FooDecl, NotNull());
2790 
2791           const auto *FooVal = dyn_cast_or_null<ConjunctionValue>(
2792               Env.getValue(*FooDecl, SkipPast::None));
2793           ASSERT_THAT(FooVal, NotNull());
2794 
2795           const auto &FooLeftSubVal =
2796               cast<ConjunctionValue>(FooVal->getLeftSubValue());
2797           const auto &FooLeftLeftSubVal =
2798               cast<ConjunctionValue>(FooLeftSubVal.getLeftSubValue());
2799           EXPECT_EQ(&FooLeftLeftSubVal.getLeftSubValue(), AVal);
2800           EXPECT_EQ(&FooLeftLeftSubVal.getRightSubValue(), BVal);
2801           EXPECT_EQ(&FooLeftSubVal.getRightSubValue(), CVal);
2802           EXPECT_EQ(&FooVal->getRightSubValue(), DVal);
2803         });
2804   }
2805 }
2806 
2807 TEST(TransferTest, AssignFromBoolNegation) {
2808   std::string Code = R"(
2809     void target() {
2810       bool Foo = true;
2811       bool Bar = !(Foo);
2812       // [[p]]
2813     }
2814   )";
2815   runDataflow(Code,
2816               [](llvm::ArrayRef<
2817                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2818                      Results,
2819                  ASTContext &ASTCtx) {
2820                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2821                 const Environment &Env = Results[0].second.Env;
2822 
2823                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2824                 ASSERT_THAT(FooDecl, NotNull());
2825 
2826                 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>(
2827                     Env.getValue(*FooDecl, SkipPast::None));
2828                 ASSERT_THAT(FooVal, NotNull());
2829 
2830                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2831                 ASSERT_THAT(BarDecl, NotNull());
2832 
2833                 const auto *BarVal = dyn_cast_or_null<NegationValue>(
2834                     Env.getValue(*BarDecl, SkipPast::None));
2835                 ASSERT_THAT(BarVal, NotNull());
2836 
2837                 EXPECT_EQ(&BarVal->getSubVal(), FooVal);
2838               });
2839 }
2840 
2841 TEST(TransferTest, BuiltinExpect) {
2842   std::string Code = R"(
2843     void target(long Foo) {
2844       long Bar = __builtin_expect(Foo, true);
2845       /*[[p]]*/
2846     }
2847   )";
2848   runDataflow(Code,
2849               [](llvm::ArrayRef<
2850                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2851                      Results,
2852                  ASTContext &ASTCtx) {
2853                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2854                 const auto &Env = Results[0].second.Env;
2855 
2856                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2857                 ASSERT_THAT(FooDecl, NotNull());
2858 
2859                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2860                 ASSERT_THAT(BarDecl, NotNull());
2861 
2862                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2863                           Env.getValue(*BarDecl, SkipPast::None));
2864               });
2865 }
2866 
2867 // `__builtin_expect` takes and returns a `long` argument, so other types
2868 // involve casts. This verifies that we identify the input and output in that
2869 // case.
2870 TEST(TransferTest, BuiltinExpectBoolArg) {
2871   std::string Code = R"(
2872     void target(bool Foo) {
2873       bool Bar = __builtin_expect(Foo, true);
2874       /*[[p]]*/
2875     }
2876   )";
2877   runDataflow(Code,
2878               [](llvm::ArrayRef<
2879                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2880                      Results,
2881                  ASTContext &ASTCtx) {
2882                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2883                 const auto &Env = Results[0].second.Env;
2884 
2885                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2886                 ASSERT_THAT(FooDecl, NotNull());
2887 
2888                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2889                 ASSERT_THAT(BarDecl, NotNull());
2890 
2891                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2892                           Env.getValue(*BarDecl, SkipPast::None));
2893               });
2894 }
2895 
2896 TEST(TransferTest, BuiltinUnreachable) {
2897   std::string Code = R"(
2898     void target(bool Foo) {
2899       bool Bar = false;
2900       if (Foo)
2901         Bar = Foo;
2902       else
2903         __builtin_unreachable();
2904       (void)0;
2905       /*[[p]]*/
2906     }
2907   )";
2908   runDataflow(Code,
2909               [](llvm::ArrayRef<
2910                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2911                      Results,
2912                  ASTContext &ASTCtx) {
2913                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2914                 const auto &Env = Results[0].second.Env;
2915 
2916                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2917                 ASSERT_THAT(FooDecl, NotNull());
2918 
2919                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2920                 ASSERT_THAT(BarDecl, NotNull());
2921 
2922                 // `__builtin_unreachable` promises that the code is
2923                 // unreachable, so the compiler treats the "then" branch as the
2924                 // only possible predecessor of this statement.
2925                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2926                           Env.getValue(*BarDecl, SkipPast::None));
2927               });
2928 }
2929 
2930 TEST(TransferTest, BuiltinTrap) {
2931   std::string Code = R"(
2932     void target(bool Foo) {
2933       bool Bar = false;
2934       if (Foo)
2935         Bar = Foo;
2936       else
2937         __builtin_trap();
2938       (void)0;
2939       /*[[p]]*/
2940     }
2941   )";
2942   runDataflow(Code,
2943               [](llvm::ArrayRef<
2944                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2945                      Results,
2946                  ASTContext &ASTCtx) {
2947                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2948                 const auto &Env = Results[0].second.Env;
2949 
2950                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2951                 ASSERT_THAT(FooDecl, NotNull());
2952 
2953                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2954                 ASSERT_THAT(BarDecl, NotNull());
2955 
2956                 // `__builtin_trap` ensures program termination, so only the
2957                 // "then" branch is a predecessor of this statement.
2958                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2959                           Env.getValue(*BarDecl, SkipPast::None));
2960               });
2961 }
2962 
2963 TEST(TransferTest, BuiltinDebugTrap) {
2964   std::string Code = R"(
2965     void target(bool Foo) {
2966       bool Bar = false;
2967       if (Foo)
2968         Bar = Foo;
2969       else
2970         __builtin_debugtrap();
2971       (void)0;
2972       /*[[p]]*/
2973     }
2974   )";
2975   runDataflow(Code,
2976               [](llvm::ArrayRef<
2977                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2978                      Results,
2979                  ASTContext &ASTCtx) {
2980                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2981                 const auto &Env = Results[0].second.Env;
2982 
2983                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2984                 ASSERT_THAT(FooDecl, NotNull());
2985 
2986                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2987                 ASSERT_THAT(BarDecl, NotNull());
2988 
2989                 // `__builtin_debugtrap` doesn't ensure program termination.
2990                 EXPECT_NE(Env.getValue(*FooDecl, SkipPast::None),
2991                           Env.getValue(*BarDecl, SkipPast::None));
2992               });
2993 }
2994 
2995 TEST(TransferTest, StaticIntSingleVarDecl) {
2996   std::string Code = R"(
2997     void target() {
2998       static int Foo;
2999       // [[p]]
3000     }
3001   )";
3002   runDataflow(Code,
3003               [](llvm::ArrayRef<
3004                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3005                      Results,
3006                  ASTContext &ASTCtx) {
3007                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3008                 const Environment &Env = Results[0].second.Env;
3009 
3010                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3011                 ASSERT_THAT(FooDecl, NotNull());
3012 
3013                 const StorageLocation *FooLoc =
3014                     Env.getStorageLocation(*FooDecl, SkipPast::None);
3015                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3016 
3017                 const Value *FooVal = Env.getValue(*FooLoc);
3018                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3019               });
3020 }
3021 
3022 TEST(TransferTest, StaticIntGroupVarDecl) {
3023   std::string Code = R"(
3024     void target() {
3025       static int Foo, Bar;
3026       (void)0;
3027       // [[p]]
3028     }
3029   )";
3030   runDataflow(Code,
3031               [](llvm::ArrayRef<
3032                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3033                      Results,
3034                  ASTContext &ASTCtx) {
3035                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3036                 const Environment &Env = Results[0].second.Env;
3037 
3038                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3039                 ASSERT_THAT(FooDecl, NotNull());
3040 
3041                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3042                 ASSERT_THAT(BarDecl, NotNull());
3043 
3044                 const StorageLocation *FooLoc =
3045                     Env.getStorageLocation(*FooDecl, SkipPast::None);
3046                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3047 
3048                 const StorageLocation *BarLoc =
3049                     Env.getStorageLocation(*BarDecl, SkipPast::None);
3050                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3051 
3052                 const Value *FooVal = Env.getValue(*FooLoc);
3053                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3054 
3055                 const Value *BarVal = Env.getValue(*BarLoc);
3056                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
3057 
3058                 EXPECT_NE(FooVal, BarVal);
3059               });
3060 }
3061 
3062 TEST(TransferTest, GlobalIntVarDecl) {
3063   std::string Code = R"(
3064     static int Foo;
3065 
3066     void target() {
3067       int Bar = Foo;
3068       int Baz = Foo;
3069       // [[p]]
3070     }
3071   )";
3072   runDataflow(Code,
3073               [](llvm::ArrayRef<
3074                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3075                      Results,
3076                  ASTContext &ASTCtx) {
3077                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3078                 const Environment &Env = Results[0].second.Env;
3079 
3080                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3081                 ASSERT_THAT(BarDecl, NotNull());
3082 
3083                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3084                 ASSERT_THAT(BazDecl, NotNull());
3085 
3086                 const Value *BarVal =
3087                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3088                 const Value *BazVal =
3089                     cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
3090                 EXPECT_EQ(BarVal, BazVal);
3091               });
3092 }
3093 
3094 TEST(TransferTest, StaticMemberIntVarDecl) {
3095   std::string Code = R"(
3096     struct A {
3097       static int Foo;
3098     };
3099 
3100     void target(A a) {
3101       int Bar = a.Foo;
3102       int Baz = a.Foo;
3103       // [[p]]
3104     }
3105   )";
3106   runDataflow(Code,
3107               [](llvm::ArrayRef<
3108                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3109                      Results,
3110                  ASTContext &ASTCtx) {
3111                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3112                 const Environment &Env = Results[0].second.Env;
3113 
3114                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3115                 ASSERT_THAT(BarDecl, NotNull());
3116 
3117                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3118                 ASSERT_THAT(BazDecl, NotNull());
3119 
3120                 const Value *BarVal =
3121                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3122                 const Value *BazVal =
3123                     cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
3124                 EXPECT_EQ(BarVal, BazVal);
3125               });
3126 }
3127 
3128 TEST(TransferTest, StaticMemberRefVarDecl) {
3129   std::string Code = R"(
3130     struct A {
3131       static int &Foo;
3132     };
3133 
3134     void target(A a) {
3135       int Bar = a.Foo;
3136       int Baz = a.Foo;
3137       // [[p]]
3138     }
3139   )";
3140   runDataflow(Code,
3141               [](llvm::ArrayRef<
3142                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3143                      Results,
3144                  ASTContext &ASTCtx) {
3145                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3146                 const Environment &Env = Results[0].second.Env;
3147 
3148                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3149                 ASSERT_THAT(BarDecl, NotNull());
3150 
3151                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3152                 ASSERT_THAT(BazDecl, NotNull());
3153 
3154                 const Value *BarVal =
3155                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3156                 const Value *BazVal =
3157                     cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
3158                 EXPECT_EQ(BarVal, BazVal);
3159               });
3160 }
3161 
3162 TEST(TransferTest, AssignMemberBeforeCopy) {
3163   std::string Code = R"(
3164     struct A {
3165       int Foo;
3166     };
3167 
3168     void target() {
3169       A A1;
3170       A A2;
3171       int Bar;
3172       A1.Foo = Bar;
3173       A2 = A1;
3174       // [[p]]
3175     }
3176   )";
3177   runDataflow(Code,
3178               [](llvm::ArrayRef<
3179                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3180                      Results,
3181                  ASTContext &ASTCtx) {
3182                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3183                 const Environment &Env = Results[0].second.Env;
3184 
3185                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3186                 ASSERT_THAT(FooDecl, NotNull());
3187 
3188                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3189                 ASSERT_THAT(BarDecl, NotNull());
3190 
3191                 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
3192                 ASSERT_THAT(A1Decl, NotNull());
3193 
3194                 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
3195                 ASSERT_THAT(A2Decl, NotNull());
3196 
3197                 const auto *BarVal =
3198                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3199 
3200                 const auto *A2Val =
3201                     cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None));
3202                 EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal);
3203               });
3204 }
3205 
3206 TEST(TransferTest, BooleanEquality) {
3207   std::string Code = R"(
3208     void target(bool Bar) {
3209       bool Foo = true;
3210       if (Bar == Foo) {
3211         (void)0;
3212         /*[[p-then]]*/
3213       } else {
3214         (void)0;
3215         /*[[p-else]]*/
3216       }
3217     }
3218   )";
3219   runDataflow(
3220       Code, [](llvm::ArrayRef<
3221                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3222                    Results,
3223                ASTContext &ASTCtx) {
3224         ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _)));
3225         const Environment &EnvElse = Results[0].second.Env;
3226         const Environment &EnvThen = Results[1].second.Env;
3227 
3228         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3229         ASSERT_THAT(BarDecl, NotNull());
3230 
3231         auto &BarValThen =
3232             *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None));
3233         EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen));
3234 
3235         auto &BarValElse =
3236             *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None));
3237         EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse));
3238       });
3239 }
3240 
3241 TEST(TransferTest, BooleanInequality) {
3242   std::string Code = R"(
3243     void target(bool Bar) {
3244       bool Foo = true;
3245       if (Bar != Foo) {
3246         (void)0;
3247         /*[[p-then]]*/
3248       } else {
3249         (void)0;
3250         /*[[p-else]]*/
3251       }
3252     }
3253   )";
3254   runDataflow(
3255       Code, [](llvm::ArrayRef<
3256                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3257                    Results,
3258                ASTContext &ASTCtx) {
3259         ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _)));
3260         const Environment &EnvElse = Results[0].second.Env;
3261         const Environment &EnvThen = Results[1].second.Env;
3262 
3263         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3264         ASSERT_THAT(BarDecl, NotNull());
3265 
3266         auto &BarValThen =
3267             *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None));
3268         EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen));
3269 
3270         auto &BarValElse =
3271             *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None));
3272         EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse));
3273       });
3274 }
3275 
3276 TEST(TransferTest, CorrelatedBranches) {
3277   std::string Code = R"(
3278     void target(bool B, bool C) {
3279       if (B) {
3280         return;
3281       }
3282       (void)0;
3283       /*[[p0]]*/
3284       if (C) {
3285         B = true;
3286         /*[[p1]]*/
3287       }
3288       if (B) {
3289         (void)0;
3290         /*[[p2]]*/
3291       }
3292     }
3293   )";
3294   runDataflow(
3295       Code, [](llvm::ArrayRef<
3296                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3297                    Results,
3298                ASTContext &ASTCtx) {
3299         ASSERT_THAT(Results, SizeIs(3));
3300 
3301         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3302         ASSERT_THAT(CDecl, NotNull());
3303 
3304         {
3305           ASSERT_THAT(Results[2], Pair("p0", _));
3306           const Environment &Env = Results[2].second.Env;
3307           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3308           ASSERT_THAT(BDecl, NotNull());
3309           auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl, SkipPast::None));
3310 
3311           EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal)));
3312         }
3313 
3314         {
3315           ASSERT_THAT(Results[1], Pair("p1", _));
3316           const Environment &Env = Results[1].second.Env;
3317           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
3318           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3319         }
3320 
3321         {
3322           ASSERT_THAT(Results[0], Pair("p2", _));
3323           const Environment &Env = Results[0].second.Env;
3324           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
3325           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3326         }
3327       });
3328 }
3329 
3330 TEST(TransferTest, LoopWithAssignmentConverges) {
3331   std::string Code = R"(
3332 
3333     bool &foo();
3334 
3335     void target() {
3336        do {
3337         bool Bar = foo();
3338         if (Bar) break;
3339         (void)Bar;
3340         /*[[p]]*/
3341       } while (true);
3342     }
3343   )";
3344   // The key property that we are verifying is implicit in `runDataflow` --
3345   // namely, that the analysis succeeds, rather than hitting the maximum number
3346   // of iterations.
3347   runDataflow(
3348       Code, [](llvm::ArrayRef<
3349                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3350                    Results,
3351                ASTContext &ASTCtx) {
3352         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3353         const Environment &Env = Results[0].second.Env;
3354 
3355         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3356         ASSERT_THAT(BarDecl, NotNull());
3357 
3358         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
3359         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3360       });
3361 }
3362 
3363 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
3364   std::string Code = R"(
3365 
3366     bool &foo();
3367 
3368     void target() {
3369        do {
3370         bool& Bar = foo();
3371         if (Bar) break;
3372         (void)Bar;
3373         /*[[p]]*/
3374       } while (true);
3375     }
3376   )";
3377   // The key property that we are verifying is implicit in `runDataflow` --
3378   // namely, that the analysis succeeds, rather than hitting the maximum number
3379   // of iterations.
3380   runDataflow(
3381       Code, [](llvm::ArrayRef<
3382                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3383                    Results,
3384                ASTContext &ASTCtx) {
3385         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3386         const Environment &Env = Results[0].second.Env;
3387 
3388         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3389         ASSERT_THAT(BarDecl, NotNull());
3390 
3391         auto &BarVal =
3392             *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::Reference));
3393         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3394       });
3395 }
3396 
3397 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
3398   std::string Code = R"(
3399     struct Lookup {
3400       int x;
3401     };
3402 
3403     void target(Lookup val, bool b) {
3404       const Lookup* l = nullptr;
3405       while (b) {
3406         l = &val;
3407         /*[[p-inner]]*/
3408       }
3409       (void)0;
3410       /*[[p-outer]]*/
3411     }
3412   )";
3413   // The key property that we are verifying is implicit in `runDataflow` --
3414   // namely, that the analysis succeeds, rather than hitting the maximum number
3415   // of iterations.
3416   runDataflow(
3417       Code, [](llvm::ArrayRef<
3418                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3419                    Results,
3420                ASTContext &ASTCtx) {
3421         ASSERT_THAT(Results,
3422                     ElementsAre(Pair("p-outer", _), Pair("p-inner", _)));
3423         const Environment &OuterEnv = Results[0].second.Env;
3424         const Environment &InnerEnv = Results[1].second.Env;
3425 
3426         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
3427         ASSERT_THAT(ValDecl, NotNull());
3428 
3429         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
3430         ASSERT_THAT(LDecl, NotNull());
3431 
3432         // Inner.
3433         auto *LVal =
3434             dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl, SkipPast::None));
3435         ASSERT_THAT(LVal, NotNull());
3436 
3437         EXPECT_EQ(&LVal->getPointeeLoc(),
3438                   InnerEnv.getStorageLocation(*ValDecl, SkipPast::Reference));
3439 
3440         // Outer.
3441         LVal =
3442             dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl, SkipPast::None));
3443         ASSERT_THAT(LVal, NotNull());
3444 
3445         // The loop body may not have been executed, so we should not conclude
3446         // that `l` points to `val`.
3447         EXPECT_NE(&LVal->getPointeeLoc(),
3448                   OuterEnv.getStorageLocation(*ValDecl, SkipPast::Reference));
3449       });
3450 }
3451 
3452 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
3453   std::string Code = R"(
3454     union Union {
3455       int A;
3456       float B;
3457     };
3458 
3459     void foo() {
3460       Union A;
3461       Union B;
3462       A = B;
3463     }
3464   )";
3465   // This is a crash regression test when calling the transfer function on a
3466   // `CXXThisExpr` that refers to a union.
3467   runDataflow(
3468       Code,
3469       [](llvm::ArrayRef<
3470              std::pair<std::string, DataflowAnalysisState<NoopLattice>>>,
3471          ASTContext &) {},
3472       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
3473 }
3474 
3475 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
3476   std::string Code = R"(
3477     struct A {
3478       int Foo;
3479       int Bar;
3480     };
3481 
3482     void target() {
3483       int Qux;
3484       A Baz;
3485       Baz.Foo = Qux;
3486       auto &FooRef = Baz.Foo;
3487       auto &BarRef = Baz.Bar;
3488       auto &[BoundFooRef, BoundBarRef] = Baz;
3489       // [[p]]
3490     }
3491   )";
3492   runDataflow(
3493       Code, [](llvm::ArrayRef<
3494                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3495                    Results,
3496                ASTContext &ASTCtx) {
3497         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3498         const Environment &Env = Results[0].second.Env;
3499 
3500         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3501         ASSERT_THAT(FooRefDecl, NotNull());
3502 
3503         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3504         ASSERT_THAT(BarRefDecl, NotNull());
3505 
3506         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3507         ASSERT_THAT(QuxDecl, NotNull());
3508 
3509         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3510         ASSERT_THAT(BoundFooRefDecl, NotNull());
3511 
3512         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3513         ASSERT_THAT(BoundBarRefDecl, NotNull());
3514 
3515         const StorageLocation *FooRefLoc =
3516             Env.getStorageLocation(*FooRefDecl, SkipPast::Reference);
3517         ASSERT_THAT(FooRefLoc, NotNull());
3518 
3519         const StorageLocation *BarRefLoc =
3520             Env.getStorageLocation(*BarRefDecl, SkipPast::Reference);
3521         ASSERT_THAT(BarRefLoc, NotNull());
3522 
3523         const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None);
3524         ASSERT_THAT(QuxVal, NotNull());
3525 
3526         const StorageLocation *BoundFooRefLoc =
3527             Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference);
3528         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3529 
3530         const StorageLocation *BoundBarRefLoc =
3531             Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference);
3532         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3533 
3534         EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal);
3535       });
3536 }
3537 
3538 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
3539   std::string Code = R"(
3540     struct A {
3541       int &Foo;
3542       int &Bar;
3543     };
3544 
3545     void target(A Baz) {
3546       int Qux;
3547       Baz.Foo = Qux;
3548       auto &FooRef = Baz.Foo;
3549       auto &BarRef = Baz.Bar;
3550       auto &[BoundFooRef, BoundBarRef] = Baz;
3551       // [[p]]
3552     }
3553   )";
3554   runDataflow(
3555       Code, [](llvm::ArrayRef<
3556                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3557                    Results,
3558                ASTContext &ASTCtx) {
3559         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3560         const Environment &Env = Results[0].second.Env;
3561 
3562         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3563         ASSERT_THAT(FooRefDecl, NotNull());
3564 
3565         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3566         ASSERT_THAT(BarRefDecl, NotNull());
3567 
3568         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3569         ASSERT_THAT(QuxDecl, NotNull());
3570 
3571         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3572         ASSERT_THAT(BoundFooRefDecl, NotNull());
3573 
3574         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3575         ASSERT_THAT(BoundBarRefDecl, NotNull());
3576 
3577         const StorageLocation *FooRefLoc =
3578             Env.getStorageLocation(*FooRefDecl, SkipPast::Reference);
3579         ASSERT_THAT(FooRefLoc, NotNull());
3580 
3581         const StorageLocation *BarRefLoc =
3582             Env.getStorageLocation(*BarRefDecl, SkipPast::Reference);
3583         ASSERT_THAT(BarRefLoc, NotNull());
3584 
3585         const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None);
3586         ASSERT_THAT(QuxVal, NotNull());
3587 
3588         const StorageLocation *BoundFooRefLoc =
3589             Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference);
3590         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3591 
3592         const StorageLocation *BoundBarRefLoc =
3593             Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference);
3594         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3595 
3596         EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal);
3597       });
3598 }
3599 
3600 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
3601   std::string Code = R"(
3602     struct A {
3603       int Foo;
3604       int Bar;
3605     };
3606 
3607     void target() {
3608       int Qux;
3609       A Baz;
3610       Baz.Foo = Qux;
3611       auto &FooRef = Baz.Foo;
3612       auto &BarRef = Baz.Bar;
3613       auto [BoundFoo, BoundBar] = Baz;
3614       // [[p]]
3615     }
3616   )";
3617   runDataflow(
3618       Code, [](llvm::ArrayRef<
3619                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3620                    Results,
3621                ASTContext &ASTCtx) {
3622         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3623         const Environment &Env = Results[0].second.Env;
3624 
3625         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3626         ASSERT_THAT(FooRefDecl, NotNull());
3627 
3628         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3629         ASSERT_THAT(BarRefDecl, NotNull());
3630 
3631         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
3632         ASSERT_THAT(BoundFooDecl, NotNull());
3633 
3634         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
3635         ASSERT_THAT(BoundBarDecl, NotNull());
3636 
3637         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3638         ASSERT_THAT(QuxDecl, NotNull());
3639 
3640         const StorageLocation *FooRefLoc =
3641             Env.getStorageLocation(*FooRefDecl, SkipPast::Reference);
3642         ASSERT_THAT(FooRefLoc, NotNull());
3643 
3644         const StorageLocation *BarRefLoc =
3645             Env.getStorageLocation(*BarRefDecl, SkipPast::Reference);
3646         ASSERT_THAT(BarRefLoc, NotNull());
3647 
3648         const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None);
3649         ASSERT_THAT(QuxVal, NotNull());
3650 
3651         const StorageLocation *BoundFooLoc =
3652             Env.getStorageLocation(*BoundFooDecl, SkipPast::Reference);
3653         EXPECT_NE(BoundFooLoc, FooRefLoc);
3654 
3655         const StorageLocation *BoundBarLoc =
3656             Env.getStorageLocation(*BoundBarDecl, SkipPast::Reference);
3657         EXPECT_NE(BoundBarLoc, BarRefLoc);
3658 
3659         EXPECT_EQ(Env.getValue(*BoundFooDecl, SkipPast::Reference), QuxVal);
3660       });
3661 }
3662 
3663 TEST(TransferTest, BinaryOperatorComma) {
3664   std::string Code = R"(
3665     void target(int Foo, int Bar) {
3666       int &Baz = (Foo, Bar);
3667       // [[p]]
3668     }
3669   )";
3670   runDataflow(Code,
3671               [](llvm::ArrayRef<
3672                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3673                      Results,
3674                  ASTContext &ASTCtx) {
3675                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3676                 const Environment &Env = Results[0].second.Env;
3677 
3678                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3679                 ASSERT_THAT(BarDecl, NotNull());
3680 
3681                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3682                 ASSERT_THAT(BazDecl, NotNull());
3683 
3684                 const StorageLocation *BarLoc =
3685                     Env.getStorageLocation(*BarDecl, SkipPast::Reference);
3686                 ASSERT_THAT(BarLoc, NotNull());
3687 
3688                 const StorageLocation *BazLoc =
3689                     Env.getStorageLocation(*BazDecl, SkipPast::Reference);
3690                 EXPECT_EQ(BazLoc, BarLoc);
3691               });
3692 }
3693 
3694 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
3695   std::string Code = R"(
3696     void target(bool Foo) {
3697       if (Foo) {
3698         (void)0;
3699         // [[if_then]]
3700       } else {
3701         (void)0;
3702         // [[if_else]]
3703       }
3704     }
3705   )";
3706   runDataflow(
3707       Code, [](llvm::ArrayRef<
3708                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3709                    Results,
3710                ASTContext &ASTCtx) {
3711         ASSERT_THAT(Results,
3712                     ElementsAre(Pair("if_else", _), Pair("if_then", _)));
3713         const Environment &ThenEnv = Results[1].second.Env;
3714         const Environment &ElseEnv = Results[0].second.Env;
3715 
3716         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3717         ASSERT_THAT(FooDecl, NotNull());
3718 
3719         BoolValue &ThenFooVal =
3720             *cast<BoolValue>(ThenEnv.getValue(*FooDecl, SkipPast::None));
3721         EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal));
3722 
3723         BoolValue &ElseFooVal =
3724             *cast<BoolValue>(ElseEnv.getValue(*FooDecl, SkipPast::None));
3725         EXPECT_TRUE(ElseEnv.flowConditionImplies(ElseEnv.makeNot(ElseFooVal)));
3726       });
3727 }
3728 
3729 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
3730   std::string Code = R"(
3731     void target(bool Foo) {
3732       while (Foo) {
3733         (void)0;
3734         // [[loop_body]]
3735       }
3736       (void)0;
3737       // [[after_loop]]
3738     }
3739   )";
3740   runDataflow(
3741       Code, [](llvm::ArrayRef<
3742                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3743                    Results,
3744                ASTContext &ASTCtx) {
3745         ASSERT_THAT(Results,
3746                     ElementsAre(Pair("after_loop", _), Pair("loop_body", _)));
3747         const Environment &LoopBodyEnv = Results[1].second.Env;
3748         const Environment &AfterLoopEnv = Results[0].second.Env;
3749 
3750         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3751         ASSERT_THAT(FooDecl, NotNull());
3752 
3753         BoolValue &LoopBodyFooVal =
3754             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
3755         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
3756 
3757         BoolValue &AfterLoopFooVal =
3758             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
3759         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
3760             AfterLoopEnv.makeNot(AfterLoopFooVal)));
3761       });
3762 }
3763 
3764 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
3765   std::string Code = R"(
3766     void target(bool Foo) {
3767       bool Bar = true;
3768       do {
3769         (void)0;
3770         // [[loop_body]]
3771         Bar = false;
3772       } while (Foo);
3773       (void)0;
3774       // [[after_loop]]
3775     }
3776   )";
3777   runDataflow(
3778       Code, [](llvm::ArrayRef<
3779                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3780                    Results,
3781                ASTContext &ASTCtx) {
3782         ASSERT_THAT(Results,
3783                     ElementsAre(Pair("after_loop", _), Pair("loop_body", _)));
3784         const Environment &LoopBodyEnv = Results[1].second.Env;
3785         const Environment &AfterLoopEnv = Results[0].second.Env;
3786 
3787         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3788         ASSERT_THAT(FooDecl, NotNull());
3789 
3790         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3791         ASSERT_THAT(BarDecl, NotNull());
3792 
3793         BoolValue &LoopBodyFooVal =
3794             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
3795         BoolValue &LoopBodyBarVal =
3796             *cast<BoolValue>(LoopBodyEnv.getValue(*BarDecl, SkipPast::None));
3797         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(
3798             LoopBodyEnv.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
3799 
3800         BoolValue &AfterLoopFooVal =
3801             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
3802         BoolValue &AfterLoopBarVal =
3803             *cast<BoolValue>(AfterLoopEnv.getValue(*BarDecl, SkipPast::None));
3804         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
3805             AfterLoopEnv.makeNot(AfterLoopFooVal)));
3806         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
3807             AfterLoopEnv.makeNot(AfterLoopBarVal)));
3808       });
3809 }
3810 
3811 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
3812   std::string Code = R"(
3813     void target(bool Foo) {
3814       for (; Foo;) {
3815         (void)0;
3816         // [[loop_body]]
3817       }
3818       (void)0;
3819       // [[after_loop]]
3820     }
3821   )";
3822   runDataflow(
3823       Code, [](llvm::ArrayRef<
3824                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3825                    Results,
3826                ASTContext &ASTCtx) {
3827         ASSERT_THAT(Results,
3828                     ElementsAre(Pair("after_loop", _), Pair("loop_body", _)));
3829         const Environment &LoopBodyEnv = Results[1].second.Env;
3830         const Environment &AfterLoopEnv = Results[0].second.Env;
3831 
3832         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3833         ASSERT_THAT(FooDecl, NotNull());
3834 
3835         BoolValue &LoopBodyFooVal =
3836             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
3837         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
3838 
3839         BoolValue &AfterLoopFooVal =
3840             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
3841         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
3842             AfterLoopEnv.makeNot(AfterLoopFooVal)));
3843       });
3844 }
3845 
3846 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
3847   std::string Code = R"(
3848     void target(bool Foo) {
3849       for (;;) {
3850         (void)0;
3851         // [[loop_body]]
3852       }
3853     }
3854   )";
3855   runDataflow(
3856       Code, [](llvm::ArrayRef<
3857                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3858                    Results,
3859                ASTContext &ASTCtx) {
3860         ASSERT_THAT(Results, ElementsAre(Pair("loop_body", _)));
3861         const Environment &LoopBodyEnv = Results[0].second.Env;
3862 
3863         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3864         ASSERT_THAT(FooDecl, NotNull());
3865 
3866         BoolValue &LoopBodyFooVal =
3867             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
3868         EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
3869       });
3870 }
3871 
3872 TEST(TransferTest, ContextSensitiveOptionDisabled) {
3873   std::string Code = R"(
3874     bool GiveBool();
3875     void SetBool(bool &Var) { Var = true; }
3876 
3877     void target() {
3878       bool Foo = GiveBool();
3879       SetBool(Foo);
3880       // [[p]]
3881     }
3882   )";
3883   runDataflow(Code,
3884               [](llvm::ArrayRef<
3885                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3886                      Results,
3887                  ASTContext &ASTCtx) {
3888                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3889                 const Environment &Env = Results[0].second.Env;
3890 
3891                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3892                 ASSERT_THAT(FooDecl, NotNull());
3893 
3894                 auto &FooVal =
3895                     *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
3896                 EXPECT_FALSE(Env.flowConditionImplies(FooVal));
3897                 EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
3898               },
3899               {/*.ApplyBuiltinTransfer=*/true,
3900                /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/false}});
3901 }
3902 
3903 TEST(TransferTest, ContextSensitiveSetTrue) {
3904   std::string Code = R"(
3905     bool GiveBool();
3906     void SetBool(bool &Var) { Var = true; }
3907 
3908     void target() {
3909       bool Foo = GiveBool();
3910       SetBool(Foo);
3911       // [[p]]
3912     }
3913   )";
3914   runDataflow(Code,
3915               [](llvm::ArrayRef<
3916                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3917                      Results,
3918                  ASTContext &ASTCtx) {
3919                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3920                 const Environment &Env = Results[0].second.Env;
3921 
3922                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3923                 ASSERT_THAT(FooDecl, NotNull());
3924 
3925                 auto &FooVal =
3926                     *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
3927                 EXPECT_TRUE(Env.flowConditionImplies(FooVal));
3928               },
3929               {/*.ApplyBuiltinTransfer=*/true,
3930                /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
3931 }
3932 
3933 TEST(TransferTest, ContextSensitiveSetFalse) {
3934   std::string Code = R"(
3935     bool GiveBool();
3936     void SetBool(bool &Var) { Var = false; }
3937 
3938     void target() {
3939       bool Foo = GiveBool();
3940       SetBool(Foo);
3941       // [[p]]
3942     }
3943   )";
3944   runDataflow(Code,
3945               [](llvm::ArrayRef<
3946                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3947                      Results,
3948                  ASTContext &ASTCtx) {
3949                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3950                 const Environment &Env = Results[0].second.Env;
3951 
3952                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3953                 ASSERT_THAT(FooDecl, NotNull());
3954 
3955                 auto &FooVal =
3956                     *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
3957                 EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
3958               },
3959               {/*.ApplyBuiltinTransfer=*/true,
3960                /*.BuiltinTransferOptions=*/{/*.ContextSensitive=*/true}});
3961 }
3962 
3963 } // namespace
3964