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