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