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