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