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