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