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