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