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