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