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