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