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