xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision e363c5963dc3ad5d9492d3f37055ad56a84411a5)
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, AddrOfValue) {
2218   std::string Code = R"(
2219     void target() {
2220       int Foo;
2221       int *Bar = &Foo;
2222       // [[p]]
2223     }
2224   )";
2225   runDataflow(Code,
2226               [](llvm::ArrayRef<
2227                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2228                      Results,
2229                  ASTContext &ASTCtx) {
2230                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2231                 const Environment &Env = Results[0].second.Env;
2232 
2233                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2234                 ASSERT_THAT(FooDecl, NotNull());
2235 
2236                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2237                 ASSERT_THAT(BarDecl, NotNull());
2238 
2239                 const auto *FooLoc = cast<ScalarStorageLocation>(
2240                     Env.getStorageLocation(*FooDecl, SkipPast::None));
2241                 const auto *BarVal =
2242                     cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
2243                 EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
2244               });
2245 }
2246 
2247 TEST_F(TransferTest, AddrOfReference) {
2248   std::string Code = R"(
2249     void target(int *Foo) {
2250       int *Bar = &(*Foo);
2251       // [[p]]
2252     }
2253   )";
2254   runDataflow(Code,
2255               [](llvm::ArrayRef<
2256                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2257                      Results,
2258                  ASTContext &ASTCtx) {
2259                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2260                 const Environment &Env = Results[0].second.Env;
2261 
2262                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2263                 ASSERT_THAT(FooDecl, NotNull());
2264 
2265                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2266                 ASSERT_THAT(BarDecl, NotNull());
2267 
2268                 const auto *FooVal =
2269                     cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2270                 const auto *BarVal =
2271                     cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
2272                 EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
2273               });
2274 }
2275 
2276 TEST_F(TransferTest, DerefDependentPtr) {
2277   std::string Code = R"(
2278     template <typename T>
2279     void target(T *Foo) {
2280       T &Bar = *Foo;
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 *FooDecl = findValueDecl(ASTCtx, "Foo");
2293         ASSERT_THAT(FooDecl, NotNull());
2294 
2295         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2296         ASSERT_THAT(BarDecl, NotNull());
2297 
2298         const auto *FooVal =
2299             cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2300         const auto *BarVal =
2301             cast<ReferenceValue>(Env.getValue(*BarDecl, SkipPast::None));
2302         EXPECT_EQ(&BarVal->getReferentLoc(), &FooVal->getPointeeLoc());
2303       });
2304 }
2305 
2306 TEST_F(TransferTest, VarDeclInitAssignConditionalOperator) {
2307   std::string Code = R"(
2308     struct A {};
2309 
2310     void target(A Foo, A Bar, bool Cond) {
2311       A Baz = Cond ?  Foo : Bar;
2312       /*[[p]]*/
2313     }
2314   )";
2315   runDataflow(
2316       Code, [](llvm::ArrayRef<
2317                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2318                    Results,
2319                ASTContext &ASTCtx) {
2320         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2321         const Environment &Env = Results[0].second.Env;
2322 
2323         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2324         ASSERT_THAT(FooDecl, NotNull());
2325 
2326         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2327         ASSERT_THAT(BarDecl, NotNull());
2328 
2329         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2330         ASSERT_THAT(BazDecl, NotNull());
2331 
2332         const auto *FooVal =
2333             cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None));
2334         const auto *BarVal =
2335             cast<StructValue>(Env.getValue(*BarDecl, SkipPast::None));
2336 
2337         const auto *BazVal =
2338             dyn_cast<StructValue>(Env.getValue(*BazDecl, SkipPast::None));
2339         ASSERT_THAT(BazVal, NotNull());
2340 
2341         EXPECT_NE(BazVal, FooVal);
2342         EXPECT_NE(BazVal, BarVal);
2343       });
2344 }
2345 
2346 TEST_F(TransferTest, VarDeclInDoWhile) {
2347   std::string Code = R"(
2348     void target(int *Foo) {
2349       do {
2350         int Bar = *Foo;
2351       } while (true);
2352       (void)0;
2353       /*[[p]]*/
2354     }
2355   )";
2356   runDataflow(Code,
2357               [](llvm::ArrayRef<
2358                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2359                      Results,
2360                  ASTContext &ASTCtx) {
2361                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2362                 const Environment &Env = Results[0].second.Env;
2363 
2364                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2365                 ASSERT_THAT(FooDecl, NotNull());
2366 
2367                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2368                 ASSERT_THAT(BarDecl, NotNull());
2369 
2370                 const auto *FooVal =
2371                     cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2372                 const auto *FooPointeeVal =
2373                     cast<IntegerValue>(Env.getValue(FooVal->getPointeeLoc()));
2374 
2375                 const auto *BarVal = dyn_cast_or_null<IntegerValue>(
2376                     Env.getValue(*BarDecl, SkipPast::None));
2377                 ASSERT_THAT(BarVal, NotNull());
2378 
2379                 EXPECT_EQ(BarVal, FooPointeeVal);
2380               });
2381 }
2382 
2383 TEST_F(TransferTest, AggregateInitialization) {
2384   std::string BracesCode = R"(
2385     struct A {
2386       int Foo;
2387     };
2388 
2389     struct B {
2390       int Bar;
2391       A Baz;
2392       int Qux;
2393     };
2394 
2395     void target(int BarArg, int FooArg, int QuxArg) {
2396       B Quux{BarArg, {FooArg}, QuxArg};
2397       /*[[p]]*/
2398     }
2399   )";
2400   std::string BraceEllisionCode = R"(
2401     struct A {
2402       int Foo;
2403     };
2404 
2405     struct B {
2406       int Bar;
2407       A Baz;
2408       int Qux;
2409     };
2410 
2411     void target(int BarArg, int FooArg, int QuxArg) {
2412       B Quux = {BarArg, FooArg, QuxArg};
2413       /*[[p]]*/
2414     }
2415   )";
2416   for (const std::string &Code : {BracesCode, BraceEllisionCode}) {
2417     runDataflow(
2418         Code, [](llvm::ArrayRef<
2419                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2420                      Results,
2421                  ASTContext &ASTCtx) {
2422           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2423           const Environment &Env = Results[0].second.Env;
2424 
2425           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2426           ASSERT_THAT(FooDecl, NotNull());
2427 
2428           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2429           ASSERT_THAT(BarDecl, NotNull());
2430 
2431           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2432           ASSERT_THAT(BazDecl, NotNull());
2433 
2434           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2435           ASSERT_THAT(QuxDecl, NotNull());
2436 
2437           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
2438           ASSERT_THAT(FooArgDecl, NotNull());
2439 
2440           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
2441           ASSERT_THAT(BarArgDecl, NotNull());
2442 
2443           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
2444           ASSERT_THAT(QuxArgDecl, NotNull());
2445 
2446           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
2447           ASSERT_THAT(QuuxDecl, NotNull());
2448 
2449           const auto *FooArgVal =
2450               cast<IntegerValue>(Env.getValue(*FooArgDecl, SkipPast::None));
2451           const auto *BarArgVal =
2452               cast<IntegerValue>(Env.getValue(*BarArgDecl, SkipPast::None));
2453           const auto *QuxArgVal =
2454               cast<IntegerValue>(Env.getValue(*QuxArgDecl, SkipPast::None));
2455 
2456           const auto *QuuxVal =
2457               cast<StructValue>(Env.getValue(*QuuxDecl, SkipPast::None));
2458           ASSERT_THAT(QuuxVal, NotNull());
2459 
2460           const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl));
2461           ASSERT_THAT(BazVal, NotNull());
2462 
2463           EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal);
2464           EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal);
2465           EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal);
2466         });
2467   }
2468 }
2469 
2470 TEST_F(TransferTest, AssignToUnionMember) {
2471   std::string Code = R"(
2472     union A {
2473       int Foo;
2474     };
2475 
2476     void target(int Bar) {
2477       A Baz;
2478       Baz.Foo = Bar;
2479       // [[p]]
2480     }
2481   )";
2482   runDataflow(Code,
2483               [](llvm::ArrayRef<
2484                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2485                      Results,
2486                  ASTContext &ASTCtx) {
2487                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2488                 const Environment &Env = Results[0].second.Env;
2489 
2490                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2491                 ASSERT_THAT(BazDecl, NotNull());
2492                 ASSERT_TRUE(BazDecl->getType()->isUnionType());
2493 
2494                 const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>(
2495                     Env.getStorageLocation(*BazDecl, SkipPast::None));
2496                 ASSERT_THAT(BazLoc, NotNull());
2497 
2498                 // FIXME: Add support for union types.
2499                 EXPECT_THAT(Env.getValue(*BazLoc), IsNull());
2500               });
2501 }
2502 
2503 TEST_F(TransferTest, AssignFromBoolLiteral) {
2504   std::string Code = R"(
2505     void target() {
2506       bool Foo = true;
2507       bool Bar = false;
2508       // [[p]]
2509     }
2510   )";
2511   runDataflow(Code,
2512               [](llvm::ArrayRef<
2513                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2514                      Results,
2515                  ASTContext &ASTCtx) {
2516                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2517                 const Environment &Env = Results[0].second.Env;
2518 
2519                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2520                 ASSERT_THAT(FooDecl, NotNull());
2521 
2522                 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>(
2523                     Env.getValue(*FooDecl, SkipPast::None));
2524                 ASSERT_THAT(FooVal, NotNull());
2525 
2526                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2527                 ASSERT_THAT(BarDecl, NotNull());
2528 
2529                 const auto *BarVal = dyn_cast_or_null<AtomicBoolValue>(
2530                     Env.getValue(*BarDecl, SkipPast::None));
2531                 ASSERT_THAT(BarVal, NotNull());
2532 
2533                 EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
2534                 EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
2535               });
2536 }
2537 
2538 TEST_F(TransferTest, AssignFromCompositeBoolExpression) {
2539   {
2540     std::string Code = R"(
2541     void target(bool Foo, bool Bar, bool Qux) {
2542       bool Baz = (Foo) && (Bar || Qux);
2543       // [[p]]
2544     }
2545   )";
2546     runDataflow(
2547         Code, [](llvm::ArrayRef<
2548                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2549                      Results,
2550                  ASTContext &ASTCtx) {
2551           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2552           const Environment &Env = Results[0].second.Env;
2553 
2554           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2555           ASSERT_THAT(FooDecl, NotNull());
2556 
2557           const auto *FooVal = dyn_cast_or_null<BoolValue>(
2558               Env.getValue(*FooDecl, SkipPast::None));
2559           ASSERT_THAT(FooVal, NotNull());
2560 
2561           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2562           ASSERT_THAT(BarDecl, NotNull());
2563 
2564           const auto *BarVal = dyn_cast_or_null<BoolValue>(
2565               Env.getValue(*BarDecl, SkipPast::None));
2566           ASSERT_THAT(BarVal, NotNull());
2567 
2568           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2569           ASSERT_THAT(QuxDecl, NotNull());
2570 
2571           const auto *QuxVal = dyn_cast_or_null<BoolValue>(
2572               Env.getValue(*QuxDecl, SkipPast::None));
2573           ASSERT_THAT(QuxVal, NotNull());
2574 
2575           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2576           ASSERT_THAT(BazDecl, NotNull());
2577 
2578           const auto *BazVal = dyn_cast_or_null<ConjunctionValue>(
2579               Env.getValue(*BazDecl, SkipPast::None));
2580           ASSERT_THAT(BazVal, NotNull());
2581           EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
2582 
2583           const auto *BazRightSubValVal =
2584               cast<DisjunctionValue>(&BazVal->getRightSubValue());
2585           EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal);
2586           EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal);
2587         });
2588   }
2589 
2590   {
2591     std::string Code = R"(
2592     void target(bool Foo, bool Bar, bool Qux) {
2593       bool Baz = (Foo && Qux) || (Bar);
2594       // [[p]]
2595     }
2596   )";
2597     runDataflow(
2598         Code, [](llvm::ArrayRef<
2599                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2600                      Results,
2601                  ASTContext &ASTCtx) {
2602           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2603           const Environment &Env = Results[0].second.Env;
2604 
2605           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2606           ASSERT_THAT(FooDecl, NotNull());
2607 
2608           const auto *FooVal = dyn_cast_or_null<BoolValue>(
2609               Env.getValue(*FooDecl, SkipPast::None));
2610           ASSERT_THAT(FooVal, NotNull());
2611 
2612           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2613           ASSERT_THAT(BarDecl, NotNull());
2614 
2615           const auto *BarVal = dyn_cast_or_null<BoolValue>(
2616               Env.getValue(*BarDecl, SkipPast::None));
2617           ASSERT_THAT(BarVal, NotNull());
2618 
2619           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2620           ASSERT_THAT(QuxDecl, NotNull());
2621 
2622           const auto *QuxVal = dyn_cast_or_null<BoolValue>(
2623               Env.getValue(*QuxDecl, SkipPast::None));
2624           ASSERT_THAT(QuxVal, NotNull());
2625 
2626           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2627           ASSERT_THAT(BazDecl, NotNull());
2628 
2629           const auto *BazVal = dyn_cast_or_null<DisjunctionValue>(
2630               Env.getValue(*BazDecl, SkipPast::None));
2631           ASSERT_THAT(BazVal, NotNull());
2632 
2633           const auto *BazLeftSubValVal =
2634               cast<ConjunctionValue>(&BazVal->getLeftSubValue());
2635           EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal);
2636           EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal);
2637 
2638           EXPECT_EQ(&BazVal->getRightSubValue(), BarVal);
2639         });
2640   }
2641 
2642   {
2643     std::string Code = R"(
2644       void target(bool A, bool B, bool C, bool D) {
2645         bool Foo = ((A && B) && C) && D;
2646         // [[p]]
2647       }
2648     )";
2649     runDataflow(
2650         Code, [](llvm::ArrayRef<
2651                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2652                      Results,
2653                  ASTContext &ASTCtx) {
2654           ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2655           const Environment &Env = Results[0].second.Env;
2656 
2657           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
2658           ASSERT_THAT(ADecl, NotNull());
2659 
2660           const auto *AVal =
2661               dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl, SkipPast::None));
2662           ASSERT_THAT(AVal, NotNull());
2663 
2664           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
2665           ASSERT_THAT(BDecl, NotNull());
2666 
2667           const auto *BVal =
2668               dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl, SkipPast::None));
2669           ASSERT_THAT(BVal, NotNull());
2670 
2671           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
2672           ASSERT_THAT(CDecl, NotNull());
2673 
2674           const auto *CVal =
2675               dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
2676           ASSERT_THAT(CVal, NotNull());
2677 
2678           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
2679           ASSERT_THAT(DDecl, NotNull());
2680 
2681           const auto *DVal =
2682               dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl, SkipPast::None));
2683           ASSERT_THAT(DVal, NotNull());
2684 
2685           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2686           ASSERT_THAT(FooDecl, NotNull());
2687 
2688           const auto *FooVal = dyn_cast_or_null<ConjunctionValue>(
2689               Env.getValue(*FooDecl, SkipPast::None));
2690           ASSERT_THAT(FooVal, NotNull());
2691 
2692           const auto &FooLeftSubVal =
2693               cast<ConjunctionValue>(FooVal->getLeftSubValue());
2694           const auto &FooLeftLeftSubVal =
2695               cast<ConjunctionValue>(FooLeftSubVal.getLeftSubValue());
2696           EXPECT_EQ(&FooLeftLeftSubVal.getLeftSubValue(), AVal);
2697           EXPECT_EQ(&FooLeftLeftSubVal.getRightSubValue(), BVal);
2698           EXPECT_EQ(&FooLeftSubVal.getRightSubValue(), CVal);
2699           EXPECT_EQ(&FooVal->getRightSubValue(), DVal);
2700         });
2701   }
2702 }
2703 
2704 TEST_F(TransferTest, AssignFromBoolNegation) {
2705   std::string Code = R"(
2706     void target() {
2707       bool Foo = true;
2708       bool Bar = !(Foo);
2709       // [[p]]
2710     }
2711   )";
2712   runDataflow(Code,
2713               [](llvm::ArrayRef<
2714                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2715                      Results,
2716                  ASTContext &ASTCtx) {
2717                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2718                 const Environment &Env = Results[0].second.Env;
2719 
2720                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2721                 ASSERT_THAT(FooDecl, NotNull());
2722 
2723                 const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>(
2724                     Env.getValue(*FooDecl, SkipPast::None));
2725                 ASSERT_THAT(FooVal, NotNull());
2726 
2727                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2728                 ASSERT_THAT(BarDecl, NotNull());
2729 
2730                 const auto *BarVal = dyn_cast_or_null<NegationValue>(
2731                     Env.getValue(*BarDecl, SkipPast::None));
2732                 ASSERT_THAT(BarVal, NotNull());
2733 
2734                 EXPECT_EQ(&BarVal->getSubVal(), FooVal);
2735               });
2736 }
2737 
2738 TEST_F(TransferTest, BuiltinExpect) {
2739   std::string Code = R"(
2740     void target(long Foo) {
2741       long Bar = __builtin_expect(Foo, true);
2742       /*[[p]]*/
2743     }
2744   )";
2745   runDataflow(Code,
2746               [](llvm::ArrayRef<
2747                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2748                      Results,
2749                  ASTContext &ASTCtx) {
2750                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2751                 const auto &Env = Results[0].second.Env;
2752 
2753                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2754                 ASSERT_THAT(FooDecl, NotNull());
2755 
2756                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2757                 ASSERT_THAT(BarDecl, NotNull());
2758 
2759                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2760                           Env.getValue(*BarDecl, SkipPast::None));
2761               });
2762 }
2763 
2764 // `__builtin_expect` takes and returns a `long` argument, so other types
2765 // involve casts. This verifies that we identify the input and output in that
2766 // case.
2767 TEST_F(TransferTest, BuiltinExpectBoolArg) {
2768   std::string Code = R"(
2769     void target(bool Foo) {
2770       bool Bar = __builtin_expect(Foo, true);
2771       /*[[p]]*/
2772     }
2773   )";
2774   runDataflow(Code,
2775               [](llvm::ArrayRef<
2776                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2777                      Results,
2778                  ASTContext &ASTCtx) {
2779                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2780                 const auto &Env = Results[0].second.Env;
2781 
2782                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2783                 ASSERT_THAT(FooDecl, NotNull());
2784 
2785                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2786                 ASSERT_THAT(BarDecl, NotNull());
2787 
2788                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2789                           Env.getValue(*BarDecl, SkipPast::None));
2790               });
2791 }
2792 
2793 TEST_F(TransferTest, BuiltinUnreachable) {
2794   std::string Code = R"(
2795     void target(bool Foo) {
2796       bool Bar = false;
2797       if (Foo)
2798         Bar = Foo;
2799       else
2800         __builtin_unreachable();
2801       (void)0;
2802       /*[[p]]*/
2803     }
2804   )";
2805   runDataflow(Code,
2806               [](llvm::ArrayRef<
2807                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2808                      Results,
2809                  ASTContext &ASTCtx) {
2810                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2811                 const auto &Env = Results[0].second.Env;
2812 
2813                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2814                 ASSERT_THAT(FooDecl, NotNull());
2815 
2816                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2817                 ASSERT_THAT(BarDecl, NotNull());
2818 
2819                 // `__builtin_unreachable` promises that the code is
2820                 // unreachable, so the compiler treats the "then" branch as the
2821                 // only possible predecessor of this statement.
2822                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2823                           Env.getValue(*BarDecl, SkipPast::None));
2824               });
2825 }
2826 
2827 TEST_F(TransferTest, BuiltinTrap) {
2828   std::string Code = R"(
2829     void target(bool Foo) {
2830       bool Bar = false;
2831       if (Foo)
2832         Bar = Foo;
2833       else
2834         __builtin_trap();
2835       (void)0;
2836       /*[[p]]*/
2837     }
2838   )";
2839   runDataflow(Code,
2840               [](llvm::ArrayRef<
2841                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2842                      Results,
2843                  ASTContext &ASTCtx) {
2844                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2845                 const auto &Env = Results[0].second.Env;
2846 
2847                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2848                 ASSERT_THAT(FooDecl, NotNull());
2849 
2850                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2851                 ASSERT_THAT(BarDecl, NotNull());
2852 
2853                 // `__builtin_trap` ensures program termination, so only the
2854                 // "then" branch is a predecessor of this statement.
2855                 EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2856                           Env.getValue(*BarDecl, SkipPast::None));
2857               });
2858 }
2859 
2860 TEST_F(TransferTest, BuiltinDebugTrap) {
2861   std::string Code = R"(
2862     void target(bool Foo) {
2863       bool Bar = false;
2864       if (Foo)
2865         Bar = Foo;
2866       else
2867         __builtin_debugtrap();
2868       (void)0;
2869       /*[[p]]*/
2870     }
2871   )";
2872   runDataflow(Code,
2873               [](llvm::ArrayRef<
2874                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2875                      Results,
2876                  ASTContext &ASTCtx) {
2877                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2878                 const auto &Env = Results[0].second.Env;
2879 
2880                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2881                 ASSERT_THAT(FooDecl, NotNull());
2882 
2883                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2884                 ASSERT_THAT(BarDecl, NotNull());
2885 
2886                 // `__builtin_debugtrap` doesn't ensure program termination.
2887                 EXPECT_NE(Env.getValue(*FooDecl, SkipPast::None),
2888                           Env.getValue(*BarDecl, SkipPast::None));
2889               });
2890 }
2891 
2892 TEST_F(TransferTest, StaticIntSingleVarDecl) {
2893   std::string Code = R"(
2894     void target() {
2895       static int Foo;
2896       // [[p]]
2897     }
2898   )";
2899   runDataflow(Code,
2900               [](llvm::ArrayRef<
2901                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2902                      Results,
2903                  ASTContext &ASTCtx) {
2904                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2905                 const Environment &Env = Results[0].second.Env;
2906 
2907                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2908                 ASSERT_THAT(FooDecl, NotNull());
2909 
2910                 const StorageLocation *FooLoc =
2911                     Env.getStorageLocation(*FooDecl, SkipPast::None);
2912                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
2913 
2914                 const Value *FooVal = Env.getValue(*FooLoc);
2915                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
2916               });
2917 }
2918 
2919 TEST_F(TransferTest, StaticIntGroupVarDecl) {
2920   std::string Code = R"(
2921     void target() {
2922       static int Foo, Bar;
2923       (void)0;
2924       // [[p]]
2925     }
2926   )";
2927   runDataflow(Code,
2928               [](llvm::ArrayRef<
2929                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2930                      Results,
2931                  ASTContext &ASTCtx) {
2932                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2933                 const Environment &Env = Results[0].second.Env;
2934 
2935                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2936                 ASSERT_THAT(FooDecl, NotNull());
2937 
2938                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2939                 ASSERT_THAT(BarDecl, NotNull());
2940 
2941                 const StorageLocation *FooLoc =
2942                     Env.getStorageLocation(*FooDecl, SkipPast::None);
2943                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
2944 
2945                 const StorageLocation *BarLoc =
2946                     Env.getStorageLocation(*BarDecl, SkipPast::None);
2947                 ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2948 
2949                 const Value *FooVal = Env.getValue(*FooLoc);
2950                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
2951 
2952                 const Value *BarVal = Env.getValue(*BarLoc);
2953                 EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
2954 
2955                 EXPECT_NE(FooVal, BarVal);
2956               });
2957 }
2958 
2959 TEST_F(TransferTest, GlobalIntVarDecl) {
2960   std::string Code = R"(
2961     static int Foo;
2962 
2963     void target() {
2964       int Bar = Foo;
2965       int Baz = Foo;
2966       // [[p]]
2967     }
2968   )";
2969   runDataflow(Code,
2970               [](llvm::ArrayRef<
2971                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
2972                      Results,
2973                  ASTContext &ASTCtx) {
2974                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
2975                 const Environment &Env = Results[0].second.Env;
2976 
2977                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2978                 ASSERT_THAT(BarDecl, NotNull());
2979 
2980                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2981                 ASSERT_THAT(BazDecl, NotNull());
2982 
2983                 const Value *BarVal =
2984                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2985                 const Value *BazVal =
2986                     cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
2987                 EXPECT_EQ(BarVal, BazVal);
2988               });
2989 }
2990 
2991 TEST_F(TransferTest, StaticMemberIntVarDecl) {
2992   std::string Code = R"(
2993     struct A {
2994       static int Foo;
2995     };
2996 
2997     void target(A a) {
2998       int Bar = a.Foo;
2999       int Baz = a.Foo;
3000       // [[p]]
3001     }
3002   )";
3003   runDataflow(Code,
3004               [](llvm::ArrayRef<
3005                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3006                      Results,
3007                  ASTContext &ASTCtx) {
3008                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3009                 const Environment &Env = Results[0].second.Env;
3010 
3011                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3012                 ASSERT_THAT(BarDecl, NotNull());
3013 
3014                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3015                 ASSERT_THAT(BazDecl, NotNull());
3016 
3017                 const Value *BarVal =
3018                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3019                 const Value *BazVal =
3020                     cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
3021                 EXPECT_EQ(BarVal, BazVal);
3022               });
3023 }
3024 
3025 TEST_F(TransferTest, StaticMemberRefVarDecl) {
3026   std::string Code = R"(
3027     struct A {
3028       static int &Foo;
3029     };
3030 
3031     void target(A a) {
3032       int Bar = a.Foo;
3033       int Baz = a.Foo;
3034       // [[p]]
3035     }
3036   )";
3037   runDataflow(Code,
3038               [](llvm::ArrayRef<
3039                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3040                      Results,
3041                  ASTContext &ASTCtx) {
3042                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3043                 const Environment &Env = Results[0].second.Env;
3044 
3045                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3046                 ASSERT_THAT(BarDecl, NotNull());
3047 
3048                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3049                 ASSERT_THAT(BazDecl, NotNull());
3050 
3051                 const Value *BarVal =
3052                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3053                 const Value *BazVal =
3054                     cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
3055                 EXPECT_EQ(BarVal, BazVal);
3056               });
3057 }
3058 
3059 TEST_F(TransferTest, AssignMemberBeforeCopy) {
3060   std::string Code = R"(
3061     struct A {
3062       int Foo;
3063     };
3064 
3065     void target() {
3066       A A1;
3067       A A2;
3068       int Bar;
3069       A1.Foo = Bar;
3070       A2 = A1;
3071       // [[p]]
3072     }
3073   )";
3074   runDataflow(Code,
3075               [](llvm::ArrayRef<
3076                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3077                      Results,
3078                  ASTContext &ASTCtx) {
3079                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3080                 const Environment &Env = Results[0].second.Env;
3081 
3082                 const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3083                 ASSERT_THAT(FooDecl, NotNull());
3084 
3085                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3086                 ASSERT_THAT(BarDecl, NotNull());
3087 
3088                 const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
3089                 ASSERT_THAT(A1Decl, NotNull());
3090 
3091                 const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
3092                 ASSERT_THAT(A2Decl, NotNull());
3093 
3094                 const auto *BarVal =
3095                     cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3096 
3097                 const auto *A2Val =
3098                     cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None));
3099                 EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal);
3100               });
3101 }
3102 
3103 TEST_F(TransferTest, BooleanEquality) {
3104   std::string Code = R"(
3105     void target(bool Bar) {
3106       bool Foo = true;
3107       if (Bar == Foo) {
3108         (void)0;
3109         /*[[p-then]]*/
3110       } else {
3111         (void)0;
3112         /*[[p-else]]*/
3113       }
3114     }
3115   )";
3116   runDataflow(
3117       Code, [](llvm::ArrayRef<
3118                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3119                    Results,
3120                ASTContext &ASTCtx) {
3121         ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _)));
3122         const Environment &EnvElse = Results[0].second.Env;
3123         const Environment &EnvThen = Results[1].second.Env;
3124 
3125         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3126         ASSERT_THAT(BarDecl, NotNull());
3127 
3128         auto &BarValThen =
3129             *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None));
3130         EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen));
3131 
3132         auto &BarValElse =
3133             *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None));
3134         EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse));
3135       });
3136 }
3137 
3138 TEST_F(TransferTest, BooleanInequality) {
3139   std::string Code = R"(
3140     void target(bool Bar) {
3141       bool Foo = true;
3142       if (Bar != Foo) {
3143         (void)0;
3144         /*[[p-then]]*/
3145       } else {
3146         (void)0;
3147         /*[[p-else]]*/
3148       }
3149     }
3150   )";
3151   runDataflow(
3152       Code, [](llvm::ArrayRef<
3153                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3154                    Results,
3155                ASTContext &ASTCtx) {
3156         ASSERT_THAT(Results, ElementsAre(Pair("p-else", _), Pair("p-then", _)));
3157         const Environment &EnvElse = Results[0].second.Env;
3158         const Environment &EnvThen = Results[1].second.Env;
3159 
3160         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3161         ASSERT_THAT(BarDecl, NotNull());
3162 
3163         auto &BarValThen =
3164             *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None));
3165         EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen));
3166 
3167         auto &BarValElse =
3168             *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None));
3169         EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse));
3170       });
3171 }
3172 
3173 TEST_F(TransferTest, CorrelatedBranches) {
3174   std::string Code = R"(
3175     void target(bool B, bool C) {
3176       if (B) {
3177         return;
3178       }
3179       (void)0;
3180       /*[[p0]]*/
3181       if (C) {
3182         B = true;
3183         /*[[p1]]*/
3184       }
3185       if (B) {
3186         (void)0;
3187         /*[[p2]]*/
3188       }
3189     }
3190   )";
3191   runDataflow(
3192       Code, [](llvm::ArrayRef<
3193                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3194                    Results,
3195                ASTContext &ASTCtx) {
3196         ASSERT_THAT(Results, SizeIs(3));
3197 
3198         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3199         ASSERT_THAT(CDecl, NotNull());
3200 
3201         {
3202           ASSERT_THAT(Results[2], Pair("p0", _));
3203           const Environment &Env = Results[2].second.Env;
3204           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3205           ASSERT_THAT(BDecl, NotNull());
3206           auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl, SkipPast::None));
3207 
3208           EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal)));
3209         }
3210 
3211         {
3212           ASSERT_THAT(Results[1], Pair("p1", _));
3213           const Environment &Env = Results[1].second.Env;
3214           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
3215           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3216         }
3217 
3218         {
3219           ASSERT_THAT(Results[0], Pair("p2", _));
3220           const Environment &Env = Results[0].second.Env;
3221           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
3222           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3223         }
3224       });
3225 }
3226 
3227 TEST_F(TransferTest, LoopWithAssignmentConverges) {
3228   std::string Code = R"(
3229 
3230     bool &foo();
3231 
3232     void target() {
3233        do {
3234         bool Bar = foo();
3235         if (Bar) break;
3236         (void)Bar;
3237         /*[[p]]*/
3238       } while (true);
3239     }
3240   )";
3241   // The key property that we are verifying is implicit in `runDataflow` --
3242   // namely, that the analysis succeeds, rather than hitting the maximum number
3243   // of iterations.
3244   runDataflow(
3245       Code, [](llvm::ArrayRef<
3246                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3247                    Results,
3248                ASTContext &ASTCtx) {
3249         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3250         const Environment &Env = Results[0].second.Env;
3251 
3252         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3253         ASSERT_THAT(BarDecl, NotNull());
3254 
3255         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
3256         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3257       });
3258 }
3259 
3260 TEST_F(TransferTest, LoopWithReferenceAssignmentConverges) {
3261   std::string Code = R"(
3262 
3263     bool &foo();
3264 
3265     void target() {
3266        do {
3267         bool& Bar = foo();
3268         if (Bar) break;
3269         (void)Bar;
3270         /*[[p]]*/
3271       } while (true);
3272     }
3273   )";
3274   // The key property that we are verifying is implicit in `runDataflow` --
3275   // namely, that the analysis succeeds, rather than hitting the maximum number
3276   // of iterations.
3277   runDataflow(
3278       Code, [](llvm::ArrayRef<
3279                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3280                    Results,
3281                ASTContext &ASTCtx) {
3282         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3283         const Environment &Env = Results[0].second.Env;
3284 
3285         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3286         ASSERT_THAT(BarDecl, NotNull());
3287 
3288         auto &BarVal =
3289             *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::Reference));
3290         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3291       });
3292 }
3293 
3294 TEST_F(TransferTest, LoopWithStructReferenceAssignmentConverges) {
3295   std::string Code = R"(
3296     struct Lookup {
3297       int x;
3298     };
3299 
3300     void target(Lookup val, bool b) {
3301       const Lookup* l = nullptr;
3302       while (b) {
3303         l = &val;
3304         /*[[p-inner]]*/
3305       }
3306       (void)0;
3307       /*[[p-outer]]*/
3308     }
3309   )";
3310   // The key property that we are verifying is implicit in `runDataflow` --
3311   // namely, that the analysis succeeds, rather than hitting the maximum number
3312   // of iterations.
3313   runDataflow(
3314       Code, [](llvm::ArrayRef<
3315                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3316                    Results,
3317                ASTContext &ASTCtx) {
3318         ASSERT_THAT(Results,
3319                     ElementsAre(Pair("p-outer", _), Pair("p-inner", _)));
3320         const Environment &OuterEnv = Results[0].second.Env;
3321         const Environment &InnerEnv = Results[1].second.Env;
3322 
3323         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
3324         ASSERT_THAT(ValDecl, NotNull());
3325 
3326         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
3327         ASSERT_THAT(LDecl, NotNull());
3328 
3329         // Inner.
3330         auto *LVal =
3331             dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl, SkipPast::None));
3332         ASSERT_THAT(LVal, NotNull());
3333 
3334         EXPECT_EQ(&LVal->getPointeeLoc(),
3335                   InnerEnv.getStorageLocation(*ValDecl, SkipPast::Reference));
3336 
3337         // Outer.
3338         LVal =
3339             dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl, SkipPast::None));
3340         ASSERT_THAT(LVal, NotNull());
3341 
3342         // The loop body may not have been executed, so we should not conclude
3343         // that `l` points to `val`.
3344         EXPECT_NE(&LVal->getPointeeLoc(),
3345                   OuterEnv.getStorageLocation(*ValDecl, SkipPast::Reference));
3346       });
3347 }
3348 
3349 TEST_F(TransferTest, DoesNotCrashOnUnionThisExpr) {
3350   std::string Code = R"(
3351     union Union {
3352       int A;
3353       float B;
3354     };
3355 
3356     void foo() {
3357       Union A;
3358       Union B;
3359       A = B;
3360     }
3361   )";
3362   // This is a crash regression test when calling the transfer function on a
3363   // `CXXThisExpr` that refers to a union.
3364   runDataflow(
3365       Code,
3366       [](llvm::ArrayRef<
3367              std::pair<std::string, DataflowAnalysisState<NoopLattice>>>,
3368          ASTContext &) {},
3369       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
3370 }
3371 
3372 TEST_F(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
3373   std::string Code = R"(
3374     struct A {
3375       int Foo;
3376       int Bar;
3377     };
3378 
3379     void target() {
3380       int Qux;
3381       A Baz;
3382       Baz.Foo = Qux;
3383       auto &FooRef = Baz.Foo;
3384       auto &BarRef = Baz.Bar;
3385       auto &[BoundFooRef, BoundBarRef] = Baz;
3386       // [[p]]
3387     }
3388   )";
3389   runDataflow(
3390       Code, [](llvm::ArrayRef<
3391                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3392                    Results,
3393                ASTContext &ASTCtx) {
3394         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3395         const Environment &Env = Results[0].second.Env;
3396 
3397         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3398         ASSERT_THAT(FooRefDecl, NotNull());
3399 
3400         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3401         ASSERT_THAT(BarRefDecl, NotNull());
3402 
3403         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3404         ASSERT_THAT(QuxDecl, NotNull());
3405 
3406         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3407         ASSERT_THAT(BoundFooRefDecl, NotNull());
3408 
3409         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3410         ASSERT_THAT(BoundBarRefDecl, NotNull());
3411 
3412         const StorageLocation *FooRefLoc =
3413             Env.getStorageLocation(*FooRefDecl, SkipPast::Reference);
3414         ASSERT_THAT(FooRefLoc, NotNull());
3415 
3416         const StorageLocation *BarRefLoc =
3417             Env.getStorageLocation(*BarRefDecl, SkipPast::Reference);
3418         ASSERT_THAT(BarRefLoc, NotNull());
3419 
3420         const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None);
3421         ASSERT_THAT(QuxVal, NotNull());
3422 
3423         const StorageLocation *BoundFooRefLoc =
3424             Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference);
3425         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3426 
3427         const StorageLocation *BoundBarRefLoc =
3428             Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference);
3429         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3430 
3431         EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal);
3432       });
3433 }
3434 
3435 TEST_F(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
3436   std::string Code = R"(
3437     struct A {
3438       int &Foo;
3439       int &Bar;
3440     };
3441 
3442     void target(A Baz) {
3443       int Qux;
3444       Baz.Foo = Qux;
3445       auto &FooRef = Baz.Foo;
3446       auto &BarRef = Baz.Bar;
3447       auto &[BoundFooRef, BoundBarRef] = Baz;
3448       // [[p]]
3449     }
3450   )";
3451   runDataflow(
3452       Code, [](llvm::ArrayRef<
3453                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3454                    Results,
3455                ASTContext &ASTCtx) {
3456         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3457         const Environment &Env = Results[0].second.Env;
3458 
3459         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3460         ASSERT_THAT(FooRefDecl, NotNull());
3461 
3462         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3463         ASSERT_THAT(BarRefDecl, NotNull());
3464 
3465         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3466         ASSERT_THAT(QuxDecl, NotNull());
3467 
3468         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3469         ASSERT_THAT(BoundFooRefDecl, NotNull());
3470 
3471         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3472         ASSERT_THAT(BoundBarRefDecl, NotNull());
3473 
3474         const StorageLocation *FooRefLoc =
3475             Env.getStorageLocation(*FooRefDecl, SkipPast::Reference);
3476         ASSERT_THAT(FooRefLoc, NotNull());
3477 
3478         const StorageLocation *BarRefLoc =
3479             Env.getStorageLocation(*BarRefDecl, SkipPast::Reference);
3480         ASSERT_THAT(BarRefLoc, NotNull());
3481 
3482         const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None);
3483         ASSERT_THAT(QuxVal, NotNull());
3484 
3485         const StorageLocation *BoundFooRefLoc =
3486             Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference);
3487         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3488 
3489         const StorageLocation *BoundBarRefLoc =
3490             Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference);
3491         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3492 
3493         EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal);
3494       });
3495 }
3496 
3497 TEST_F(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
3498   std::string Code = R"(
3499     struct A {
3500       int Foo;
3501       int Bar;
3502     };
3503 
3504     void target() {
3505       int Qux;
3506       A Baz;
3507       Baz.Foo = Qux;
3508       auto &FooRef = Baz.Foo;
3509       auto &BarRef = Baz.Bar;
3510       auto [BoundFoo, BoundBar] = Baz;
3511       // [[p]]
3512     }
3513   )";
3514   runDataflow(
3515       Code, [](llvm::ArrayRef<
3516                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3517                    Results,
3518                ASTContext &ASTCtx) {
3519         ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3520         const Environment &Env = Results[0].second.Env;
3521 
3522         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3523         ASSERT_THAT(FooRefDecl, NotNull());
3524 
3525         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3526         ASSERT_THAT(BarRefDecl, NotNull());
3527 
3528         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
3529         ASSERT_THAT(BoundFooDecl, NotNull());
3530 
3531         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
3532         ASSERT_THAT(BoundBarDecl, NotNull());
3533 
3534         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3535         ASSERT_THAT(QuxDecl, NotNull());
3536 
3537         const StorageLocation *FooRefLoc =
3538             Env.getStorageLocation(*FooRefDecl, SkipPast::Reference);
3539         ASSERT_THAT(FooRefLoc, NotNull());
3540 
3541         const StorageLocation *BarRefLoc =
3542             Env.getStorageLocation(*BarRefDecl, SkipPast::Reference);
3543         ASSERT_THAT(BarRefLoc, NotNull());
3544 
3545         const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None);
3546         ASSERT_THAT(QuxVal, NotNull());
3547 
3548         const StorageLocation *BoundFooLoc =
3549             Env.getStorageLocation(*BoundFooDecl, SkipPast::Reference);
3550         EXPECT_NE(BoundFooLoc, FooRefLoc);
3551 
3552         const StorageLocation *BoundBarLoc =
3553             Env.getStorageLocation(*BoundBarDecl, SkipPast::Reference);
3554         EXPECT_NE(BoundBarLoc, BarRefLoc);
3555 
3556         EXPECT_EQ(Env.getValue(*BoundFooDecl, SkipPast::Reference), QuxVal);
3557       });
3558 }
3559 
3560 TEST_F(TransferTest, BinaryOperatorComma) {
3561   std::string Code = R"(
3562     void target(int Foo, int Bar) {
3563       int &Baz = (Foo, Bar);
3564       // [[p]]
3565     }
3566   )";
3567   runDataflow(Code,
3568               [](llvm::ArrayRef<
3569                      std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3570                      Results,
3571                  ASTContext &ASTCtx) {
3572                 ASSERT_THAT(Results, ElementsAre(Pair("p", _)));
3573                 const Environment &Env = Results[0].second.Env;
3574 
3575                 const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3576                 ASSERT_THAT(BarDecl, NotNull());
3577 
3578                 const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3579                 ASSERT_THAT(BazDecl, NotNull());
3580 
3581                 const StorageLocation *BarLoc =
3582                     Env.getStorageLocation(*BarDecl, SkipPast::Reference);
3583                 ASSERT_THAT(BarLoc, NotNull());
3584 
3585                 const StorageLocation *BazLoc =
3586                     Env.getStorageLocation(*BazDecl, SkipPast::Reference);
3587                 EXPECT_EQ(BazLoc, BarLoc);
3588               });
3589 }
3590 
3591 TEST_F(TransferTest, IfStmtBranchExtendsFlowCondition) {
3592   std::string Code = R"(
3593     void target(bool Foo) {
3594       if (Foo) {
3595         (void)0;
3596         // [[if_then]]
3597       } else {
3598         (void)0;
3599         // [[if_else]]
3600       }
3601     }
3602   )";
3603   runDataflow(
3604       Code, [](llvm::ArrayRef<
3605                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3606                    Results,
3607                ASTContext &ASTCtx) {
3608         ASSERT_THAT(Results,
3609                     ElementsAre(Pair("if_else", _), Pair("if_then", _)));
3610         const Environment &ThenEnv = Results[1].second.Env;
3611         const Environment &ElseEnv = Results[0].second.Env;
3612 
3613         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3614         ASSERT_THAT(FooDecl, NotNull());
3615 
3616         BoolValue &ThenFooVal =
3617             *cast<BoolValue>(ThenEnv.getValue(*FooDecl, SkipPast::None));
3618         EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal));
3619 
3620         BoolValue &ElseFooVal =
3621             *cast<BoolValue>(ElseEnv.getValue(*FooDecl, SkipPast::None));
3622         EXPECT_TRUE(ElseEnv.flowConditionImplies(ElseEnv.makeNot(ElseFooVal)));
3623       });
3624 }
3625 
3626 TEST_F(TransferTest, WhileStmtBranchExtendsFlowCondition) {
3627   std::string Code = R"(
3628     void target(bool Foo) {
3629       while (Foo) {
3630         (void)0;
3631         // [[loop_body]]
3632       }
3633       (void)0;
3634       // [[after_loop]]
3635     }
3636   )";
3637   runDataflow(
3638       Code, [](llvm::ArrayRef<
3639                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3640                    Results,
3641                ASTContext &ASTCtx) {
3642         ASSERT_THAT(Results,
3643                     ElementsAre(Pair("after_loop", _), Pair("loop_body", _)));
3644         const Environment &LoopBodyEnv = Results[1].second.Env;
3645         const Environment &AfterLoopEnv = Results[0].second.Env;
3646 
3647         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3648         ASSERT_THAT(FooDecl, NotNull());
3649 
3650         BoolValue &LoopBodyFooVal =
3651             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
3652         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
3653 
3654         BoolValue &AfterLoopFooVal =
3655             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
3656         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
3657             AfterLoopEnv.makeNot(AfterLoopFooVal)));
3658       });
3659 }
3660 
3661 TEST_F(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
3662   std::string Code = R"(
3663     void target(bool Foo) {
3664       bool Bar = true;
3665       do {
3666         (void)0;
3667         // [[loop_body]]
3668         Bar = false;
3669       } while (Foo);
3670       (void)0;
3671       // [[after_loop]]
3672     }
3673   )";
3674   runDataflow(
3675       Code, [](llvm::ArrayRef<
3676                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3677                    Results,
3678                ASTContext &ASTCtx) {
3679         ASSERT_THAT(Results,
3680                     ElementsAre(Pair("after_loop", _), Pair("loop_body", _)));
3681         const Environment &LoopBodyEnv = Results[1].second.Env;
3682         const Environment &AfterLoopEnv = Results[0].second.Env;
3683 
3684         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3685         ASSERT_THAT(FooDecl, NotNull());
3686 
3687         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3688         ASSERT_THAT(BarDecl, NotNull());
3689 
3690         BoolValue &LoopBodyFooVal =
3691             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
3692         BoolValue &LoopBodyBarVal =
3693             *cast<BoolValue>(LoopBodyEnv.getValue(*BarDecl, SkipPast::None));
3694         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(
3695             LoopBodyEnv.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
3696 
3697         BoolValue &AfterLoopFooVal =
3698             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
3699         BoolValue &AfterLoopBarVal =
3700             *cast<BoolValue>(AfterLoopEnv.getValue(*BarDecl, SkipPast::None));
3701         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
3702             AfterLoopEnv.makeNot(AfterLoopFooVal)));
3703         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
3704             AfterLoopEnv.makeNot(AfterLoopBarVal)));
3705       });
3706 }
3707 
3708 TEST_F(TransferTest, ForStmtBranchExtendsFlowCondition) {
3709   std::string Code = R"(
3710     void target(bool Foo) {
3711       for (; Foo;) {
3712         (void)0;
3713         // [[loop_body]]
3714       }
3715       (void)0;
3716       // [[after_loop]]
3717     }
3718   )";
3719   runDataflow(
3720       Code, [](llvm::ArrayRef<
3721                    std::pair<std::string, DataflowAnalysisState<NoopLattice>>>
3722                    Results,
3723                ASTContext &ASTCtx) {
3724         ASSERT_THAT(Results,
3725                     ElementsAre(Pair("after_loop", _), Pair("loop_body", _)));
3726         const Environment &LoopBodyEnv = Results[1].second.Env;
3727         const Environment &AfterLoopEnv = Results[0].second.Env;
3728 
3729         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3730         ASSERT_THAT(FooDecl, NotNull());
3731 
3732         BoolValue &LoopBodyFooVal =
3733             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
3734         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
3735 
3736         BoolValue &AfterLoopFooVal =
3737             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
3738         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
3739             AfterLoopEnv.makeNot(AfterLoopFooVal)));
3740       });
3741 }
3742 
3743 } // namespace
3744