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