xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision ef4635452f3a23ee29f7586148e19e8c84471a59)
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, StructThisInLambda) {
1522   std::string ThisCaptureCode = R"(
1523     struct A {
1524       void frob() {
1525         [this]() {
1526           int Foo = Bar;
1527           // [[p1]]
1528         }();
1529       }
1530 
1531       int Bar;
1532     };
1533   )";
1534   runDataflow(
1535       ThisCaptureCode,
1536       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1537          ASTContext &ASTCtx) {
1538         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1"));
1539         const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
1540 
1541         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1542             Env.getThisPointeeStorageLocation());
1543         ASSERT_THAT(ThisLoc, NotNull());
1544 
1545         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1546         ASSERT_THAT(BarDecl, NotNull());
1547 
1548         const auto *BarLoc =
1549             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1550         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1551 
1552         const Value *BarVal = Env.getValue(*BarLoc);
1553         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1554 
1555         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1556         ASSERT_THAT(FooDecl, NotNull());
1557         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1558       },
1559       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1560 
1561   std::string RefCaptureDefaultCode = R"(
1562     struct A {
1563       void frob() {
1564         [&]() {
1565           int Foo = Bar;
1566           // [[p2]]
1567         }();
1568       }
1569 
1570       int Bar;
1571     };
1572   )";
1573   runDataflow(
1574       RefCaptureDefaultCode,
1575       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1576          ASTContext &ASTCtx) {
1577         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p2"));
1578         const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
1579 
1580         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1581             Env.getThisPointeeStorageLocation());
1582         ASSERT_THAT(ThisLoc, NotNull());
1583 
1584         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1585         ASSERT_THAT(BarDecl, NotNull());
1586 
1587         const auto *BarLoc =
1588             cast<ScalarStorageLocation>(&ThisLoc->getChild(*BarDecl));
1589         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1590 
1591         const Value *BarVal = Env.getValue(*BarLoc);
1592         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1593 
1594         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1595         ASSERT_THAT(FooDecl, NotNull());
1596         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None), BarVal);
1597       },
1598       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1599 
1600   std::string FreeFunctionLambdaCode = R"(
1601     void foo() {
1602       int Bar;
1603       [&]() {
1604         int Foo = Bar;
1605         // [[p3]]
1606       }();
1607     }
1608   )";
1609   runDataflow(
1610       FreeFunctionLambdaCode,
1611       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1612          ASTContext &ASTCtx) {
1613         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p3"));
1614         const Environment &Env = getEnvironmentAtAnnotation(Results, "p3");
1615 
1616         EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull());
1617       },
1618       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1619 }
1620 
1621 TEST(TransferTest, ConstructorInitializer) {
1622   std::string Code = R"(
1623     struct target {
1624       int Bar;
1625 
1626       target(int Foo) : Bar(Foo) {
1627         int Qux = Bar;
1628         // [[p]]
1629       }
1630     };
1631   )";
1632   runDataflow(
1633       Code,
1634       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1635          ASTContext &ASTCtx) {
1636         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1637         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1638 
1639         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1640             Env.getThisPointeeStorageLocation());
1641         ASSERT_THAT(ThisLoc, NotNull());
1642 
1643         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1644         ASSERT_THAT(FooDecl, NotNull());
1645 
1646         const auto *FooVal =
1647             cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None));
1648 
1649         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1650         ASSERT_THAT(QuxDecl, NotNull());
1651         EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal);
1652       });
1653 }
1654 
1655 TEST(TransferTest, DefaultInitializer) {
1656   std::string Code = R"(
1657     struct target {
1658       int Bar;
1659       int Baz = Bar;
1660 
1661       target(int Foo) : Bar(Foo) {
1662         int Qux = Baz;
1663         // [[p]]
1664       }
1665     };
1666   )";
1667   runDataflow(
1668       Code,
1669       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1670          ASTContext &ASTCtx) {
1671         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1672         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1673 
1674         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1675             Env.getThisPointeeStorageLocation());
1676         ASSERT_THAT(ThisLoc, NotNull());
1677 
1678         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1679         ASSERT_THAT(FooDecl, NotNull());
1680 
1681         const auto *FooVal =
1682             cast<IntegerValue>(Env.getValue(*FooDecl, SkipPast::None));
1683 
1684         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1685         ASSERT_THAT(QuxDecl, NotNull());
1686         EXPECT_EQ(Env.getValue(*QuxDecl, SkipPast::None), FooVal);
1687       });
1688 }
1689 
1690 TEST(TransferTest, DefaultInitializerReference) {
1691   std::string Code = R"(
1692     struct target {
1693       int &Bar;
1694       int &Baz = Bar;
1695 
1696       target(int &Foo) : Bar(Foo) {
1697         int &Qux = Baz;
1698         // [[p]]
1699       }
1700     };
1701   )";
1702   runDataflow(
1703       Code,
1704       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1705          ASTContext &ASTCtx) {
1706         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1707         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1708 
1709         const auto *ThisLoc = dyn_cast<AggregateStorageLocation>(
1710             Env.getThisPointeeStorageLocation());
1711         ASSERT_THAT(ThisLoc, NotNull());
1712 
1713         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1714         ASSERT_THAT(FooDecl, NotNull());
1715 
1716         const auto *FooVal =
1717             cast<ReferenceValue>(Env.getValue(*FooDecl, SkipPast::None));
1718 
1719         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1720         ASSERT_THAT(QuxDecl, NotNull());
1721 
1722         const auto *QuxVal =
1723             cast<ReferenceValue>(Env.getValue(*QuxDecl, SkipPast::None));
1724         EXPECT_EQ(&QuxVal->getReferentLoc(), &FooVal->getReferentLoc());
1725       });
1726 }
1727 
1728 TEST(TransferTest, TemporaryObject) {
1729   std::string Code = R"(
1730     struct A {
1731       int Bar;
1732     };
1733 
1734     void target() {
1735       A Foo = A();
1736       // [[p]]
1737     }
1738   )";
1739   runDataflow(
1740       Code,
1741       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1742          ASTContext &ASTCtx) {
1743         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1744         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1745 
1746         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1747         ASSERT_THAT(FooDecl, NotNull());
1748 
1749         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1750         ASSERT_THAT(BarDecl, NotNull());
1751 
1752         const auto *FooLoc = cast<AggregateStorageLocation>(
1753             Env.getStorageLocation(*FooDecl, SkipPast::None));
1754         const auto *BarLoc =
1755             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
1756 
1757         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1758         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1759         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
1760       });
1761 }
1762 
1763 TEST(TransferTest, ElidableConstructor) {
1764   // This test is effectively the same as TransferTest.TemporaryObject, but
1765   // the code is compiled as C++ 14.
1766   std::string Code = R"(
1767     struct A {
1768       int Bar;
1769     };
1770 
1771     void target() {
1772       A Foo = A();
1773       // [[p]]
1774     }
1775   )";
1776   runDataflow(
1777       Code,
1778       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1779          ASTContext &ASTCtx) {
1780         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1781         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1782 
1783         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1784         ASSERT_THAT(FooDecl, NotNull());
1785 
1786         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1787         ASSERT_THAT(BarDecl, NotNull());
1788 
1789         const auto *FooLoc = cast<AggregateStorageLocation>(
1790             Env.getStorageLocation(*FooDecl, SkipPast::None));
1791         const auto *BarLoc =
1792             cast<ScalarStorageLocation>(&FooLoc->getChild(*BarDecl));
1793 
1794         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1795         const auto *BarVal = cast<IntegerValue>(FooVal->getChild(*BarDecl));
1796         EXPECT_EQ(Env.getValue(*BarLoc), BarVal);
1797       },
1798       LangStandard::lang_cxx14);
1799 }
1800 
1801 TEST(TransferTest, AssignmentOperator) {
1802   std::string Code = R"(
1803     struct A {
1804       int Baz;
1805     };
1806 
1807     void target() {
1808       A Foo;
1809       A Bar;
1810       // [[p1]]
1811       Foo = Bar;
1812       // [[p2]]
1813     }
1814   )";
1815   runDataflow(
1816       Code,
1817       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1818          ASTContext &ASTCtx) {
1819         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
1820         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
1821         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
1822 
1823         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1824         ASSERT_THAT(FooDecl, NotNull());
1825 
1826         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1827         ASSERT_THAT(BarDecl, NotNull());
1828 
1829         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1830         ASSERT_THAT(BazDecl, NotNull());
1831 
1832         const auto *FooLoc1 = cast<AggregateStorageLocation>(
1833             Env1.getStorageLocation(*FooDecl, SkipPast::None));
1834         const auto *BarLoc1 = cast<AggregateStorageLocation>(
1835             Env1.getStorageLocation(*BarDecl, SkipPast::None));
1836 
1837         const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1));
1838         const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1));
1839         EXPECT_NE(FooVal1, BarVal1);
1840 
1841         const auto *FooBazVal1 =
1842             cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl)));
1843         const auto *BarBazVal1 =
1844             cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl)));
1845         EXPECT_NE(FooBazVal1, BarBazVal1);
1846 
1847         const auto *FooLoc2 = cast<AggregateStorageLocation>(
1848             Env2.getStorageLocation(*FooDecl, SkipPast::None));
1849         const auto *BarLoc2 = cast<AggregateStorageLocation>(
1850             Env2.getStorageLocation(*BarDecl, SkipPast::None));
1851 
1852         const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2));
1853         const auto *BarVal2 = cast<StructValue>(Env2.getValue(*BarLoc2));
1854         EXPECT_EQ(FooVal2, BarVal2);
1855 
1856         const auto *FooBazVal2 =
1857             cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl)));
1858         const auto *BarBazVal2 =
1859             cast<IntegerValue>(Env2.getValue(BarLoc1->getChild(*BazDecl)));
1860         EXPECT_EQ(FooBazVal2, BarBazVal2);
1861       });
1862 }
1863 
1864 TEST(TransferTest, CopyConstructor) {
1865   std::string Code = R"(
1866     struct A {
1867       int Baz;
1868     };
1869 
1870     void target() {
1871       A Foo;
1872       A Bar = Foo;
1873       // [[p]]
1874     }
1875   )";
1876   runDataflow(
1877       Code,
1878       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1879          ASTContext &ASTCtx) {
1880         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1881         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1882 
1883         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1884         ASSERT_THAT(FooDecl, NotNull());
1885 
1886         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1887         ASSERT_THAT(BarDecl, NotNull());
1888 
1889         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1890         ASSERT_THAT(BazDecl, NotNull());
1891 
1892         const auto *FooLoc = cast<AggregateStorageLocation>(
1893             Env.getStorageLocation(*FooDecl, SkipPast::None));
1894         const auto *BarLoc = cast<AggregateStorageLocation>(
1895             Env.getStorageLocation(*BarDecl, SkipPast::None));
1896 
1897         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1898         const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc));
1899         EXPECT_EQ(FooVal, BarVal);
1900 
1901         const auto *FooBazVal =
1902             cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl)));
1903         const auto *BarBazVal =
1904             cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl)));
1905         EXPECT_EQ(FooBazVal, BarBazVal);
1906       });
1907 }
1908 
1909 TEST(TransferTest, CopyConstructorWithParens) {
1910   std::string Code = R"(
1911     struct A {
1912       int Baz;
1913     };
1914 
1915     void target() {
1916       A Foo;
1917       A Bar((A(Foo)));
1918       // [[p]]
1919     }
1920   )";
1921   runDataflow(
1922       Code,
1923       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1924          ASTContext &ASTCtx) {
1925         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1926         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1927 
1928         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1929         ASSERT_THAT(FooDecl, NotNull());
1930 
1931         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1932         ASSERT_THAT(BarDecl, NotNull());
1933 
1934         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1935         ASSERT_THAT(BazDecl, NotNull());
1936 
1937         const auto *FooLoc = cast<AggregateStorageLocation>(
1938             Env.getStorageLocation(*FooDecl, SkipPast::None));
1939         const auto *BarLoc = cast<AggregateStorageLocation>(
1940             Env.getStorageLocation(*BarDecl, SkipPast::None));
1941 
1942         const auto *FooVal = cast<StructValue>(Env.getValue(*FooLoc));
1943         const auto *BarVal = cast<StructValue>(Env.getValue(*BarLoc));
1944         EXPECT_EQ(FooVal, BarVal);
1945 
1946         const auto *FooBazVal =
1947             cast<IntegerValue>(Env.getValue(FooLoc->getChild(*BazDecl)));
1948         const auto *BarBazVal =
1949             cast<IntegerValue>(Env.getValue(BarLoc->getChild(*BazDecl)));
1950         EXPECT_EQ(FooBazVal, BarBazVal);
1951       });
1952 }
1953 
1954 TEST(TransferTest, MoveConstructor) {
1955   std::string Code = R"(
1956     namespace std {
1957 
1958     template <typename T> struct remove_reference      { using type = T; };
1959     template <typename T> struct remove_reference<T&>  { using type = T; };
1960     template <typename T> struct remove_reference<T&&> { using type = T; };
1961 
1962     template <typename T>
1963     using remove_reference_t = typename remove_reference<T>::type;
1964 
1965     template <typename T>
1966     std::remove_reference_t<T>&& move(T&& x);
1967 
1968     } // namespace std
1969 
1970     struct A {
1971       int Baz;
1972     };
1973 
1974     void target() {
1975       A Foo;
1976       A Bar;
1977       // [[p1]]
1978       Foo = std::move(Bar);
1979       // [[p2]]
1980     }
1981   )";
1982   runDataflow(
1983       Code,
1984       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1985          ASTContext &ASTCtx) {
1986         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
1987         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
1988         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
1989 
1990         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1991         ASSERT_THAT(FooDecl, NotNull());
1992 
1993         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1994         ASSERT_THAT(BarDecl, NotNull());
1995 
1996         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1997         ASSERT_THAT(BazDecl, NotNull());
1998 
1999         const auto *FooLoc1 = cast<AggregateStorageLocation>(
2000             Env1.getStorageLocation(*FooDecl, SkipPast::None));
2001         const auto *BarLoc1 = cast<AggregateStorageLocation>(
2002             Env1.getStorageLocation(*BarDecl, SkipPast::None));
2003 
2004         const auto *FooVal1 = cast<StructValue>(Env1.getValue(*FooLoc1));
2005         const auto *BarVal1 = cast<StructValue>(Env1.getValue(*BarLoc1));
2006         EXPECT_NE(FooVal1, BarVal1);
2007 
2008         const auto *FooBazVal1 =
2009             cast<IntegerValue>(Env1.getValue(FooLoc1->getChild(*BazDecl)));
2010         const auto *BarBazVal1 =
2011             cast<IntegerValue>(Env1.getValue(BarLoc1->getChild(*BazDecl)));
2012         EXPECT_NE(FooBazVal1, BarBazVal1);
2013 
2014         const auto *FooLoc2 = cast<AggregateStorageLocation>(
2015             Env2.getStorageLocation(*FooDecl, SkipPast::None));
2016         const auto *FooVal2 = cast<StructValue>(Env2.getValue(*FooLoc2));
2017         EXPECT_EQ(FooVal2, BarVal1);
2018 
2019         const auto *FooBazVal2 =
2020             cast<IntegerValue>(Env2.getValue(FooLoc1->getChild(*BazDecl)));
2021         EXPECT_EQ(FooBazVal2, BarBazVal1);
2022       });
2023 }
2024 
2025 TEST(TransferTest, BindTemporary) {
2026   std::string Code = R"(
2027     struct A {
2028       virtual ~A() = default;
2029 
2030       int Baz;
2031     };
2032 
2033     void target(A Foo) {
2034       int Bar = A(Foo).Baz;
2035       // [[p]]
2036     }
2037   )";
2038   runDataflow(
2039       Code,
2040       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2041          ASTContext &ASTCtx) {
2042         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2043         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2044 
2045         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2046         ASSERT_THAT(FooDecl, NotNull());
2047 
2048         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2049         ASSERT_THAT(BarDecl, NotNull());
2050 
2051         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2052         ASSERT_THAT(BazDecl, NotNull());
2053 
2054         const auto &FooVal =
2055             *cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None));
2056         const auto *BarVal =
2057             cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
2058         EXPECT_EQ(BarVal, FooVal.getChild(*BazDecl));
2059       });
2060 }
2061 
2062 TEST(TransferTest, StaticCast) {
2063   std::string Code = R"(
2064     void target(int Foo) {
2065       int Bar = static_cast<int>(Foo);
2066       // [[p]]
2067     }
2068   )";
2069   runDataflow(
2070       Code,
2071       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2072          ASTContext &ASTCtx) {
2073         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2074         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2075 
2076         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2077         ASSERT_THAT(FooDecl, NotNull());
2078 
2079         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2080         ASSERT_THAT(BarDecl, NotNull());
2081 
2082         const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2083         const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2084         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2085         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2086         EXPECT_EQ(FooVal, BarVal);
2087       });
2088 }
2089 
2090 TEST(TransferTest, IntegralCast) {
2091   std::string Code = R"(
2092     void target(int Foo) {
2093       long Bar = Foo;
2094       // [[p]]
2095     }
2096   )";
2097   runDataflow(
2098       Code,
2099       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2100          ASTContext &ASTCtx) {
2101         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2102         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2103 
2104         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2105         ASSERT_THAT(FooDecl, NotNull());
2106 
2107         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2108         ASSERT_THAT(BarDecl, NotNull());
2109 
2110         const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2111         const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2112         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2113         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2114         EXPECT_EQ(FooVal, BarVal);
2115       });
2116 }
2117 
2118 TEST(TransferTest, IntegraltoBooleanCast) {
2119   std::string Code = R"(
2120     void target(int Foo) {
2121       bool Bar = Foo;
2122       // [[p]]
2123     }
2124   )";
2125   runDataflow(
2126       Code,
2127       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2128          ASTContext &ASTCtx) {
2129         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2130         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2131 
2132         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2133         ASSERT_THAT(FooDecl, NotNull());
2134 
2135         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2136         ASSERT_THAT(BarDecl, NotNull());
2137 
2138         const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2139         const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2140         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2141         EXPECT_TRUE(isa<BoolValue>(BarVal));
2142       });
2143 }
2144 
2145 TEST(TransferTest, IntegralToBooleanCastFromBool) {
2146   std::string Code = R"(
2147     void target(bool Foo) {
2148       int Zab = Foo;
2149       bool Bar = Zab;
2150       // [[p]]
2151     }
2152   )";
2153   runDataflow(
2154       Code,
2155       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2156          ASTContext &ASTCtx) {
2157         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2158         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2159 
2160         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2161         ASSERT_THAT(FooDecl, NotNull());
2162 
2163         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2164         ASSERT_THAT(BarDecl, NotNull());
2165 
2166         const auto *FooVal = Env.getValue(*FooDecl, SkipPast::None);
2167         const auto *BarVal = Env.getValue(*BarDecl, SkipPast::None);
2168         EXPECT_TRUE(isa<BoolValue>(FooVal));
2169         EXPECT_TRUE(isa<BoolValue>(BarVal));
2170         EXPECT_EQ(FooVal, BarVal);
2171       });
2172 }
2173 
2174 TEST(TransferTest, NullToPointerCast) {
2175   std::string Code = R"(
2176     using my_nullptr_t = decltype(nullptr);
2177     struct Baz {};
2178     void target() {
2179       int *FooX = nullptr;
2180       int *FooY = nullptr;
2181       bool **Bar = nullptr;
2182       Baz *Baz = nullptr;
2183       my_nullptr_t Null = 0;
2184       // [[p]]
2185     }
2186   )";
2187   runDataflow(
2188       Code,
2189       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2190          ASTContext &ASTCtx) {
2191         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2192         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2193 
2194         const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
2195         ASSERT_THAT(FooXDecl, NotNull());
2196 
2197         const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
2198         ASSERT_THAT(FooYDecl, NotNull());
2199 
2200         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2201         ASSERT_THAT(BarDecl, NotNull());
2202 
2203         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2204         ASSERT_THAT(BazDecl, NotNull());
2205 
2206         const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
2207         ASSERT_THAT(NullDecl, NotNull());
2208 
2209         const auto *FooXVal =
2210             cast<PointerValue>(Env.getValue(*FooXDecl, SkipPast::None));
2211         const auto *FooYVal =
2212             cast<PointerValue>(Env.getValue(*FooYDecl, SkipPast::None));
2213         const auto *BarVal =
2214             cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
2215         const auto *BazVal =
2216             cast<PointerValue>(Env.getValue(*BazDecl, SkipPast::None));
2217         const auto *NullVal =
2218             cast<PointerValue>(Env.getValue(*NullDecl, SkipPast::None));
2219 
2220         EXPECT_EQ(FooXVal, FooYVal);
2221         EXPECT_NE(FooXVal, BarVal);
2222         EXPECT_NE(FooXVal, BazVal);
2223         EXPECT_NE(BarVal, BazVal);
2224 
2225         const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
2226         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
2227         EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
2228 
2229         const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
2230         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
2231         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
2232 
2233         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
2234         EXPECT_TRUE(isa<AggregateStorageLocation>(BazPointeeLoc));
2235         EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull());
2236 
2237         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
2238         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
2239         EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
2240       });
2241 }
2242 
2243 TEST(TransferTest, NullToMemberPointerCast) {
2244   std::string Code = R"(
2245     struct Foo {};
2246     void target(Foo *Foo) {
2247       int Foo::*MemberPointer = nullptr;
2248       // [[p]]
2249     }
2250   )";
2251   runDataflow(
2252       Code,
2253       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2254          ASTContext &ASTCtx) {
2255         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2256         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2257 
2258         const ValueDecl *MemberPointerDecl =
2259             findValueDecl(ASTCtx, "MemberPointer");
2260         ASSERT_THAT(MemberPointerDecl, NotNull());
2261 
2262         const auto *MemberPointerVal = cast<PointerValue>(
2263             Env.getValue(*MemberPointerDecl, SkipPast::None));
2264 
2265         const StorageLocation &MemberLoc = MemberPointerVal->getPointeeLoc();
2266         EXPECT_THAT(Env.getValue(MemberLoc), IsNull());
2267       });
2268 }
2269 
2270 TEST(TransferTest, AddrOfValue) {
2271   std::string Code = R"(
2272     void target() {
2273       int Foo;
2274       int *Bar = &Foo;
2275       // [[p]]
2276     }
2277   )";
2278   runDataflow(
2279       Code,
2280       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2281          ASTContext &ASTCtx) {
2282         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2283         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2284 
2285         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2286         ASSERT_THAT(FooDecl, NotNull());
2287 
2288         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2289         ASSERT_THAT(BarDecl, NotNull());
2290 
2291         const auto *FooLoc = cast<ScalarStorageLocation>(
2292             Env.getStorageLocation(*FooDecl, SkipPast::None));
2293         const auto *BarVal =
2294             cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
2295         EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
2296       });
2297 }
2298 
2299 TEST(TransferTest, AddrOfReference) {
2300   std::string Code = R"(
2301     void target(int *Foo) {
2302       int *Bar = &(*Foo);
2303       // [[p]]
2304     }
2305   )";
2306   runDataflow(
2307       Code,
2308       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2309          ASTContext &ASTCtx) {
2310         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2311         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2312 
2313         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2314         ASSERT_THAT(FooDecl, NotNull());
2315 
2316         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2317         ASSERT_THAT(BarDecl, NotNull());
2318 
2319         const auto *FooVal =
2320             cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2321         const auto *BarVal =
2322             cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None));
2323         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
2324       });
2325 }
2326 
2327 TEST(TransferTest, DerefDependentPtr) {
2328   std::string Code = R"(
2329     template <typename T>
2330     void target(T *Foo) {
2331       T &Bar = *Foo;
2332       /*[[p]]*/
2333     }
2334   )";
2335   runDataflow(
2336       Code,
2337       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2338          ASTContext &ASTCtx) {
2339         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2340         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2341 
2342         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2343         ASSERT_THAT(FooDecl, NotNull());
2344 
2345         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2346         ASSERT_THAT(BarDecl, NotNull());
2347 
2348         const auto *FooVal =
2349             cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2350         const auto *BarVal =
2351             cast<ReferenceValue>(Env.getValue(*BarDecl, SkipPast::None));
2352         EXPECT_EQ(&BarVal->getReferentLoc(), &FooVal->getPointeeLoc());
2353       });
2354 }
2355 
2356 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
2357   std::string Code = R"(
2358     struct A {};
2359 
2360     void target(A Foo, A Bar, bool Cond) {
2361       A Baz = Cond ?  Foo : Bar;
2362       /*[[p]]*/
2363     }
2364   )";
2365   runDataflow(
2366       Code,
2367       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2368          ASTContext &ASTCtx) {
2369         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2370         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2371 
2372         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2373         ASSERT_THAT(FooDecl, NotNull());
2374 
2375         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2376         ASSERT_THAT(BarDecl, NotNull());
2377 
2378         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2379         ASSERT_THAT(BazDecl, NotNull());
2380 
2381         const auto *FooVal =
2382             cast<StructValue>(Env.getValue(*FooDecl, SkipPast::None));
2383         const auto *BarVal =
2384             cast<StructValue>(Env.getValue(*BarDecl, SkipPast::None));
2385 
2386         const auto *BazVal =
2387             dyn_cast<StructValue>(Env.getValue(*BazDecl, SkipPast::None));
2388         ASSERT_THAT(BazVal, NotNull());
2389 
2390         EXPECT_NE(BazVal, FooVal);
2391         EXPECT_NE(BazVal, BarVal);
2392       });
2393 }
2394 
2395 TEST(TransferTest, VarDeclInDoWhile) {
2396   std::string Code = R"(
2397     void target(int *Foo) {
2398       do {
2399         int Bar = *Foo;
2400       } while (true);
2401       (void)0;
2402       /*[[p]]*/
2403     }
2404   )";
2405   runDataflow(
2406       Code,
2407       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2408          ASTContext &ASTCtx) {
2409         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2410         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2411 
2412         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2413         ASSERT_THAT(FooDecl, NotNull());
2414 
2415         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2416         ASSERT_THAT(BarDecl, NotNull());
2417 
2418         const auto *FooVal =
2419             cast<PointerValue>(Env.getValue(*FooDecl, SkipPast::None));
2420         const auto *FooPointeeVal =
2421             cast<IntegerValue>(Env.getValue(FooVal->getPointeeLoc()));
2422 
2423         const auto *BarVal = dyn_cast_or_null<IntegerValue>(
2424             Env.getValue(*BarDecl, SkipPast::None));
2425         ASSERT_THAT(BarVal, NotNull());
2426 
2427         EXPECT_EQ(BarVal, FooPointeeVal);
2428       });
2429 }
2430 
2431 TEST(TransferTest, AggregateInitialization) {
2432   std::string BracesCode = R"(
2433     struct A {
2434       int Foo;
2435     };
2436 
2437     struct B {
2438       int Bar;
2439       A Baz;
2440       int Qux;
2441     };
2442 
2443     void target(int BarArg, int FooArg, int QuxArg) {
2444       B Quux{BarArg, {FooArg}, QuxArg};
2445       /*[[p]]*/
2446     }
2447   )";
2448   std::string BraceEllisionCode = R"(
2449     struct A {
2450       int Foo;
2451     };
2452 
2453     struct B {
2454       int Bar;
2455       A Baz;
2456       int Qux;
2457     };
2458 
2459     void target(int BarArg, int FooArg, int QuxArg) {
2460       B Quux = {BarArg, FooArg, QuxArg};
2461       /*[[p]]*/
2462     }
2463   )";
2464   for (const std::string &Code : {BracesCode, BraceEllisionCode}) {
2465     runDataflow(
2466         Code,
2467         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2468            ASTContext &ASTCtx) {
2469           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2470           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2471 
2472           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2473           ASSERT_THAT(FooDecl, NotNull());
2474 
2475           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2476           ASSERT_THAT(BarDecl, NotNull());
2477 
2478           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2479           ASSERT_THAT(BazDecl, NotNull());
2480 
2481           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2482           ASSERT_THAT(QuxDecl, NotNull());
2483 
2484           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
2485           ASSERT_THAT(FooArgDecl, NotNull());
2486 
2487           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
2488           ASSERT_THAT(BarArgDecl, NotNull());
2489 
2490           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
2491           ASSERT_THAT(QuxArgDecl, NotNull());
2492 
2493           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
2494           ASSERT_THAT(QuuxDecl, NotNull());
2495 
2496           const auto *FooArgVal =
2497               cast<IntegerValue>(Env.getValue(*FooArgDecl, SkipPast::None));
2498           const auto *BarArgVal =
2499               cast<IntegerValue>(Env.getValue(*BarArgDecl, SkipPast::None));
2500           const auto *QuxArgVal =
2501               cast<IntegerValue>(Env.getValue(*QuxArgDecl, SkipPast::None));
2502 
2503           const auto *QuuxVal =
2504               cast<StructValue>(Env.getValue(*QuuxDecl, SkipPast::None));
2505           ASSERT_THAT(QuuxVal, NotNull());
2506 
2507           const auto *BazVal = cast<StructValue>(QuuxVal->getChild(*BazDecl));
2508           ASSERT_THAT(BazVal, NotNull());
2509 
2510           EXPECT_EQ(QuuxVal->getChild(*BarDecl), BarArgVal);
2511           EXPECT_EQ(BazVal->getChild(*FooDecl), FooArgVal);
2512           EXPECT_EQ(QuuxVal->getChild(*QuxDecl), QuxArgVal);
2513         });
2514   }
2515 }
2516 
2517 TEST(TransferTest, AssignToUnionMember) {
2518   std::string Code = R"(
2519     union A {
2520       int Foo;
2521     };
2522 
2523     void target(int Bar) {
2524       A Baz;
2525       Baz.Foo = Bar;
2526       // [[p]]
2527     }
2528   )";
2529   runDataflow(
2530       Code,
2531       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2532          ASTContext &ASTCtx) {
2533         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2534         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2535 
2536         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2537         ASSERT_THAT(BazDecl, NotNull());
2538         ASSERT_TRUE(BazDecl->getType()->isUnionType());
2539 
2540         const auto *BazLoc = dyn_cast_or_null<AggregateStorageLocation>(
2541             Env.getStorageLocation(*BazDecl, SkipPast::None));
2542         ASSERT_THAT(BazLoc, NotNull());
2543 
2544         // FIXME: Add support for union types.
2545         EXPECT_THAT(Env.getValue(*BazLoc), IsNull());
2546       });
2547 }
2548 
2549 TEST(TransferTest, AssignFromBoolLiteral) {
2550   std::string Code = R"(
2551     void target() {
2552       bool Foo = true;
2553       bool Bar = false;
2554       // [[p]]
2555     }
2556   )";
2557   runDataflow(
2558       Code,
2559       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2560          ASTContext &ASTCtx) {
2561         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2562         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2563 
2564         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2565         ASSERT_THAT(FooDecl, NotNull());
2566 
2567         const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>(
2568             Env.getValue(*FooDecl, SkipPast::None));
2569         ASSERT_THAT(FooVal, NotNull());
2570 
2571         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2572         ASSERT_THAT(BarDecl, NotNull());
2573 
2574         const auto *BarVal = dyn_cast_or_null<AtomicBoolValue>(
2575             Env.getValue(*BarDecl, SkipPast::None));
2576         ASSERT_THAT(BarVal, NotNull());
2577 
2578         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
2579         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
2580       });
2581 }
2582 
2583 TEST(TransferTest, AssignFromCompositeBoolExpression) {
2584   {
2585     std::string Code = R"(
2586     void target(bool Foo, bool Bar, bool Qux) {
2587       bool Baz = (Foo) && (Bar || Qux);
2588       // [[p]]
2589     }
2590   )";
2591     runDataflow(
2592         Code,
2593         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2594            ASTContext &ASTCtx) {
2595           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2596           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2597 
2598           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2599           ASSERT_THAT(FooDecl, NotNull());
2600 
2601           const auto *FooVal = dyn_cast_or_null<BoolValue>(
2602               Env.getValue(*FooDecl, SkipPast::None));
2603           ASSERT_THAT(FooVal, NotNull());
2604 
2605           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2606           ASSERT_THAT(BarDecl, NotNull());
2607 
2608           const auto *BarVal = dyn_cast_or_null<BoolValue>(
2609               Env.getValue(*BarDecl, SkipPast::None));
2610           ASSERT_THAT(BarVal, NotNull());
2611 
2612           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2613           ASSERT_THAT(QuxDecl, NotNull());
2614 
2615           const auto *QuxVal = dyn_cast_or_null<BoolValue>(
2616               Env.getValue(*QuxDecl, SkipPast::None));
2617           ASSERT_THAT(QuxVal, NotNull());
2618 
2619           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2620           ASSERT_THAT(BazDecl, NotNull());
2621 
2622           const auto *BazVal = dyn_cast_or_null<ConjunctionValue>(
2623               Env.getValue(*BazDecl, SkipPast::None));
2624           ASSERT_THAT(BazVal, NotNull());
2625           EXPECT_EQ(&BazVal->getLeftSubValue(), FooVal);
2626 
2627           const auto *BazRightSubValVal =
2628               cast<DisjunctionValue>(&BazVal->getRightSubValue());
2629           EXPECT_EQ(&BazRightSubValVal->getLeftSubValue(), BarVal);
2630           EXPECT_EQ(&BazRightSubValVal->getRightSubValue(), QuxVal);
2631         });
2632   }
2633 
2634   {
2635     std::string Code = R"(
2636     void target(bool Foo, bool Bar, bool Qux) {
2637       bool Baz = (Foo && Qux) || (Bar);
2638       // [[p]]
2639     }
2640   )";
2641     runDataflow(
2642         Code,
2643         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2644            ASTContext &ASTCtx) {
2645           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2646           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2647 
2648           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2649           ASSERT_THAT(FooDecl, NotNull());
2650 
2651           const auto *FooVal = dyn_cast_or_null<BoolValue>(
2652               Env.getValue(*FooDecl, SkipPast::None));
2653           ASSERT_THAT(FooVal, NotNull());
2654 
2655           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2656           ASSERT_THAT(BarDecl, NotNull());
2657 
2658           const auto *BarVal = dyn_cast_or_null<BoolValue>(
2659               Env.getValue(*BarDecl, SkipPast::None));
2660           ASSERT_THAT(BarVal, NotNull());
2661 
2662           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2663           ASSERT_THAT(QuxDecl, NotNull());
2664 
2665           const auto *QuxVal = dyn_cast_or_null<BoolValue>(
2666               Env.getValue(*QuxDecl, SkipPast::None));
2667           ASSERT_THAT(QuxVal, NotNull());
2668 
2669           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2670           ASSERT_THAT(BazDecl, NotNull());
2671 
2672           const auto *BazVal = dyn_cast_or_null<DisjunctionValue>(
2673               Env.getValue(*BazDecl, SkipPast::None));
2674           ASSERT_THAT(BazVal, NotNull());
2675 
2676           const auto *BazLeftSubValVal =
2677               cast<ConjunctionValue>(&BazVal->getLeftSubValue());
2678           EXPECT_EQ(&BazLeftSubValVal->getLeftSubValue(), FooVal);
2679           EXPECT_EQ(&BazLeftSubValVal->getRightSubValue(), QuxVal);
2680 
2681           EXPECT_EQ(&BazVal->getRightSubValue(), BarVal);
2682         });
2683   }
2684 
2685   {
2686     std::string Code = R"(
2687       void target(bool A, bool B, bool C, bool D) {
2688         bool Foo = ((A && B) && C) && D;
2689         // [[p]]
2690       }
2691     )";
2692     runDataflow(
2693         Code,
2694         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2695            ASTContext &ASTCtx) {
2696           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2697           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2698 
2699           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
2700           ASSERT_THAT(ADecl, NotNull());
2701 
2702           const auto *AVal =
2703               dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl, SkipPast::None));
2704           ASSERT_THAT(AVal, NotNull());
2705 
2706           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
2707           ASSERT_THAT(BDecl, NotNull());
2708 
2709           const auto *BVal =
2710               dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl, SkipPast::None));
2711           ASSERT_THAT(BVal, NotNull());
2712 
2713           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
2714           ASSERT_THAT(CDecl, NotNull());
2715 
2716           const auto *CVal =
2717               dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
2718           ASSERT_THAT(CVal, NotNull());
2719 
2720           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
2721           ASSERT_THAT(DDecl, NotNull());
2722 
2723           const auto *DVal =
2724               dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl, SkipPast::None));
2725           ASSERT_THAT(DVal, NotNull());
2726 
2727           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2728           ASSERT_THAT(FooDecl, NotNull());
2729 
2730           const auto *FooVal = dyn_cast_or_null<ConjunctionValue>(
2731               Env.getValue(*FooDecl, SkipPast::None));
2732           ASSERT_THAT(FooVal, NotNull());
2733 
2734           const auto &FooLeftSubVal =
2735               cast<ConjunctionValue>(FooVal->getLeftSubValue());
2736           const auto &FooLeftLeftSubVal =
2737               cast<ConjunctionValue>(FooLeftSubVal.getLeftSubValue());
2738           EXPECT_EQ(&FooLeftLeftSubVal.getLeftSubValue(), AVal);
2739           EXPECT_EQ(&FooLeftLeftSubVal.getRightSubValue(), BVal);
2740           EXPECT_EQ(&FooLeftSubVal.getRightSubValue(), CVal);
2741           EXPECT_EQ(&FooVal->getRightSubValue(), DVal);
2742         });
2743   }
2744 }
2745 
2746 TEST(TransferTest, AssignFromBoolNegation) {
2747   std::string Code = R"(
2748     void target() {
2749       bool Foo = true;
2750       bool Bar = !(Foo);
2751       // [[p]]
2752     }
2753   )";
2754   runDataflow(
2755       Code,
2756       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2757          ASTContext &ASTCtx) {
2758         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2759         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2760 
2761         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2762         ASSERT_THAT(FooDecl, NotNull());
2763 
2764         const auto *FooVal = dyn_cast_or_null<AtomicBoolValue>(
2765             Env.getValue(*FooDecl, SkipPast::None));
2766         ASSERT_THAT(FooVal, NotNull());
2767 
2768         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2769         ASSERT_THAT(BarDecl, NotNull());
2770 
2771         const auto *BarVal = dyn_cast_or_null<NegationValue>(
2772             Env.getValue(*BarDecl, SkipPast::None));
2773         ASSERT_THAT(BarVal, NotNull());
2774 
2775         EXPECT_EQ(&BarVal->getSubVal(), FooVal);
2776       });
2777 }
2778 
2779 TEST(TransferTest, BuiltinExpect) {
2780   std::string Code = R"(
2781     void target(long Foo) {
2782       long Bar = __builtin_expect(Foo, true);
2783       /*[[p]]*/
2784     }
2785   )";
2786   runDataflow(
2787       Code,
2788       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2789          ASTContext &ASTCtx) {
2790         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2791         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2792 
2793         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2794         ASSERT_THAT(FooDecl, NotNull());
2795 
2796         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2797         ASSERT_THAT(BarDecl, NotNull());
2798 
2799         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2800                   Env.getValue(*BarDecl, SkipPast::None));
2801       });
2802 }
2803 
2804 // `__builtin_expect` takes and returns a `long` argument, so other types
2805 // involve casts. This verifies that we identify the input and output in that
2806 // case.
2807 TEST(TransferTest, BuiltinExpectBoolArg) {
2808   std::string Code = R"(
2809     void target(bool Foo) {
2810       bool Bar = __builtin_expect(Foo, true);
2811       /*[[p]]*/
2812     }
2813   )";
2814   runDataflow(
2815       Code,
2816       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2817          ASTContext &ASTCtx) {
2818         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2819         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2820 
2821         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2822         ASSERT_THAT(FooDecl, NotNull());
2823 
2824         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2825         ASSERT_THAT(BarDecl, NotNull());
2826 
2827         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2828                   Env.getValue(*BarDecl, SkipPast::None));
2829       });
2830 }
2831 
2832 TEST(TransferTest, BuiltinUnreachable) {
2833   std::string Code = R"(
2834     void target(bool Foo) {
2835       bool Bar = false;
2836       if (Foo)
2837         Bar = Foo;
2838       else
2839         __builtin_unreachable();
2840       (void)0;
2841       /*[[p]]*/
2842     }
2843   )";
2844   runDataflow(
2845       Code,
2846       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2847          ASTContext &ASTCtx) {
2848         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2849         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2850 
2851         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2852         ASSERT_THAT(FooDecl, NotNull());
2853 
2854         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2855         ASSERT_THAT(BarDecl, NotNull());
2856 
2857         // `__builtin_unreachable` promises that the code is
2858         // unreachable, so the compiler treats the "then" branch as the
2859         // only possible predecessor of this statement.
2860         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2861                   Env.getValue(*BarDecl, SkipPast::None));
2862       });
2863 }
2864 
2865 TEST(TransferTest, BuiltinTrap) {
2866   std::string Code = R"(
2867     void target(bool Foo) {
2868       bool Bar = false;
2869       if (Foo)
2870         Bar = Foo;
2871       else
2872         __builtin_trap();
2873       (void)0;
2874       /*[[p]]*/
2875     }
2876   )";
2877   runDataflow(
2878       Code,
2879       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2880          ASTContext &ASTCtx) {
2881         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2882         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2883 
2884         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2885         ASSERT_THAT(FooDecl, NotNull());
2886 
2887         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2888         ASSERT_THAT(BarDecl, NotNull());
2889 
2890         // `__builtin_trap` ensures program termination, so only the
2891         // "then" branch is a predecessor of this statement.
2892         EXPECT_EQ(Env.getValue(*FooDecl, SkipPast::None),
2893                   Env.getValue(*BarDecl, SkipPast::None));
2894       });
2895 }
2896 
2897 TEST(TransferTest, BuiltinDebugTrap) {
2898   std::string Code = R"(
2899     void target(bool Foo) {
2900       bool Bar = false;
2901       if (Foo)
2902         Bar = Foo;
2903       else
2904         __builtin_debugtrap();
2905       (void)0;
2906       /*[[p]]*/
2907     }
2908   )";
2909   runDataflow(
2910       Code,
2911       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2912          ASTContext &ASTCtx) {
2913         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2914         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2915 
2916         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2917         ASSERT_THAT(FooDecl, NotNull());
2918 
2919         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2920         ASSERT_THAT(BarDecl, NotNull());
2921 
2922         // `__builtin_debugtrap` doesn't ensure program termination.
2923         EXPECT_NE(Env.getValue(*FooDecl, SkipPast::None),
2924                   Env.getValue(*BarDecl, SkipPast::None));
2925       });
2926 }
2927 
2928 TEST(TransferTest, StaticIntSingleVarDecl) {
2929   std::string Code = R"(
2930     void target() {
2931       static int Foo;
2932       // [[p]]
2933     }
2934   )";
2935   runDataflow(
2936       Code,
2937       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2938          ASTContext &ASTCtx) {
2939         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2940         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2941 
2942         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2943         ASSERT_THAT(FooDecl, NotNull());
2944 
2945         const StorageLocation *FooLoc =
2946             Env.getStorageLocation(*FooDecl, SkipPast::None);
2947         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
2948 
2949         const Value *FooVal = Env.getValue(*FooLoc);
2950         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
2951       });
2952 }
2953 
2954 TEST(TransferTest, StaticIntGroupVarDecl) {
2955   std::string Code = R"(
2956     void target() {
2957       static int Foo, Bar;
2958       (void)0;
2959       // [[p]]
2960     }
2961   )";
2962   runDataflow(
2963       Code,
2964       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2965          ASTContext &ASTCtx) {
2966         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2967         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2968 
2969         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2970         ASSERT_THAT(FooDecl, NotNull());
2971 
2972         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2973         ASSERT_THAT(BarDecl, NotNull());
2974 
2975         const StorageLocation *FooLoc =
2976             Env.getStorageLocation(*FooDecl, SkipPast::None);
2977         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
2978 
2979         const StorageLocation *BarLoc =
2980             Env.getStorageLocation(*BarDecl, SkipPast::None);
2981         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2982 
2983         const Value *FooVal = Env.getValue(*FooLoc);
2984         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
2985 
2986         const Value *BarVal = Env.getValue(*BarLoc);
2987         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
2988 
2989         EXPECT_NE(FooVal, BarVal);
2990       });
2991 }
2992 
2993 TEST(TransferTest, GlobalIntVarDecl) {
2994   std::string Code = R"(
2995     static int Foo;
2996 
2997     void target() {
2998       int Bar = Foo;
2999       int Baz = Foo;
3000       // [[p]]
3001     }
3002   )";
3003   runDataflow(
3004       Code,
3005       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3006          ASTContext &ASTCtx) {
3007         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3008         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3009 
3010         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3011         ASSERT_THAT(BarDecl, NotNull());
3012 
3013         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3014         ASSERT_THAT(BazDecl, NotNull());
3015 
3016         const Value *BarVal =
3017             cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3018         const Value *BazVal =
3019             cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
3020         EXPECT_EQ(BarVal, BazVal);
3021       });
3022 }
3023 
3024 TEST(TransferTest, StaticMemberIntVarDecl) {
3025   std::string Code = R"(
3026     struct A {
3027       static int Foo;
3028     };
3029 
3030     void target(A a) {
3031       int Bar = a.Foo;
3032       int Baz = a.Foo;
3033       // [[p]]
3034     }
3035   )";
3036   runDataflow(
3037       Code,
3038       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3039          ASTContext &ASTCtx) {
3040         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3041         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3042 
3043         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3044         ASSERT_THAT(BarDecl, NotNull());
3045 
3046         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3047         ASSERT_THAT(BazDecl, NotNull());
3048 
3049         const Value *BarVal =
3050             cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3051         const Value *BazVal =
3052             cast<IntegerValue>(Env.getValue(*BazDecl, SkipPast::None));
3053         EXPECT_EQ(BarVal, BazVal);
3054       });
3055 }
3056 
3057 TEST(TransferTest, StaticMemberRefVarDecl) {
3058   std::string Code = R"(
3059     struct A {
3060       static int &Foo;
3061     };
3062 
3063     void target(A a) {
3064       int Bar = a.Foo;
3065       int Baz = a.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, AssignMemberBeforeCopy) {
3091   std::string Code = R"(
3092     struct A {
3093       int Foo;
3094     };
3095 
3096     void target() {
3097       A A1;
3098       A A2;
3099       int Bar;
3100       A1.Foo = Bar;
3101       A2 = A1;
3102       // [[p]]
3103     }
3104   )";
3105   runDataflow(
3106       Code,
3107       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3108          ASTContext &ASTCtx) {
3109         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3110         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3111 
3112         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3113         ASSERT_THAT(FooDecl, NotNull());
3114 
3115         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3116         ASSERT_THAT(BarDecl, NotNull());
3117 
3118         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
3119         ASSERT_THAT(A1Decl, NotNull());
3120 
3121         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
3122         ASSERT_THAT(A2Decl, NotNull());
3123 
3124         const auto *BarVal =
3125             cast<IntegerValue>(Env.getValue(*BarDecl, SkipPast::None));
3126 
3127         const auto *A2Val =
3128             cast<StructValue>(Env.getValue(*A2Decl, SkipPast::None));
3129         EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal);
3130       });
3131 }
3132 
3133 TEST(TransferTest, BooleanEquality) {
3134   std::string Code = R"(
3135     void target(bool Bar) {
3136       bool Foo = true;
3137       if (Bar == Foo) {
3138         (void)0;
3139         /*[[p-then]]*/
3140       } else {
3141         (void)0;
3142         /*[[p-else]]*/
3143       }
3144     }
3145   )";
3146   runDataflow(
3147       Code,
3148       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3149          ASTContext &ASTCtx) {
3150         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3151         const Environment &EnvThen =
3152             getEnvironmentAtAnnotation(Results, "p-then");
3153         const Environment &EnvElse =
3154             getEnvironmentAtAnnotation(Results, "p-else");
3155 
3156         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3157         ASSERT_THAT(BarDecl, NotNull());
3158 
3159         auto &BarValThen =
3160             *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None));
3161         EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen));
3162 
3163         auto &BarValElse =
3164             *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None));
3165         EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse));
3166       });
3167 }
3168 
3169 TEST(TransferTest, BooleanInequality) {
3170   std::string Code = R"(
3171     void target(bool Bar) {
3172       bool Foo = true;
3173       if (Bar != Foo) {
3174         (void)0;
3175         /*[[p-then]]*/
3176       } else {
3177         (void)0;
3178         /*[[p-else]]*/
3179       }
3180     }
3181   )";
3182   runDataflow(
3183       Code,
3184       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3185          ASTContext &ASTCtx) {
3186         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3187         const Environment &EnvThen =
3188             getEnvironmentAtAnnotation(Results, "p-then");
3189         const Environment &EnvElse =
3190             getEnvironmentAtAnnotation(Results, "p-else");
3191 
3192         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3193         ASSERT_THAT(BarDecl, NotNull());
3194 
3195         auto &BarValThen =
3196             *cast<BoolValue>(EnvThen.getValue(*BarDecl, SkipPast::None));
3197         EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen));
3198 
3199         auto &BarValElse =
3200             *cast<BoolValue>(EnvElse.getValue(*BarDecl, SkipPast::None));
3201         EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse));
3202       });
3203 }
3204 
3205 TEST(TransferTest, CorrelatedBranches) {
3206   std::string Code = R"(
3207     void target(bool B, bool C) {
3208       if (B) {
3209         return;
3210       }
3211       (void)0;
3212       /*[[p0]]*/
3213       if (C) {
3214         B = true;
3215         /*[[p1]]*/
3216       }
3217       if (B) {
3218         (void)0;
3219         /*[[p2]]*/
3220       }
3221     }
3222   )";
3223   runDataflow(
3224       Code,
3225       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3226          ASTContext &ASTCtx) {
3227         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
3228 
3229         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3230         ASSERT_THAT(CDecl, NotNull());
3231 
3232         {
3233           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
3234           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3235           ASSERT_THAT(BDecl, NotNull());
3236           auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl, SkipPast::None));
3237 
3238           EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal)));
3239         }
3240 
3241         {
3242           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
3243           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
3244           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3245         }
3246 
3247         {
3248           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
3249           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl, SkipPast::None));
3250           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3251         }
3252       });
3253 }
3254 
3255 TEST(TransferTest, LoopWithAssignmentConverges) {
3256   std::string Code = R"(
3257     bool foo();
3258 
3259     void target() {
3260        do {
3261         bool Bar = foo();
3262         if (Bar) break;
3263         (void)Bar;
3264         /*[[p]]*/
3265       } while (true);
3266     }
3267   )";
3268   // The key property that we are verifying is implicit in `runDataflow` --
3269   // namely, that the analysis succeeds, rather than hitting the maximum number
3270   // of iterations.
3271   runDataflow(
3272       Code,
3273       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3274          ASTContext &ASTCtx) {
3275         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3276         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3277 
3278         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3279         ASSERT_THAT(BarDecl, NotNull());
3280 
3281         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
3282         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3283       });
3284 }
3285 
3286 TEST(TransferTest, LoopWithStagedAssignments) {
3287   std::string Code = R"(
3288     bool foo();
3289 
3290     void target() {
3291       bool Bar = false;
3292       bool Err = false;
3293       while (foo()) {
3294         if (Bar)
3295           Err = true;
3296         Bar = true;
3297         /*[[p]]*/
3298       }
3299     }
3300   )";
3301   runDataflow(
3302       Code,
3303       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3304          ASTContext &ASTCtx) {
3305         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3306         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3307 
3308         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3309         ASSERT_THAT(BarDecl, NotNull());
3310         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
3311         ASSERT_THAT(ErrDecl, NotNull());
3312 
3313         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
3314         auto &ErrVal = *cast<BoolValue>(Env.getValue(*ErrDecl, SkipPast::None));
3315         EXPECT_TRUE(Env.flowConditionImplies(BarVal));
3316         // An unsound analysis, for example only evaluating the loop once, can
3317         // conclude that `Err` is false. So, we test that this conclusion is not
3318         // reached.
3319         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(ErrVal)));
3320       });
3321 }
3322 
3323 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
3324   std::string Code = R"(
3325     bool &foo();
3326 
3327     void target() {
3328        do {
3329         bool& Bar = foo();
3330         if (Bar) break;
3331         (void)Bar;
3332         /*[[p]]*/
3333       } while (true);
3334     }
3335   )";
3336   // The key property that we are verifying is that the analysis succeeds,
3337   // rather than hitting the maximum number of iterations.
3338   runDataflow(
3339       Code,
3340       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3341          ASTContext &ASTCtx) {
3342         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3343         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3344 
3345         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3346         ASSERT_THAT(BarDecl, NotNull());
3347 
3348         auto &BarVal =
3349             *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::Reference));
3350         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3351       });
3352 }
3353 
3354 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
3355   std::string Code = R"(
3356     struct Lookup {
3357       int x;
3358     };
3359 
3360     void target(Lookup val, bool b) {
3361       const Lookup* l = nullptr;
3362       while (b) {
3363         l = &val;
3364         /*[[p-inner]]*/
3365       }
3366       (void)0;
3367       /*[[p-outer]]*/
3368     }
3369   )";
3370   // The key property that we are verifying is implicit in `runDataflow` --
3371   // namely, that the analysis succeeds, rather than hitting the maximum number
3372   // of iterations.
3373   runDataflow(
3374       Code,
3375       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3376          ASTContext &ASTCtx) {
3377         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
3378         const Environment &InnerEnv =
3379             getEnvironmentAtAnnotation(Results, "p-inner");
3380         const Environment &OuterEnv =
3381             getEnvironmentAtAnnotation(Results, "p-outer");
3382 
3383         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
3384         ASSERT_THAT(ValDecl, NotNull());
3385 
3386         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
3387         ASSERT_THAT(LDecl, NotNull());
3388 
3389         // Inner.
3390         auto *LVal =
3391             dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl, SkipPast::None));
3392         ASSERT_THAT(LVal, NotNull());
3393 
3394         EXPECT_EQ(&LVal->getPointeeLoc(),
3395                   InnerEnv.getStorageLocation(*ValDecl, SkipPast::Reference));
3396 
3397         // Outer.
3398         LVal =
3399             dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl, SkipPast::None));
3400         ASSERT_THAT(LVal, NotNull());
3401 
3402         // The loop body may not have been executed, so we should not conclude
3403         // that `l` points to `val`.
3404         EXPECT_NE(&LVal->getPointeeLoc(),
3405                   OuterEnv.getStorageLocation(*ValDecl, SkipPast::Reference));
3406       });
3407 }
3408 
3409 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
3410   std::string Code = R"(
3411     union Union {
3412       int A;
3413       float B;
3414     };
3415 
3416     void foo() {
3417       Union A;
3418       Union B;
3419       A = B;
3420     }
3421   )";
3422   // This is a crash regression test when calling the transfer function on a
3423   // `CXXThisExpr` that refers to a union.
3424   runDataflow(
3425       Code,
3426       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
3427          ASTContext &) {},
3428       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
3429 }
3430 
3431 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
3432   std::string Code = R"(
3433     struct A {
3434       int Foo;
3435       int Bar;
3436     };
3437 
3438     void target() {
3439       int Qux;
3440       A Baz;
3441       Baz.Foo = Qux;
3442       auto &FooRef = Baz.Foo;
3443       auto &BarRef = Baz.Bar;
3444       auto &[BoundFooRef, BoundBarRef] = Baz;
3445       // [[p]]
3446     }
3447   )";
3448   runDataflow(
3449       Code,
3450       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3451          ASTContext &ASTCtx) {
3452         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3453         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3454 
3455         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3456         ASSERT_THAT(FooRefDecl, NotNull());
3457 
3458         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3459         ASSERT_THAT(BarRefDecl, NotNull());
3460 
3461         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3462         ASSERT_THAT(QuxDecl, NotNull());
3463 
3464         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3465         ASSERT_THAT(BoundFooRefDecl, NotNull());
3466 
3467         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3468         ASSERT_THAT(BoundBarRefDecl, NotNull());
3469 
3470         const StorageLocation *FooRefLoc =
3471             Env.getStorageLocation(*FooRefDecl, SkipPast::Reference);
3472         ASSERT_THAT(FooRefLoc, NotNull());
3473 
3474         const StorageLocation *BarRefLoc =
3475             Env.getStorageLocation(*BarRefDecl, SkipPast::Reference);
3476         ASSERT_THAT(BarRefLoc, NotNull());
3477 
3478         const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None);
3479         ASSERT_THAT(QuxVal, NotNull());
3480 
3481         const StorageLocation *BoundFooRefLoc =
3482             Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference);
3483         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3484 
3485         const StorageLocation *BoundBarRefLoc =
3486             Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference);
3487         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3488 
3489         EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal);
3490       });
3491 }
3492 
3493 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
3494   std::string Code = R"(
3495     struct A {
3496       int &Foo;
3497       int &Bar;
3498     };
3499 
3500     void target(A Baz) {
3501       int Qux;
3502       Baz.Foo = Qux;
3503       auto &FooRef = Baz.Foo;
3504       auto &BarRef = Baz.Bar;
3505       auto &[BoundFooRef, BoundBarRef] = Baz;
3506       // [[p]]
3507     }
3508   )";
3509   runDataflow(
3510       Code,
3511       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3512          ASTContext &ASTCtx) {
3513         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3514         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3515 
3516         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3517         ASSERT_THAT(FooRefDecl, NotNull());
3518 
3519         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3520         ASSERT_THAT(BarRefDecl, NotNull());
3521 
3522         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3523         ASSERT_THAT(QuxDecl, NotNull());
3524 
3525         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3526         ASSERT_THAT(BoundFooRefDecl, NotNull());
3527 
3528         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3529         ASSERT_THAT(BoundBarRefDecl, NotNull());
3530 
3531         const StorageLocation *FooRefLoc =
3532             Env.getStorageLocation(*FooRefDecl, SkipPast::Reference);
3533         ASSERT_THAT(FooRefLoc, NotNull());
3534 
3535         const StorageLocation *BarRefLoc =
3536             Env.getStorageLocation(*BarRefDecl, SkipPast::Reference);
3537         ASSERT_THAT(BarRefLoc, NotNull());
3538 
3539         const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None);
3540         ASSERT_THAT(QuxVal, NotNull());
3541 
3542         const StorageLocation *BoundFooRefLoc =
3543             Env.getStorageLocation(*BoundFooRefDecl, SkipPast::Reference);
3544         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3545 
3546         const StorageLocation *BoundBarRefLoc =
3547             Env.getStorageLocation(*BoundBarRefDecl, SkipPast::Reference);
3548         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3549 
3550         EXPECT_EQ(Env.getValue(*BoundFooRefDecl, SkipPast::Reference), QuxVal);
3551       });
3552 }
3553 
3554 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
3555   std::string Code = R"(
3556     struct A {
3557       int Foo;
3558       int Bar;
3559     };
3560 
3561     void target() {
3562       int Qux;
3563       A Baz;
3564       Baz.Foo = Qux;
3565       auto &FooRef = Baz.Foo;
3566       auto &BarRef = Baz.Bar;
3567       auto [BoundFoo, BoundBar] = Baz;
3568       // [[p]]
3569     }
3570   )";
3571   runDataflow(
3572       Code,
3573       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3574          ASTContext &ASTCtx) {
3575         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3576         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3577 
3578         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3579         ASSERT_THAT(FooRefDecl, NotNull());
3580 
3581         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3582         ASSERT_THAT(BarRefDecl, NotNull());
3583 
3584         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
3585         ASSERT_THAT(BoundFooDecl, NotNull());
3586 
3587         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
3588         ASSERT_THAT(BoundBarDecl, NotNull());
3589 
3590         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3591         ASSERT_THAT(QuxDecl, NotNull());
3592 
3593         const StorageLocation *FooRefLoc =
3594             Env.getStorageLocation(*FooRefDecl, SkipPast::Reference);
3595         ASSERT_THAT(FooRefLoc, NotNull());
3596 
3597         const StorageLocation *BarRefLoc =
3598             Env.getStorageLocation(*BarRefDecl, SkipPast::Reference);
3599         ASSERT_THAT(BarRefLoc, NotNull());
3600 
3601         const Value *QuxVal = Env.getValue(*QuxDecl, SkipPast::None);
3602         ASSERT_THAT(QuxVal, NotNull());
3603 
3604         const StorageLocation *BoundFooLoc =
3605             Env.getStorageLocation(*BoundFooDecl, SkipPast::Reference);
3606         EXPECT_NE(BoundFooLoc, FooRefLoc);
3607 
3608         const StorageLocation *BoundBarLoc =
3609             Env.getStorageLocation(*BoundBarDecl, SkipPast::Reference);
3610         EXPECT_NE(BoundBarLoc, BarRefLoc);
3611 
3612         EXPECT_EQ(Env.getValue(*BoundFooDecl, SkipPast::Reference), QuxVal);
3613       });
3614 }
3615 
3616 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
3617   std::string Code = R"(
3618     namespace std {
3619     using size_t = int;
3620     template <class> struct tuple_size;
3621     template <std::size_t, class> struct tuple_element;
3622     template <class...> class tuple;
3623 
3624     namespace {
3625     template <class T, T v>
3626     struct size_helper { static const T value = v; };
3627     } // namespace
3628 
3629     template <class... T>
3630     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
3631 
3632     template <std::size_t I, class... T>
3633     struct tuple_element<I, tuple<T...>> {
3634       using type =  __type_pack_element<I, T...>;
3635     };
3636 
3637     template <class...> class tuple {};
3638 
3639     template <std::size_t I, class... T>
3640     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
3641     } // namespace std
3642 
3643     std::tuple<bool, int> makeTuple();
3644 
3645     void target(bool B) {
3646       auto [BoundFoo, BoundBar] = makeTuple();
3647       bool Baz;
3648       // Include if-then-else to test interaction of `BindingDecl` with join.
3649       if (B) {
3650         Baz = BoundFoo;
3651         (void)BoundBar;
3652         // [[p1]]
3653       } else {
3654         Baz = BoundFoo;
3655       }
3656       (void)0;
3657       // [[p2]]
3658     }
3659   )";
3660   runDataflow(
3661       Code,
3662       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3663          ASTContext &ASTCtx) {
3664         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
3665         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
3666 
3667         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
3668         ASSERT_THAT(BoundFooDecl, NotNull());
3669 
3670         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
3671         ASSERT_THAT(BoundBarDecl, NotNull());
3672 
3673         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3674         ASSERT_THAT(BazDecl, NotNull());
3675 
3676         const Value *BoundFooValue =
3677             Env1.getValue(*BoundFooDecl, SkipPast::Reference);
3678         ASSERT_THAT(BoundFooValue, NotNull());
3679         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
3680 
3681         const Value *BoundBarValue =
3682             Env1.getValue(*BoundBarDecl, SkipPast::Reference);
3683         ASSERT_THAT(BoundBarValue, NotNull());
3684         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
3685 
3686         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
3687         EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), BoundFooValue);
3688 
3689         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
3690 
3691         // Test that `BoundFooDecl` retains the value we expect, after the join.
3692         BoundFooValue = Env2.getValue(*BoundFooDecl, SkipPast::Reference);
3693         EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BoundFooValue);
3694       });
3695 }
3696 
3697 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
3698   std::string Code = R"(
3699     namespace std {
3700     using size_t = int;
3701     template <class> struct tuple_size;
3702     template <std::size_t, class> struct tuple_element;
3703     template <class...> class tuple;
3704 
3705     namespace {
3706     template <class T, T v>
3707     struct size_helper { static const T value = v; };
3708     } // namespace
3709 
3710     template <class... T>
3711     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
3712 
3713     template <std::size_t I, class... T>
3714     struct tuple_element<I, tuple<T...>> {
3715       using type =  __type_pack_element<I, T...>;
3716     };
3717 
3718     template <class...> class tuple {};
3719 
3720     template <std::size_t I, class... T>
3721     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
3722     } // namespace std
3723 
3724     std::tuple<bool, int> &getTuple();
3725 
3726     void target(bool B) {
3727       auto &[BoundFoo, BoundBar] = getTuple();
3728       bool Baz;
3729       // Include if-then-else to test interaction of `BindingDecl` with join.
3730       if (B) {
3731         Baz = BoundFoo;
3732         (void)BoundBar;
3733         // [[p1]]
3734       } else {
3735         Baz = BoundFoo;
3736       }
3737       (void)0;
3738       // [[p2]]
3739     }
3740   )";
3741   runDataflow(
3742       Code,
3743       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3744          ASTContext &ASTCtx) {
3745         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
3746         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
3747 
3748         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
3749         ASSERT_THAT(BoundFooDecl, NotNull());
3750 
3751         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
3752         ASSERT_THAT(BoundBarDecl, NotNull());
3753 
3754         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3755         ASSERT_THAT(BazDecl, NotNull());
3756 
3757         const Value *BoundFooValue =
3758             Env1.getValue(*BoundFooDecl, SkipPast::Reference);
3759         ASSERT_THAT(BoundFooValue, NotNull());
3760         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
3761 
3762         const Value *BoundBarValue =
3763             Env1.getValue(*BoundBarDecl, SkipPast::Reference);
3764         ASSERT_THAT(BoundBarValue, NotNull());
3765         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
3766 
3767         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
3768         // works as expected. We don't test aliasing properties of the
3769         // reference, because we don't model `std::get` and so have no way to
3770         // equate separate references into the tuple.
3771         EXPECT_EQ(Env1.getValue(*BazDecl, SkipPast::Reference), BoundFooValue);
3772 
3773         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
3774 
3775         // Test that `BoundFooDecl` retains the value we expect, after the join.
3776         BoundFooValue = Env2.getValue(*BoundFooDecl, SkipPast::Reference);
3777         EXPECT_EQ(Env2.getValue(*BazDecl, SkipPast::Reference), BoundFooValue);
3778       });
3779 }
3780 // TODO: ref binding
3781 
3782 TEST(TransferTest, BinaryOperatorComma) {
3783   std::string Code = R"(
3784     void target(int Foo, int Bar) {
3785       int &Baz = (Foo, Bar);
3786       // [[p]]
3787     }
3788   )";
3789   runDataflow(
3790       Code,
3791       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3792          ASTContext &ASTCtx) {
3793         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3794         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3795 
3796         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3797         ASSERT_THAT(BarDecl, NotNull());
3798 
3799         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3800         ASSERT_THAT(BazDecl, NotNull());
3801 
3802         const StorageLocation *BarLoc =
3803             Env.getStorageLocation(*BarDecl, SkipPast::Reference);
3804         ASSERT_THAT(BarLoc, NotNull());
3805 
3806         const StorageLocation *BazLoc =
3807             Env.getStorageLocation(*BazDecl, SkipPast::Reference);
3808         EXPECT_EQ(BazLoc, BarLoc);
3809       });
3810 }
3811 
3812 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
3813   std::string Code = R"(
3814     void target(bool Foo) {
3815       if (Foo) {
3816         (void)0;
3817         // [[if_then]]
3818       } else {
3819         (void)0;
3820         // [[if_else]]
3821       }
3822     }
3823   )";
3824   runDataflow(
3825       Code,
3826       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3827          ASTContext &ASTCtx) {
3828         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
3829         const Environment &ThenEnv =
3830             getEnvironmentAtAnnotation(Results, "if_then");
3831         const Environment &ElseEnv =
3832             getEnvironmentAtAnnotation(Results, "if_else");
3833 
3834         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3835         ASSERT_THAT(FooDecl, NotNull());
3836 
3837         BoolValue &ThenFooVal =
3838             *cast<BoolValue>(ThenEnv.getValue(*FooDecl, SkipPast::None));
3839         EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal));
3840 
3841         BoolValue &ElseFooVal =
3842             *cast<BoolValue>(ElseEnv.getValue(*FooDecl, SkipPast::None));
3843         EXPECT_TRUE(ElseEnv.flowConditionImplies(ElseEnv.makeNot(ElseFooVal)));
3844       });
3845 }
3846 
3847 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
3848   std::string Code = R"(
3849     void target(bool Foo) {
3850       while (Foo) {
3851         (void)0;
3852         // [[loop_body]]
3853       }
3854       (void)0;
3855       // [[after_loop]]
3856     }
3857   )";
3858   runDataflow(
3859       Code,
3860       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3861          ASTContext &ASTCtx) {
3862         ASSERT_THAT(Results.keys(),
3863                     UnorderedElementsAre("loop_body", "after_loop"));
3864         const Environment &LoopBodyEnv =
3865             getEnvironmentAtAnnotation(Results, "loop_body");
3866         const Environment &AfterLoopEnv =
3867             getEnvironmentAtAnnotation(Results, "after_loop");
3868 
3869         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3870         ASSERT_THAT(FooDecl, NotNull());
3871 
3872         BoolValue &LoopBodyFooVal =
3873             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
3874         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
3875 
3876         BoolValue &AfterLoopFooVal =
3877             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
3878         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
3879             AfterLoopEnv.makeNot(AfterLoopFooVal)));
3880       });
3881 }
3882 
3883 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
3884   std::string Code = R"(
3885     void target(bool Foo) {
3886       bool Bar = true;
3887       do {
3888         (void)0;
3889         // [[loop_body]]
3890         Bar = false;
3891       } while (Foo);
3892       (void)0;
3893       // [[after_loop]]
3894     }
3895   )";
3896   runDataflow(
3897       Code,
3898       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3899          ASTContext &ASTCtx) {
3900         ASSERT_THAT(Results.keys(),
3901                     UnorderedElementsAre("loop_body", "after_loop"));
3902         const Environment &LoopBodyEnv =
3903             getEnvironmentAtAnnotation(Results, "loop_body");
3904         const Environment &AfterLoopEnv =
3905             getEnvironmentAtAnnotation(Results, "after_loop");
3906 
3907         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3908         ASSERT_THAT(FooDecl, NotNull());
3909 
3910         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3911         ASSERT_THAT(BarDecl, NotNull());
3912 
3913         BoolValue &LoopBodyFooVal =
3914             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
3915         BoolValue &LoopBodyBarVal =
3916             *cast<BoolValue>(LoopBodyEnv.getValue(*BarDecl, SkipPast::None));
3917         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(
3918             LoopBodyEnv.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
3919 
3920         BoolValue &AfterLoopFooVal =
3921             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
3922         BoolValue &AfterLoopBarVal =
3923             *cast<BoolValue>(AfterLoopEnv.getValue(*BarDecl, SkipPast::None));
3924         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
3925             AfterLoopEnv.makeNot(AfterLoopFooVal)));
3926         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
3927             AfterLoopEnv.makeNot(AfterLoopBarVal)));
3928       });
3929 }
3930 
3931 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
3932   std::string Code = R"(
3933     void target(bool Foo) {
3934       for (; Foo;) {
3935         (void)0;
3936         // [[loop_body]]
3937       }
3938       (void)0;
3939       // [[after_loop]]
3940     }
3941   )";
3942   runDataflow(
3943       Code,
3944       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3945          ASTContext &ASTCtx) {
3946         ASSERT_THAT(Results.keys(),
3947                     UnorderedElementsAre("loop_body", "after_loop"));
3948         const Environment &LoopBodyEnv =
3949             getEnvironmentAtAnnotation(Results, "loop_body");
3950         const Environment &AfterLoopEnv =
3951             getEnvironmentAtAnnotation(Results, "after_loop");
3952 
3953         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3954         ASSERT_THAT(FooDecl, NotNull());
3955 
3956         BoolValue &LoopBodyFooVal =
3957             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
3958         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
3959 
3960         BoolValue &AfterLoopFooVal =
3961             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
3962         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
3963             AfterLoopEnv.makeNot(AfterLoopFooVal)));
3964       });
3965 }
3966 
3967 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
3968   std::string Code = R"(
3969     void target(bool Foo) {
3970       for (;;) {
3971         (void)0;
3972         // [[loop_body]]
3973       }
3974     }
3975   )";
3976   runDataflow(
3977       Code,
3978       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3979          ASTContext &ASTCtx) {
3980         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
3981         const Environment &LoopBodyEnv =
3982             getEnvironmentAtAnnotation(Results, "loop_body");
3983 
3984         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3985         ASSERT_THAT(FooDecl, NotNull());
3986 
3987         BoolValue &LoopBodyFooVal =
3988             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
3989         EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
3990       });
3991 }
3992 
3993 TEST(TransferTest, ContextSensitiveOptionDisabled) {
3994   std::string Code = R"(
3995     bool GiveBool();
3996     void SetBool(bool &Var) { Var = true; }
3997 
3998     void target() {
3999       bool Foo = GiveBool();
4000       SetBool(Foo);
4001       // [[p]]
4002     }
4003   )";
4004   runDataflow(
4005       Code,
4006       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4007          ASTContext &ASTCtx) {
4008         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4009         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4010 
4011         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4012         ASSERT_THAT(FooDecl, NotNull());
4013 
4014         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4015         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4016         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4017       },
4018       {TransferOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
4019 }
4020 
4021 TEST(TransferTest, ContextSensitiveDepthZero) {
4022   std::string Code = R"(
4023     bool GiveBool();
4024     void SetBool(bool &Var) { Var = true; }
4025 
4026     void target() {
4027       bool Foo = GiveBool();
4028       SetBool(Foo);
4029       // [[p]]
4030     }
4031   )";
4032   runDataflow(
4033       Code,
4034       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4035          ASTContext &ASTCtx) {
4036         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4037         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4038 
4039         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4040         ASSERT_THAT(FooDecl, NotNull());
4041 
4042         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4043         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4044         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4045       },
4046       {TransferOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
4047 }
4048 
4049 TEST(TransferTest, ContextSensitiveSetTrue) {
4050   std::string Code = R"(
4051     bool GiveBool();
4052     void SetBool(bool &Var) { Var = true; }
4053 
4054     void target() {
4055       bool Foo = GiveBool();
4056       SetBool(Foo);
4057       // [[p]]
4058     }
4059   )";
4060   runDataflow(
4061       Code,
4062       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4063          ASTContext &ASTCtx) {
4064         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4065         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4066 
4067         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4068         ASSERT_THAT(FooDecl, NotNull());
4069 
4070         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4071         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4072       },
4073       {TransferOptions{ContextSensitiveOptions{}}});
4074 }
4075 
4076 TEST(TransferTest, ContextSensitiveSetFalse) {
4077   std::string Code = R"(
4078     bool GiveBool();
4079     void SetBool(bool &Var) { Var = false; }
4080 
4081     void target() {
4082       bool Foo = GiveBool();
4083       SetBool(Foo);
4084       // [[p]]
4085     }
4086   )";
4087   runDataflow(
4088       Code,
4089       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4090          ASTContext &ASTCtx) {
4091         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4092         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4093 
4094         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4095         ASSERT_THAT(FooDecl, NotNull());
4096 
4097         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4098         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4099       },
4100       {TransferOptions{ContextSensitiveOptions{}}});
4101 }
4102 
4103 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
4104   std::string Code = R"(
4105     bool GiveBool();
4106     void SetBool(bool &Var, bool Val) { Var = Val; }
4107 
4108     void target() {
4109       bool Foo = GiveBool();
4110       bool Bar = GiveBool();
4111       SetBool(Foo, true);
4112       SetBool(Bar, false);
4113       // [[p]]
4114     }
4115   )";
4116   runDataflow(
4117       Code,
4118       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4119          ASTContext &ASTCtx) {
4120         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4121         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4122 
4123         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4124         ASSERT_THAT(FooDecl, NotNull());
4125 
4126         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4127         ASSERT_THAT(BarDecl, NotNull());
4128 
4129         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4130         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4131         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4132 
4133         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
4134         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4135         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4136       },
4137       {TransferOptions{ContextSensitiveOptions{}}});
4138 }
4139 
4140 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
4141   std::string Code = R"(
4142     bool GiveBool();
4143     void SetBool1(bool &Var) { Var = true; }
4144     void SetBool2(bool &Var) { SetBool1(Var); }
4145 
4146     void target() {
4147       bool Foo = GiveBool();
4148       SetBool2(Foo);
4149       // [[p]]
4150     }
4151   )";
4152   runDataflow(
4153       Code,
4154       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4155          ASTContext &ASTCtx) {
4156         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4157         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4158 
4159         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4160         ASSERT_THAT(FooDecl, NotNull());
4161 
4162         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4163         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4164         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4165       },
4166       {TransferOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
4167 }
4168 
4169 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
4170   std::string Code = R"(
4171     bool GiveBool();
4172     void SetBool1(bool &Var) { Var = true; }
4173     void SetBool2(bool &Var) { SetBool1(Var); }
4174 
4175     void target() {
4176       bool Foo = GiveBool();
4177       SetBool2(Foo);
4178       // [[p]]
4179     }
4180   )";
4181   runDataflow(
4182       Code,
4183       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4184          ASTContext &ASTCtx) {
4185         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4186         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4187 
4188         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4189         ASSERT_THAT(FooDecl, NotNull());
4190 
4191         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4192         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4193       },
4194       {TransferOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4195 }
4196 
4197 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
4198   std::string Code = R"(
4199     bool GiveBool();
4200     void SetBool1(bool &Var) { Var = true; }
4201     void SetBool2(bool &Var) { SetBool1(Var); }
4202     void SetBool3(bool &Var) { SetBool2(Var); }
4203 
4204     void target() {
4205       bool Foo = GiveBool();
4206       SetBool3(Foo);
4207       // [[p]]
4208     }
4209   )";
4210   runDataflow(
4211       Code,
4212       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4213          ASTContext &ASTCtx) {
4214         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4215         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4216 
4217         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4218         ASSERT_THAT(FooDecl, NotNull());
4219 
4220         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4221         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4222         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4223       },
4224       {TransferOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4225 }
4226 
4227 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
4228   std::string Code = R"(
4229     bool GiveBool();
4230     void SetBool1(bool &Var) { Var = true; }
4231     void SetBool2(bool &Var) { SetBool1(Var); }
4232     void SetBool3(bool &Var) { SetBool2(Var); }
4233 
4234     void target() {
4235       bool Foo = GiveBool();
4236       SetBool3(Foo);
4237       // [[p]]
4238     }
4239   )";
4240   runDataflow(
4241       Code,
4242       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4243          ASTContext &ASTCtx) {
4244         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4245         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4246 
4247         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4248         ASSERT_THAT(FooDecl, NotNull());
4249 
4250         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4251         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4252       },
4253       {TransferOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
4254 }
4255 
4256 TEST(TransferTest, ContextSensitiveMutualRecursion) {
4257   std::string Code = R"(
4258     bool Pong(bool X, bool Y);
4259 
4260     bool Ping(bool X, bool Y) {
4261       if (X) {
4262         return Y;
4263       } else {
4264         return Pong(!X, Y);
4265       }
4266     }
4267 
4268     bool Pong(bool X, bool Y) {
4269       if (Y) {
4270         return X;
4271       } else {
4272         return Ping(X, !Y);
4273       }
4274     }
4275 
4276     void target() {
4277       bool Foo = Ping(false, false);
4278       // [[p]]
4279     }
4280   )";
4281   runDataflow(
4282       Code,
4283       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4284          ASTContext &ASTCtx) {
4285         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4286         // The analysis doesn't crash...
4287         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4288 
4289         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4290         ASSERT_THAT(FooDecl, NotNull());
4291 
4292         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4293         // ... but it also can't prove anything here.
4294         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4295         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4296       },
4297       {TransferOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
4298 }
4299 
4300 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
4301   std::string Code = R"(
4302     void SetBools(bool &Var1, bool &Var2) {
4303       Var1 = true;
4304       Var2 = false;
4305     }
4306 
4307     void target() {
4308       bool Foo = false;
4309       bool Bar = true;
4310       SetBools(Foo, Bar);
4311       // [[p]]
4312     }
4313   )";
4314   runDataflow(
4315       Code,
4316       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4317          ASTContext &ASTCtx) {
4318         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4319         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4320 
4321         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4322         ASSERT_THAT(FooDecl, NotNull());
4323 
4324         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4325         ASSERT_THAT(BarDecl, NotNull());
4326 
4327         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4328         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4329         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4330 
4331         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
4332         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4333         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4334       },
4335       {TransferOptions{ContextSensitiveOptions{}}});
4336 }
4337 
4338 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
4339   std::string Code = R"(
4340     void IfCond(bool Cond, bool &Then, bool &Else) {
4341       if (Cond) {
4342         Then = true;
4343       } else {
4344         Else = true;
4345       }
4346     }
4347 
4348     void target() {
4349       bool Foo = false;
4350       bool Bar = false;
4351       bool Baz = false;
4352       IfCond(Foo, Bar, Baz);
4353       // [[p]]
4354     }
4355   )";
4356   runDataflow(
4357       Code,
4358       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4359          ASTContext &ASTCtx) {
4360         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4361         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4362 
4363         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4364         ASSERT_THAT(BarDecl, NotNull());
4365 
4366         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4367         ASSERT_THAT(BazDecl, NotNull());
4368 
4369         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
4370         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4371         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4372 
4373         auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl, SkipPast::None));
4374         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
4375         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(BazVal)));
4376       },
4377       {TransferOptions{ContextSensitiveOptions{}}});
4378 }
4379 
4380 TEST(TransferTest, ContextSensitiveReturnVoid) {
4381   std::string Code = R"(
4382     void Noop() { return; }
4383 
4384     void target() {
4385       Noop();
4386       // [[p]]
4387     }
4388   )";
4389   runDataflow(
4390       Code,
4391       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4392          ASTContext &ASTCtx) {
4393         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4394         // This just tests that the analysis doesn't crash.
4395       },
4396       {TransferOptions{ContextSensitiveOptions{}}});
4397 }
4398 
4399 TEST(TransferTest, ContextSensitiveReturnTrue) {
4400   std::string Code = R"(
4401     bool GiveBool() { return true; }
4402 
4403     void target() {
4404       bool Foo = GiveBool();
4405       // [[p]]
4406     }
4407   )";
4408   runDataflow(
4409       Code,
4410       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4411          ASTContext &ASTCtx) {
4412         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4413         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4414 
4415         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4416         ASSERT_THAT(FooDecl, NotNull());
4417 
4418         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4419         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4420       },
4421       {TransferOptions{ContextSensitiveOptions{}}});
4422 }
4423 
4424 TEST(TransferTest, ContextSensitiveReturnFalse) {
4425   std::string Code = R"(
4426     bool GiveBool() { return false; }
4427 
4428     void target() {
4429       bool Foo = GiveBool();
4430       // [[p]]
4431     }
4432   )";
4433   runDataflow(
4434       Code,
4435       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4436          ASTContext &ASTCtx) {
4437         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4438         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4439 
4440         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4441         ASSERT_THAT(FooDecl, NotNull());
4442 
4443         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4444         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4445       },
4446       {TransferOptions{ContextSensitiveOptions{}}});
4447 }
4448 
4449 TEST(TransferTest, ContextSensitiveReturnArg) {
4450   std::string Code = R"(
4451     bool GiveBool();
4452     bool GiveBack(bool Arg) { return Arg; }
4453 
4454     void target() {
4455       bool Foo = GiveBool();
4456       bool Bar = GiveBack(Foo);
4457       bool Baz = Foo == Bar;
4458       // [[p]]
4459     }
4460   )";
4461   runDataflow(
4462       Code,
4463       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4464          ASTContext &ASTCtx) {
4465         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4466         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4467 
4468         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4469         ASSERT_THAT(BazDecl, NotNull());
4470 
4471         auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl, SkipPast::None));
4472         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
4473       },
4474       {TransferOptions{ContextSensitiveOptions{}}});
4475 }
4476 
4477 TEST(TransferTest, ContextSensitiveReturnInt) {
4478   std::string Code = R"(
4479     int identity(int x) { return x; }
4480 
4481     void target() {
4482       int y = identity(42);
4483       // [[p]]
4484     }
4485   )";
4486   runDataflow(
4487       Code,
4488       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4489          ASTContext &ASTCtx) {
4490         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4491         // This just tests that the analysis doesn't crash.
4492       },
4493       {TransferOptions{ContextSensitiveOptions{}}});
4494 }
4495 
4496 TEST(TransferTest, ContextSensitiveMethodLiteral) {
4497   std::string Code = R"(
4498     class MyClass {
4499     public:
4500       bool giveBool() { return true; }
4501     };
4502 
4503     void target() {
4504       MyClass MyObj;
4505       bool Foo = MyObj.giveBool();
4506       // [[p]]
4507     }
4508   )";
4509   runDataflow(
4510       Code,
4511       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4512          ASTContext &ASTCtx) {
4513         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4514         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4515 
4516         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4517         ASSERT_THAT(FooDecl, NotNull());
4518 
4519         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4520         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4521       },
4522       {TransferOptions{ContextSensitiveOptions{}}});
4523 }
4524 
4525 TEST(TransferTest, ContextSensitiveMethodGetter) {
4526   std::string Code = R"(
4527     class MyClass {
4528     public:
4529       bool getField() { return Field; }
4530 
4531       bool Field;
4532     };
4533 
4534     void target() {
4535       MyClass MyObj;
4536       MyObj.Field = true;
4537       bool Foo = MyObj.getField();
4538       // [[p]]
4539     }
4540   )";
4541   runDataflow(
4542       Code,
4543       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4544          ASTContext &ASTCtx) {
4545         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4546         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4547 
4548         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4549         ASSERT_THAT(FooDecl, NotNull());
4550 
4551         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4552         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4553       },
4554       {TransferOptions{ContextSensitiveOptions{}}});
4555 }
4556 
4557 TEST(TransferTest, ContextSensitiveMethodSetter) {
4558   std::string Code = R"(
4559     class MyClass {
4560     public:
4561       void setField(bool Val) { Field = Val; }
4562 
4563       bool Field;
4564     };
4565 
4566     void target() {
4567       MyClass MyObj;
4568       MyObj.setField(true);
4569       bool Foo = MyObj.Field;
4570       // [[p]]
4571     }
4572   )";
4573   runDataflow(
4574       Code,
4575       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4576          ASTContext &ASTCtx) {
4577         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4578         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4579 
4580         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4581         ASSERT_THAT(FooDecl, NotNull());
4582 
4583         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4584         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4585       },
4586       {TransferOptions{ContextSensitiveOptions{}}});
4587 }
4588 
4589 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
4590   std::string Code = R"(
4591     class MyClass {
4592     public:
4593       bool getField() { return Field; }
4594       void setField(bool Val) { Field = Val; }
4595 
4596     private:
4597       bool Field;
4598     };
4599 
4600     void target() {
4601       MyClass MyObj;
4602       MyObj.setField(true);
4603       bool Foo = MyObj.getField();
4604       // [[p]]
4605     }
4606   )";
4607   runDataflow(
4608       Code,
4609       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4610          ASTContext &ASTCtx) {
4611         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4612         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4613 
4614         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4615         ASSERT_THAT(FooDecl, NotNull());
4616 
4617         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4618         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4619       },
4620       {TransferOptions{ContextSensitiveOptions{}}});
4621 }
4622 
4623 
4624 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
4625   std::string Code = R"(
4626     class MyClass {
4627     public:
4628       void Inner() { MyField = true; }
4629       void Outer() { Inner(); }
4630 
4631       bool MyField;
4632     };
4633 
4634     void target() {
4635       MyClass MyObj;
4636       MyObj.Outer();
4637       bool Foo = MyObj.MyField;
4638       // [[p]]
4639     }
4640   )";
4641   runDataflow(
4642       Code,
4643       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4644          ASTContext &ASTCtx) {
4645         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));;
4646         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4647 
4648         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4649         ASSERT_THAT(FooDecl, NotNull());
4650 
4651         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4652         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4653       },
4654       {TransferOptions{ContextSensitiveOptions{}}});
4655 }
4656 
4657 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
4658   std::string Code = R"(
4659     class MyClass {
4660     public:
4661       bool Inner() { return MyField; }
4662       bool Outer() { return Inner(); }
4663 
4664       bool MyField;
4665     };
4666 
4667     void target() {
4668       MyClass MyObj;
4669       MyObj.MyField = true;
4670       bool Foo = MyObj.Outer();
4671       // [[p]]
4672     }
4673   )";
4674   runDataflow(
4675       Code,
4676       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4677          ASTContext &ASTCtx) {
4678         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));;
4679         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4680 
4681         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4682         ASSERT_THAT(FooDecl, NotNull());
4683 
4684         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4685         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4686       },
4687       {TransferOptions{ContextSensitiveOptions{}}});
4688 }
4689 
4690 TEST(TransferTest, ContextSensitiveConstructorBody) {
4691   std::string Code = R"(
4692     class MyClass {
4693     public:
4694       MyClass() { MyField = true; }
4695 
4696       bool MyField;
4697     };
4698 
4699     void target() {
4700       MyClass MyObj;
4701       bool Foo = MyObj.MyField;
4702       // [[p]]
4703     }
4704   )";
4705   runDataflow(
4706       Code,
4707       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4708          ASTContext &ASTCtx) {
4709         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4710         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4711 
4712         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4713         ASSERT_THAT(FooDecl, NotNull());
4714 
4715         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4716         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4717       },
4718       {TransferOptions{ContextSensitiveOptions{}}});
4719 }
4720 
4721 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
4722   std::string Code = R"(
4723     class MyClass {
4724     public:
4725       MyClass() : MyField(true) {}
4726 
4727       bool MyField;
4728     };
4729 
4730     void target() {
4731       MyClass MyObj;
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, ContextSensitiveConstructorDefault) {
4753   std::string Code = R"(
4754     class MyClass {
4755     public:
4756       MyClass() = default;
4757 
4758       bool MyField = true;
4759     };
4760 
4761     void target() {
4762       MyClass MyObj;
4763       bool Foo = MyObj.MyField;
4764       // [[p]]
4765     }
4766   )";
4767   runDataflow(
4768       Code,
4769       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4770          ASTContext &ASTCtx) {
4771         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4772         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4773 
4774         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4775         ASSERT_THAT(FooDecl, NotNull());
4776 
4777         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4778         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4779       },
4780       {TransferOptions{ContextSensitiveOptions{}}});
4781 }
4782 
4783 } // namespace
4784