xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision 84dd12b29064095cdef3949e8fd5c91b93f36004)
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, BinaryOperatorComma) {
3617   std::string Code = R"(
3618     void target(int Foo, int Bar) {
3619       int &Baz = (Foo, Bar);
3620       // [[p]]
3621     }
3622   )";
3623   runDataflow(
3624       Code,
3625       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3626          ASTContext &ASTCtx) {
3627         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3628         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3629 
3630         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3631         ASSERT_THAT(BarDecl, NotNull());
3632 
3633         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3634         ASSERT_THAT(BazDecl, NotNull());
3635 
3636         const StorageLocation *BarLoc =
3637             Env.getStorageLocation(*BarDecl, SkipPast::Reference);
3638         ASSERT_THAT(BarLoc, NotNull());
3639 
3640         const StorageLocation *BazLoc =
3641             Env.getStorageLocation(*BazDecl, SkipPast::Reference);
3642         EXPECT_EQ(BazLoc, BarLoc);
3643       });
3644 }
3645 
3646 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
3647   std::string Code = R"(
3648     void target(bool Foo) {
3649       if (Foo) {
3650         (void)0;
3651         // [[if_then]]
3652       } else {
3653         (void)0;
3654         // [[if_else]]
3655       }
3656     }
3657   )";
3658   runDataflow(
3659       Code,
3660       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3661          ASTContext &ASTCtx) {
3662         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
3663         const Environment &ThenEnv =
3664             getEnvironmentAtAnnotation(Results, "if_then");
3665         const Environment &ElseEnv =
3666             getEnvironmentAtAnnotation(Results, "if_else");
3667 
3668         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3669         ASSERT_THAT(FooDecl, NotNull());
3670 
3671         BoolValue &ThenFooVal =
3672             *cast<BoolValue>(ThenEnv.getValue(*FooDecl, SkipPast::None));
3673         EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal));
3674 
3675         BoolValue &ElseFooVal =
3676             *cast<BoolValue>(ElseEnv.getValue(*FooDecl, SkipPast::None));
3677         EXPECT_TRUE(ElseEnv.flowConditionImplies(ElseEnv.makeNot(ElseFooVal)));
3678       });
3679 }
3680 
3681 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
3682   std::string Code = R"(
3683     void target(bool Foo) {
3684       while (Foo) {
3685         (void)0;
3686         // [[loop_body]]
3687       }
3688       (void)0;
3689       // [[after_loop]]
3690     }
3691   )";
3692   runDataflow(
3693       Code,
3694       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3695          ASTContext &ASTCtx) {
3696         ASSERT_THAT(Results.keys(),
3697                     UnorderedElementsAre("loop_body", "after_loop"));
3698         const Environment &LoopBodyEnv =
3699             getEnvironmentAtAnnotation(Results, "loop_body");
3700         const Environment &AfterLoopEnv =
3701             getEnvironmentAtAnnotation(Results, "after_loop");
3702 
3703         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3704         ASSERT_THAT(FooDecl, NotNull());
3705 
3706         BoolValue &LoopBodyFooVal =
3707             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
3708         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
3709 
3710         BoolValue &AfterLoopFooVal =
3711             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
3712         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
3713             AfterLoopEnv.makeNot(AfterLoopFooVal)));
3714       });
3715 }
3716 
3717 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
3718   std::string Code = R"(
3719     void target(bool Foo) {
3720       bool Bar = true;
3721       do {
3722         (void)0;
3723         // [[loop_body]]
3724         Bar = false;
3725       } while (Foo);
3726       (void)0;
3727       // [[after_loop]]
3728     }
3729   )";
3730   runDataflow(
3731       Code,
3732       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3733          ASTContext &ASTCtx) {
3734         ASSERT_THAT(Results.keys(),
3735                     UnorderedElementsAre("loop_body", "after_loop"));
3736         const Environment &LoopBodyEnv =
3737             getEnvironmentAtAnnotation(Results, "loop_body");
3738         const Environment &AfterLoopEnv =
3739             getEnvironmentAtAnnotation(Results, "after_loop");
3740 
3741         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3742         ASSERT_THAT(FooDecl, NotNull());
3743 
3744         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3745         ASSERT_THAT(BarDecl, NotNull());
3746 
3747         BoolValue &LoopBodyFooVal =
3748             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
3749         BoolValue &LoopBodyBarVal =
3750             *cast<BoolValue>(LoopBodyEnv.getValue(*BarDecl, SkipPast::None));
3751         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(
3752             LoopBodyEnv.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
3753 
3754         BoolValue &AfterLoopFooVal =
3755             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
3756         BoolValue &AfterLoopBarVal =
3757             *cast<BoolValue>(AfterLoopEnv.getValue(*BarDecl, SkipPast::None));
3758         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
3759             AfterLoopEnv.makeNot(AfterLoopFooVal)));
3760         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
3761             AfterLoopEnv.makeNot(AfterLoopBarVal)));
3762       });
3763 }
3764 
3765 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
3766   std::string Code = R"(
3767     void target(bool Foo) {
3768       for (; Foo;) {
3769         (void)0;
3770         // [[loop_body]]
3771       }
3772       (void)0;
3773       // [[after_loop]]
3774     }
3775   )";
3776   runDataflow(
3777       Code,
3778       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3779          ASTContext &ASTCtx) {
3780         ASSERT_THAT(Results.keys(),
3781                     UnorderedElementsAre("loop_body", "after_loop"));
3782         const Environment &LoopBodyEnv =
3783             getEnvironmentAtAnnotation(Results, "loop_body");
3784         const Environment &AfterLoopEnv =
3785             getEnvironmentAtAnnotation(Results, "after_loop");
3786 
3787         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3788         ASSERT_THAT(FooDecl, NotNull());
3789 
3790         BoolValue &LoopBodyFooVal =
3791             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
3792         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
3793 
3794         BoolValue &AfterLoopFooVal =
3795             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl, SkipPast::None));
3796         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
3797             AfterLoopEnv.makeNot(AfterLoopFooVal)));
3798       });
3799 }
3800 
3801 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
3802   std::string Code = R"(
3803     void target(bool Foo) {
3804       for (;;) {
3805         (void)0;
3806         // [[loop_body]]
3807       }
3808     }
3809   )";
3810   runDataflow(
3811       Code,
3812       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3813          ASTContext &ASTCtx) {
3814         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
3815         const Environment &LoopBodyEnv =
3816             getEnvironmentAtAnnotation(Results, "loop_body");
3817 
3818         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3819         ASSERT_THAT(FooDecl, NotNull());
3820 
3821         BoolValue &LoopBodyFooVal =
3822             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl, SkipPast::None));
3823         EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
3824       });
3825 }
3826 
3827 TEST(TransferTest, ContextSensitiveOptionDisabled) {
3828   std::string Code = R"(
3829     bool GiveBool();
3830     void SetBool(bool &Var) { Var = true; }
3831 
3832     void target() {
3833       bool Foo = GiveBool();
3834       SetBool(Foo);
3835       // [[p]]
3836     }
3837   )";
3838   runDataflow(
3839       Code,
3840       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3841          ASTContext &ASTCtx) {
3842         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3843         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3844 
3845         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3846         ASSERT_THAT(FooDecl, NotNull());
3847 
3848         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
3849         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
3850         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
3851       },
3852       {TransferOptions{/*.ContextSensitiveOpts=*/llvm::None}});
3853 }
3854 
3855 TEST(TransferTest, ContextSensitiveDepthZero) {
3856   std::string Code = R"(
3857     bool GiveBool();
3858     void SetBool(bool &Var) { Var = true; }
3859 
3860     void target() {
3861       bool Foo = GiveBool();
3862       SetBool(Foo);
3863       // [[p]]
3864     }
3865   )";
3866   runDataflow(
3867       Code,
3868       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3869          ASTContext &ASTCtx) {
3870         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3871         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3872 
3873         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3874         ASSERT_THAT(FooDecl, NotNull());
3875 
3876         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
3877         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
3878         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
3879       },
3880       {TransferOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
3881 }
3882 
3883 TEST(TransferTest, ContextSensitiveSetTrue) {
3884   std::string Code = R"(
3885     bool GiveBool();
3886     void SetBool(bool &Var) { Var = true; }
3887 
3888     void target() {
3889       bool Foo = GiveBool();
3890       SetBool(Foo);
3891       // [[p]]
3892     }
3893   )";
3894   runDataflow(
3895       Code,
3896       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3897          ASTContext &ASTCtx) {
3898         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3899         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3900 
3901         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3902         ASSERT_THAT(FooDecl, NotNull());
3903 
3904         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
3905         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
3906       },
3907       {TransferOptions{ContextSensitiveOptions{}}});
3908 }
3909 
3910 TEST(TransferTest, ContextSensitiveSetFalse) {
3911   std::string Code = R"(
3912     bool GiveBool();
3913     void SetBool(bool &Var) { Var = false; }
3914 
3915     void target() {
3916       bool Foo = GiveBool();
3917       SetBool(Foo);
3918       // [[p]]
3919     }
3920   )";
3921   runDataflow(
3922       Code,
3923       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3924          ASTContext &ASTCtx) {
3925         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3926         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3927 
3928         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3929         ASSERT_THAT(FooDecl, NotNull());
3930 
3931         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
3932         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
3933       },
3934       {TransferOptions{ContextSensitiveOptions{}}});
3935 }
3936 
3937 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
3938   std::string Code = R"(
3939     bool GiveBool();
3940     void SetBool(bool &Var, bool Val) { Var = Val; }
3941 
3942     void target() {
3943       bool Foo = GiveBool();
3944       bool Bar = GiveBool();
3945       SetBool(Foo, true);
3946       SetBool(Bar, false);
3947       // [[p]]
3948     }
3949   )";
3950   runDataflow(
3951       Code,
3952       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3953          ASTContext &ASTCtx) {
3954         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3955         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3956 
3957         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3958         ASSERT_THAT(FooDecl, NotNull());
3959 
3960         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3961         ASSERT_THAT(BarDecl, NotNull());
3962 
3963         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
3964         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
3965         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
3966 
3967         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
3968         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
3969         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3970       },
3971       {TransferOptions{ContextSensitiveOptions{}}});
3972 }
3973 
3974 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
3975   std::string Code = R"(
3976     bool GiveBool();
3977     void SetBool1(bool &Var) { Var = true; }
3978     void SetBool2(bool &Var) { SetBool1(Var); }
3979 
3980     void target() {
3981       bool Foo = GiveBool();
3982       SetBool2(Foo);
3983       // [[p]]
3984     }
3985   )";
3986   runDataflow(
3987       Code,
3988       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3989          ASTContext &ASTCtx) {
3990         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3991         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3992 
3993         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3994         ASSERT_THAT(FooDecl, NotNull());
3995 
3996         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
3997         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
3998         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
3999       },
4000       {TransferOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
4001 }
4002 
4003 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
4004   std::string Code = R"(
4005     bool GiveBool();
4006     void SetBool1(bool &Var) { Var = true; }
4007     void SetBool2(bool &Var) { SetBool1(Var); }
4008 
4009     void target() {
4010       bool Foo = GiveBool();
4011       SetBool2(Foo);
4012       // [[p]]
4013     }
4014   )";
4015   runDataflow(
4016       Code,
4017       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4018          ASTContext &ASTCtx) {
4019         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4020         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4021 
4022         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4023         ASSERT_THAT(FooDecl, NotNull());
4024 
4025         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4026         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4027       },
4028       {TransferOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4029 }
4030 
4031 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
4032   std::string Code = R"(
4033     bool GiveBool();
4034     void SetBool1(bool &Var) { Var = true; }
4035     void SetBool2(bool &Var) { SetBool1(Var); }
4036     void SetBool3(bool &Var) { SetBool2(Var); }
4037 
4038     void target() {
4039       bool Foo = GiveBool();
4040       SetBool3(Foo);
4041       // [[p]]
4042     }
4043   )";
4044   runDataflow(
4045       Code,
4046       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4047          ASTContext &ASTCtx) {
4048         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4049         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4050 
4051         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4052         ASSERT_THAT(FooDecl, NotNull());
4053 
4054         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4055         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4056         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4057       },
4058       {TransferOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4059 }
4060 
4061 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
4062   std::string Code = R"(
4063     bool GiveBool();
4064     void SetBool1(bool &Var) { Var = true; }
4065     void SetBool2(bool &Var) { SetBool1(Var); }
4066     void SetBool3(bool &Var) { SetBool2(Var); }
4067 
4068     void target() {
4069       bool Foo = GiveBool();
4070       SetBool3(Foo);
4071       // [[p]]
4072     }
4073   )";
4074   runDataflow(
4075       Code,
4076       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4077          ASTContext &ASTCtx) {
4078         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4079         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4080 
4081         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4082         ASSERT_THAT(FooDecl, NotNull());
4083 
4084         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4085         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4086       },
4087       {TransferOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
4088 }
4089 
4090 TEST(TransferTest, ContextSensitiveMutualRecursion) {
4091   std::string Code = R"(
4092     bool Pong(bool X, bool Y);
4093 
4094     bool Ping(bool X, bool Y) {
4095       if (X) {
4096         return Y;
4097       } else {
4098         return Pong(!X, Y);
4099       }
4100     }
4101 
4102     bool Pong(bool X, bool Y) {
4103       if (Y) {
4104         return X;
4105       } else {
4106         return Ping(X, !Y);
4107       }
4108     }
4109 
4110     void target() {
4111       bool Foo = Ping(false, false);
4112       // [[p]]
4113     }
4114   )";
4115   runDataflow(
4116       Code,
4117       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4118          ASTContext &ASTCtx) {
4119         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4120         // The analysis doesn't crash...
4121         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4122 
4123         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4124         ASSERT_THAT(FooDecl, NotNull());
4125 
4126         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4127         // ... but it also can't prove anything here.
4128         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4129         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4130       },
4131       {TransferOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
4132 }
4133 
4134 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
4135   std::string Code = R"(
4136     void SetBools(bool &Var1, bool &Var2) {
4137       Var1 = true;
4138       Var2 = false;
4139     }
4140 
4141     void target() {
4142       bool Foo = false;
4143       bool Bar = true;
4144       SetBools(Foo, Bar);
4145       // [[p]]
4146     }
4147   )";
4148   runDataflow(
4149       Code,
4150       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4151          ASTContext &ASTCtx) {
4152         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4153         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4154 
4155         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4156         ASSERT_THAT(FooDecl, NotNull());
4157 
4158         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4159         ASSERT_THAT(BarDecl, NotNull());
4160 
4161         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4162         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4163         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4164 
4165         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
4166         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4167         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4168       },
4169       {TransferOptions{ContextSensitiveOptions{}}});
4170 }
4171 
4172 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
4173   std::string Code = R"(
4174     void IfCond(bool Cond, bool &Then, bool &Else) {
4175       if (Cond) {
4176         Then = true;
4177       } else {
4178         Else = true;
4179       }
4180     }
4181 
4182     void target() {
4183       bool Foo = false;
4184       bool Bar = false;
4185       bool Baz = false;
4186       IfCond(Foo, Bar, Baz);
4187       // [[p]]
4188     }
4189   )";
4190   runDataflow(
4191       Code,
4192       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4193          ASTContext &ASTCtx) {
4194         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4195         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4196 
4197         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4198         ASSERT_THAT(BarDecl, NotNull());
4199 
4200         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4201         ASSERT_THAT(BazDecl, NotNull());
4202 
4203         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl, SkipPast::None));
4204         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4205         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4206 
4207         auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl, SkipPast::None));
4208         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
4209         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(BazVal)));
4210       },
4211       {TransferOptions{ContextSensitiveOptions{}}});
4212 }
4213 
4214 TEST(TransferTest, ContextSensitiveReturnVoid) {
4215   std::string Code = R"(
4216     void Noop() { return; }
4217 
4218     void target() {
4219       Noop();
4220       // [[p]]
4221     }
4222   )";
4223   runDataflow(
4224       Code,
4225       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4226          ASTContext &ASTCtx) {
4227         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4228         // This just tests that the analysis doesn't crash.
4229       },
4230       {TransferOptions{ContextSensitiveOptions{}}});
4231 }
4232 
4233 TEST(TransferTest, ContextSensitiveReturnTrue) {
4234   std::string Code = R"(
4235     bool GiveBool() { return true; }
4236 
4237     void target() {
4238       bool Foo = GiveBool();
4239       // [[p]]
4240     }
4241   )";
4242   runDataflow(
4243       Code,
4244       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4245          ASTContext &ASTCtx) {
4246         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4247         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4248 
4249         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4250         ASSERT_THAT(FooDecl, NotNull());
4251 
4252         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4253         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4254       },
4255       {TransferOptions{ContextSensitiveOptions{}}});
4256 }
4257 
4258 TEST(TransferTest, ContextSensitiveReturnFalse) {
4259   std::string Code = R"(
4260     bool GiveBool() { return false; }
4261 
4262     void target() {
4263       bool Foo = GiveBool();
4264       // [[p]]
4265     }
4266   )";
4267   runDataflow(
4268       Code,
4269       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4270          ASTContext &ASTCtx) {
4271         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4272         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4273 
4274         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4275         ASSERT_THAT(FooDecl, NotNull());
4276 
4277         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4278         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4279       },
4280       {TransferOptions{ContextSensitiveOptions{}}});
4281 }
4282 
4283 TEST(TransferTest, ContextSensitiveReturnArg) {
4284   std::string Code = R"(
4285     bool GiveBool();
4286     bool GiveBack(bool Arg) { return Arg; }
4287 
4288     void target() {
4289       bool Foo = GiveBool();
4290       bool Bar = GiveBack(Foo);
4291       bool Baz = Foo == Bar;
4292       // [[p]]
4293     }
4294   )";
4295   runDataflow(
4296       Code,
4297       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4298          ASTContext &ASTCtx) {
4299         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4300         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4301 
4302         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4303         ASSERT_THAT(BazDecl, NotNull());
4304 
4305         auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl, SkipPast::None));
4306         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
4307       },
4308       {TransferOptions{ContextSensitiveOptions{}}});
4309 }
4310 
4311 TEST(TransferTest, ContextSensitiveReturnInt) {
4312   std::string Code = R"(
4313     int identity(int x) { return x; }
4314 
4315     void target() {
4316       int y = identity(42);
4317       // [[p]]
4318     }
4319   )";
4320   runDataflow(
4321       Code,
4322       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4323          ASTContext &ASTCtx) {
4324         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4325         // This just tests that the analysis doesn't crash.
4326       },
4327       {TransferOptions{ContextSensitiveOptions{}}});
4328 }
4329 
4330 TEST(TransferTest, ContextSensitiveMethodLiteral) {
4331   std::string Code = R"(
4332     class MyClass {
4333     public:
4334       bool giveBool() { return true; }
4335     };
4336 
4337     void target() {
4338       MyClass MyObj;
4339       bool Foo = MyObj.giveBool();
4340       // [[p]]
4341     }
4342   )";
4343   runDataflow(
4344       Code,
4345       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4346          ASTContext &ASTCtx) {
4347         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4348         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4349 
4350         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4351         ASSERT_THAT(FooDecl, NotNull());
4352 
4353         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4354         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4355       },
4356       {TransferOptions{ContextSensitiveOptions{}}});
4357 }
4358 
4359 TEST(TransferTest, ContextSensitiveMethodGetter) {
4360   std::string Code = R"(
4361     class MyClass {
4362     public:
4363       bool getField() { return Field; }
4364 
4365       bool Field;
4366     };
4367 
4368     void target() {
4369       MyClass MyObj;
4370       MyObj.Field = true;
4371       bool Foo = MyObj.getField();
4372       // [[p]]
4373     }
4374   )";
4375   runDataflow(
4376       Code,
4377       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4378          ASTContext &ASTCtx) {
4379         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4380         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4381 
4382         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4383         ASSERT_THAT(FooDecl, NotNull());
4384 
4385         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4386         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4387       },
4388       {TransferOptions{ContextSensitiveOptions{}}});
4389 }
4390 
4391 TEST(TransferTest, ContextSensitiveMethodSetter) {
4392   std::string Code = R"(
4393     class MyClass {
4394     public:
4395       void setField(bool Val) { Field = Val; }
4396 
4397       bool Field;
4398     };
4399 
4400     void target() {
4401       MyClass MyObj;
4402       MyObj.setField(true);
4403       bool Foo = MyObj.Field;
4404       // [[p]]
4405     }
4406   )";
4407   runDataflow(
4408       Code,
4409       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4410          ASTContext &ASTCtx) {
4411         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4412         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4413 
4414         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4415         ASSERT_THAT(FooDecl, NotNull());
4416 
4417         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4418         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4419       },
4420       {TransferOptions{ContextSensitiveOptions{}}});
4421 }
4422 
4423 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
4424   std::string Code = R"(
4425     class MyClass {
4426     public:
4427       bool getField() { return Field; }
4428       void setField(bool Val) { Field = Val; }
4429 
4430     private:
4431       bool Field;
4432     };
4433 
4434     void target() {
4435       MyClass MyObj;
4436       MyObj.setField(true);
4437       bool Foo = MyObj.getField();
4438       // [[p]]
4439     }
4440   )";
4441   runDataflow(
4442       Code,
4443       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4444          ASTContext &ASTCtx) {
4445         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4446         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4447 
4448         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4449         ASSERT_THAT(FooDecl, NotNull());
4450 
4451         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4452         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4453       },
4454       {TransferOptions{ContextSensitiveOptions{}}});
4455 }
4456 
4457 
4458 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
4459   std::string Code = R"(
4460     class MyClass {
4461     public:
4462       void Inner() { MyField = true; }
4463       void Outer() { Inner(); }
4464 
4465       bool MyField;
4466     };
4467 
4468     void target() {
4469       MyClass MyObj;
4470       MyObj.Outer();
4471       bool Foo = MyObj.MyField;
4472       // [[p]]
4473     }
4474   )";
4475   runDataflow(
4476       Code,
4477       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4478          ASTContext &ASTCtx) {
4479         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));;
4480         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4481 
4482         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4483         ASSERT_THAT(FooDecl, NotNull());
4484 
4485         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4486         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4487       },
4488       {TransferOptions{ContextSensitiveOptions{}}});
4489 }
4490 
4491 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
4492   std::string Code = R"(
4493     class MyClass {
4494     public:
4495       bool Inner() { return MyField; }
4496       bool Outer() { return Inner(); }
4497 
4498       bool MyField;
4499     };
4500 
4501     void target() {
4502       MyClass MyObj;
4503       MyObj.MyField = true;
4504       bool Foo = MyObj.Outer();
4505       // [[p]]
4506     }
4507   )";
4508   runDataflow(
4509       Code,
4510       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4511          ASTContext &ASTCtx) {
4512         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));;
4513         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4514 
4515         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4516         ASSERT_THAT(FooDecl, NotNull());
4517 
4518         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4519         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4520       },
4521       {TransferOptions{ContextSensitiveOptions{}}});
4522 }
4523 
4524 TEST(TransferTest, ContextSensitiveConstructorBody) {
4525   std::string Code = R"(
4526     class MyClass {
4527     public:
4528       MyClass() { MyField = true; }
4529 
4530       bool MyField;
4531     };
4532 
4533     void target() {
4534       MyClass MyObj;
4535       bool Foo = MyObj.MyField;
4536       // [[p]]
4537     }
4538   )";
4539   runDataflow(
4540       Code,
4541       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4542          ASTContext &ASTCtx) {
4543         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4544         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4545 
4546         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4547         ASSERT_THAT(FooDecl, NotNull());
4548 
4549         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4550         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4551       },
4552       {TransferOptions{ContextSensitiveOptions{}}});
4553 }
4554 
4555 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
4556   std::string Code = R"(
4557     class MyClass {
4558     public:
4559       MyClass() : MyField(true) {}
4560 
4561       bool MyField;
4562     };
4563 
4564     void target() {
4565       MyClass MyObj;
4566       bool Foo = MyObj.MyField;
4567       // [[p]]
4568     }
4569   )";
4570   runDataflow(
4571       Code,
4572       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4573          ASTContext &ASTCtx) {
4574         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4575         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4576 
4577         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4578         ASSERT_THAT(FooDecl, NotNull());
4579 
4580         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4581         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4582       },
4583       {TransferOptions{ContextSensitiveOptions{}}});
4584 }
4585 
4586 TEST(TransferTest, ContextSensitiveConstructorDefault) {
4587   std::string Code = R"(
4588     class MyClass {
4589     public:
4590       MyClass() = default;
4591 
4592       bool MyField = true;
4593     };
4594 
4595     void target() {
4596       MyClass MyObj;
4597       bool Foo = MyObj.MyField;
4598       // [[p]]
4599     }
4600   )";
4601   runDataflow(
4602       Code,
4603       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4604          ASTContext &ASTCtx) {
4605         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4606         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4607 
4608         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4609         ASSERT_THAT(FooDecl, NotNull());
4610 
4611         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl, SkipPast::None));
4612         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4613       },
4614       {TransferOptions{ContextSensitiveOptions{}}});
4615 }
4616 
4617 } // namespace
4618