xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision 5e4ad816bf100b0325ed45ab1cfea18deb3ab3d1)
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<BoolValue>(Env.getValue(*BazDecl));
3022           ASSERT_THAT(BazVal, NotNull());
3023           auto &A = Env.arena();
3024           EXPECT_EQ(&BazVal->formula(),
3025                     &A.makeAnd(FooVal->formula(),
3026                                A.makeOr(BarVal->formula(), QuxVal->formula())));
3027         });
3028   }
3029 
3030   {
3031     std::string Code = R"(
3032     void target(bool Foo, bool Bar, bool Qux) {
3033       bool Baz = (Foo && Qux) || (Bar);
3034       // [[p]]
3035     }
3036   )";
3037     runDataflow(
3038         Code,
3039         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3040            ASTContext &ASTCtx) {
3041           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3042           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3043 
3044           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3045           ASSERT_THAT(FooDecl, NotNull());
3046 
3047           const auto *FooVal =
3048               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3049           ASSERT_THAT(FooVal, NotNull());
3050 
3051           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3052           ASSERT_THAT(BarDecl, NotNull());
3053 
3054           const auto *BarVal =
3055               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3056           ASSERT_THAT(BarVal, NotNull());
3057 
3058           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3059           ASSERT_THAT(QuxDecl, NotNull());
3060 
3061           const auto *QuxVal =
3062               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3063           ASSERT_THAT(QuxVal, NotNull());
3064 
3065           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3066           ASSERT_THAT(BazDecl, NotNull());
3067 
3068           const auto *BazVal =
3069               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3070           ASSERT_THAT(BazVal, NotNull());
3071           auto &A = Env.arena();
3072           EXPECT_EQ(&BazVal->formula(),
3073                     &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()),
3074                               BarVal->formula()));
3075         });
3076   }
3077 
3078   {
3079     std::string Code = R"(
3080       void target(bool A, bool B, bool C, bool D) {
3081         bool Foo = ((A && B) && C) && D;
3082         // [[p]]
3083       }
3084     )";
3085     runDataflow(
3086         Code,
3087         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3088            ASTContext &ASTCtx) {
3089           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3090           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3091 
3092           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
3093           ASSERT_THAT(ADecl, NotNull());
3094 
3095           const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl));
3096           ASSERT_THAT(AVal, NotNull());
3097 
3098           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3099           ASSERT_THAT(BDecl, NotNull());
3100 
3101           const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl));
3102           ASSERT_THAT(BVal, NotNull());
3103 
3104           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3105           ASSERT_THAT(CDecl, NotNull());
3106 
3107           const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl));
3108           ASSERT_THAT(CVal, NotNull());
3109 
3110           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
3111           ASSERT_THAT(DDecl, NotNull());
3112 
3113           const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl));
3114           ASSERT_THAT(DVal, NotNull());
3115 
3116           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3117           ASSERT_THAT(FooDecl, NotNull());
3118 
3119           const auto *FooVal =
3120               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3121           ASSERT_THAT(FooVal, NotNull());
3122           auto &A = Env.arena();
3123           EXPECT_EQ(
3124               &FooVal->formula(),
3125               &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()),
3126                                    CVal->formula()),
3127                          DVal->formula()));
3128         });
3129   }
3130 }
3131 
3132 TEST(TransferTest, AssignFromBoolNegation) {
3133   std::string Code = R"(
3134     void target() {
3135       bool Foo = true;
3136       bool Bar = !(Foo);
3137       // [[p]]
3138     }
3139   )";
3140   runDataflow(
3141       Code,
3142       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3143          ASTContext &ASTCtx) {
3144         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3145         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3146 
3147         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3148         ASSERT_THAT(FooDecl, NotNull());
3149 
3150         const auto *FooVal =
3151             dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl));
3152         ASSERT_THAT(FooVal, NotNull());
3153 
3154         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3155         ASSERT_THAT(BarDecl, NotNull());
3156 
3157         const auto *BarVal =
3158             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3159         ASSERT_THAT(BarVal, NotNull());
3160         auto &A = Env.arena();
3161         EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula()));
3162       });
3163 }
3164 
3165 TEST(TransferTest, BuiltinExpect) {
3166   std::string Code = R"(
3167     void target(long Foo) {
3168       long Bar = __builtin_expect(Foo, true);
3169       /*[[p]]*/
3170     }
3171   )";
3172   runDataflow(
3173       Code,
3174       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3175          ASTContext &ASTCtx) {
3176         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3177         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3178 
3179         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3180         ASSERT_THAT(FooDecl, NotNull());
3181 
3182         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3183         ASSERT_THAT(BarDecl, NotNull());
3184 
3185         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3186       });
3187 }
3188 
3189 // `__builtin_expect` takes and returns a `long` argument, so other types
3190 // involve casts. This verifies that we identify the input and output in that
3191 // case.
3192 TEST(TransferTest, BuiltinExpectBoolArg) {
3193   std::string Code = R"(
3194     void target(bool Foo) {
3195       bool Bar = __builtin_expect(Foo, true);
3196       /*[[p]]*/
3197     }
3198   )";
3199   runDataflow(
3200       Code,
3201       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3202          ASTContext &ASTCtx) {
3203         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3204         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3205 
3206         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3207         ASSERT_THAT(FooDecl, NotNull());
3208 
3209         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3210         ASSERT_THAT(BarDecl, NotNull());
3211 
3212         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3213       });
3214 }
3215 
3216 TEST(TransferTest, BuiltinUnreachable) {
3217   std::string Code = R"(
3218     void target(bool Foo) {
3219       bool Bar = false;
3220       if (Foo)
3221         Bar = Foo;
3222       else
3223         __builtin_unreachable();
3224       (void)0;
3225       /*[[p]]*/
3226     }
3227   )";
3228   runDataflow(
3229       Code,
3230       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3231          ASTContext &ASTCtx) {
3232         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3233         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3234 
3235         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3236         ASSERT_THAT(FooDecl, NotNull());
3237 
3238         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3239         ASSERT_THAT(BarDecl, NotNull());
3240 
3241         // `__builtin_unreachable` promises that the code is
3242         // unreachable, so the compiler treats the "then" branch as the
3243         // only possible predecessor of this statement.
3244         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3245       });
3246 }
3247 
3248 TEST(TransferTest, BuiltinTrap) {
3249   std::string Code = R"(
3250     void target(bool Foo) {
3251       bool Bar = false;
3252       if (Foo)
3253         Bar = Foo;
3254       else
3255         __builtin_trap();
3256       (void)0;
3257       /*[[p]]*/
3258     }
3259   )";
3260   runDataflow(
3261       Code,
3262       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3263          ASTContext &ASTCtx) {
3264         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3265         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3266 
3267         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3268         ASSERT_THAT(FooDecl, NotNull());
3269 
3270         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3271         ASSERT_THAT(BarDecl, NotNull());
3272 
3273         // `__builtin_trap` ensures program termination, so only the
3274         // "then" branch is a predecessor of this statement.
3275         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3276       });
3277 }
3278 
3279 TEST(TransferTest, BuiltinDebugTrap) {
3280   std::string Code = R"(
3281     void target(bool Foo) {
3282       bool Bar = false;
3283       if (Foo)
3284         Bar = Foo;
3285       else
3286         __builtin_debugtrap();
3287       (void)0;
3288       /*[[p]]*/
3289     }
3290   )";
3291   runDataflow(
3292       Code,
3293       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3294          ASTContext &ASTCtx) {
3295         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3296         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3297 
3298         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3299         ASSERT_THAT(FooDecl, NotNull());
3300 
3301         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3302         ASSERT_THAT(BarDecl, NotNull());
3303 
3304         // `__builtin_debugtrap` doesn't ensure program termination.
3305         EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3306       });
3307 }
3308 
3309 TEST(TransferTest, StaticIntSingleVarDecl) {
3310   std::string Code = R"(
3311     void target() {
3312       static int Foo;
3313       // [[p]]
3314     }
3315   )";
3316   runDataflow(
3317       Code,
3318       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3319          ASTContext &ASTCtx) {
3320         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3321         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3322 
3323         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3324         ASSERT_THAT(FooDecl, NotNull());
3325 
3326         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3327         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3328 
3329         const Value *FooVal = Env.getValue(*FooLoc);
3330         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3331       });
3332 }
3333 
3334 TEST(TransferTest, StaticIntGroupVarDecl) {
3335   std::string Code = R"(
3336     void target() {
3337       static int Foo, Bar;
3338       (void)0;
3339       // [[p]]
3340     }
3341   )";
3342   runDataflow(
3343       Code,
3344       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3345          ASTContext &ASTCtx) {
3346         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3347         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3348 
3349         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3350         ASSERT_THAT(FooDecl, NotNull());
3351 
3352         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3353         ASSERT_THAT(BarDecl, NotNull());
3354 
3355         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3356         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3357 
3358         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
3359         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3360 
3361         const Value *FooVal = Env.getValue(*FooLoc);
3362         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3363 
3364         const Value *BarVal = Env.getValue(*BarLoc);
3365         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
3366 
3367         EXPECT_NE(FooVal, BarVal);
3368       });
3369 }
3370 
3371 TEST(TransferTest, GlobalIntVarDecl) {
3372   std::string Code = R"(
3373     static int Foo;
3374 
3375     void target() {
3376       int Bar = Foo;
3377       int Baz = Foo;
3378       // [[p]]
3379     }
3380   )";
3381   runDataflow(
3382       Code,
3383       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3384          ASTContext &ASTCtx) {
3385         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3386         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3387 
3388         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3389         ASSERT_THAT(BarDecl, NotNull());
3390 
3391         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3392         ASSERT_THAT(BazDecl, NotNull());
3393 
3394         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3395         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3396         EXPECT_EQ(BarVal, BazVal);
3397       });
3398 }
3399 
3400 TEST(TransferTest, StaticMemberIntVarDecl) {
3401   std::string Code = R"(
3402     struct A {
3403       static int Foo;
3404     };
3405 
3406     void target(A a) {
3407       int Bar = a.Foo;
3408       int Baz = a.Foo;
3409       // [[p]]
3410     }
3411   )";
3412   runDataflow(
3413       Code,
3414       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3415          ASTContext &ASTCtx) {
3416         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3417         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3418 
3419         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3420         ASSERT_THAT(BarDecl, NotNull());
3421 
3422         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3423         ASSERT_THAT(BazDecl, NotNull());
3424 
3425         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3426         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3427         EXPECT_EQ(BarVal, BazVal);
3428       });
3429 }
3430 
3431 TEST(TransferTest, StaticMemberRefVarDecl) {
3432   std::string Code = R"(
3433     struct A {
3434       static int &Foo;
3435     };
3436 
3437     void target(A a) {
3438       int Bar = a.Foo;
3439       int Baz = a.Foo;
3440       // [[p]]
3441     }
3442   )";
3443   runDataflow(
3444       Code,
3445       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3446          ASTContext &ASTCtx) {
3447         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3448         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3449 
3450         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3451         ASSERT_THAT(BarDecl, NotNull());
3452 
3453         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3454         ASSERT_THAT(BazDecl, NotNull());
3455 
3456         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3457         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3458         EXPECT_EQ(BarVal, BazVal);
3459       });
3460 }
3461 
3462 TEST(TransferTest, AssignMemberBeforeCopy) {
3463   std::string Code = R"(
3464     struct A {
3465       int Foo;
3466     };
3467 
3468     void target() {
3469       A A1;
3470       A A2;
3471       int Bar;
3472       A1.Foo = Bar;
3473       A2 = A1;
3474       // [[p]]
3475     }
3476   )";
3477   runDataflow(
3478       Code,
3479       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3480          ASTContext &ASTCtx) {
3481         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3482         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3483 
3484         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3485         ASSERT_THAT(FooDecl, NotNull());
3486 
3487         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3488         ASSERT_THAT(BarDecl, NotNull());
3489 
3490         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
3491         ASSERT_THAT(A1Decl, NotNull());
3492 
3493         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
3494         ASSERT_THAT(A2Decl, NotNull());
3495 
3496         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3497 
3498         const auto *A2Val = cast<StructValue>(Env.getValue(*A2Decl));
3499         EXPECT_EQ(A2Val->getChild(*FooDecl), BarVal);
3500       });
3501 }
3502 
3503 TEST(TransferTest, BooleanEquality) {
3504   std::string Code = R"(
3505     void target(bool Bar) {
3506       bool Foo = true;
3507       if (Bar == Foo) {
3508         (void)0;
3509         /*[[p-then]]*/
3510       } else {
3511         (void)0;
3512         /*[[p-else]]*/
3513       }
3514     }
3515   )";
3516   runDataflow(
3517       Code,
3518       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3519          ASTContext &ASTCtx) {
3520         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3521         const Environment &EnvThen =
3522             getEnvironmentAtAnnotation(Results, "p-then");
3523         const Environment &EnvElse =
3524             getEnvironmentAtAnnotation(Results, "p-else");
3525 
3526         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3527         ASSERT_THAT(BarDecl, NotNull());
3528 
3529         auto &BarValThen = *cast<BoolValue>(EnvThen.getValue(*BarDecl));
3530         EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen));
3531 
3532         auto &BarValElse = *cast<BoolValue>(EnvElse.getValue(*BarDecl));
3533         EXPECT_FALSE(EnvElse.flowConditionImplies(BarValElse));
3534       });
3535 }
3536 
3537 TEST(TransferTest, BooleanInequality) {
3538   std::string Code = R"(
3539     void target(bool Bar) {
3540       bool Foo = true;
3541       if (Bar != Foo) {
3542         (void)0;
3543         /*[[p-then]]*/
3544       } else {
3545         (void)0;
3546         /*[[p-else]]*/
3547       }
3548     }
3549   )";
3550   runDataflow(
3551       Code,
3552       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3553          ASTContext &ASTCtx) {
3554         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3555         const Environment &EnvThen =
3556             getEnvironmentAtAnnotation(Results, "p-then");
3557         const Environment &EnvElse =
3558             getEnvironmentAtAnnotation(Results, "p-else");
3559 
3560         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3561         ASSERT_THAT(BarDecl, NotNull());
3562 
3563         auto &BarValThen = *cast<BoolValue>(EnvThen.getValue(*BarDecl));
3564         EXPECT_FALSE(EnvThen.flowConditionImplies(BarValThen));
3565 
3566         auto &BarValElse = *cast<BoolValue>(EnvElse.getValue(*BarDecl));
3567         EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse));
3568       });
3569 }
3570 
3571 TEST(TransferTest, IntegerLiteralEquality) {
3572   std::string Code = R"(
3573     void target() {
3574       bool equal = (42 == 42);
3575       // [[p]]
3576     }
3577   )";
3578   runDataflow(
3579       Code,
3580       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3581          ASTContext &ASTCtx) {
3582         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3583 
3584         auto &Equal = getValueForDecl<BoolValue>(ASTCtx, Env, "equal");
3585         EXPECT_TRUE(Env.flowConditionImplies(Equal));
3586       });
3587 }
3588 
3589 TEST(TransferTest, CorrelatedBranches) {
3590   std::string Code = R"(
3591     void target(bool B, bool C) {
3592       if (B) {
3593         return;
3594       }
3595       (void)0;
3596       /*[[p0]]*/
3597       if (C) {
3598         B = true;
3599         /*[[p1]]*/
3600       }
3601       if (B) {
3602         (void)0;
3603         /*[[p2]]*/
3604       }
3605     }
3606   )";
3607   runDataflow(
3608       Code,
3609       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3610          ASTContext &ASTCtx) {
3611         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
3612 
3613         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3614         ASSERT_THAT(CDecl, NotNull());
3615 
3616         {
3617           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
3618           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3619           ASSERT_THAT(BDecl, NotNull());
3620           auto &BVal = *cast<BoolValue>(Env.getValue(*BDecl));
3621 
3622           EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BVal)));
3623         }
3624 
3625         {
3626           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
3627           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl));
3628           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3629         }
3630 
3631         {
3632           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
3633           auto &CVal = *cast<BoolValue>(Env.getValue(*CDecl));
3634           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3635         }
3636       });
3637 }
3638 
3639 TEST(TransferTest, LoopWithAssignmentConverges) {
3640   std::string Code = R"(
3641     bool foo();
3642 
3643     void target() {
3644        do {
3645         bool Bar = foo();
3646         if (Bar) break;
3647         (void)Bar;
3648         /*[[p]]*/
3649       } while (true);
3650     }
3651   )";
3652   // The key property that we are verifying is implicit in `runDataflow` --
3653   // namely, that the analysis succeeds, rather than hitting the maximum number
3654   // of iterations.
3655   runDataflow(
3656       Code,
3657       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3658          ASTContext &ASTCtx) {
3659         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3660         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3661 
3662         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3663         ASSERT_THAT(BarDecl, NotNull());
3664 
3665         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl));
3666         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3667       });
3668 }
3669 
3670 TEST(TransferTest, LoopWithStagedAssignments) {
3671   std::string Code = R"(
3672     bool foo();
3673 
3674     void target() {
3675       bool Bar = false;
3676       bool Err = false;
3677       while (foo()) {
3678         if (Bar)
3679           Err = true;
3680         Bar = true;
3681         /*[[p]]*/
3682       }
3683     }
3684   )";
3685   runDataflow(
3686       Code,
3687       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3688          ASTContext &ASTCtx) {
3689         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3690         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3691 
3692         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3693         ASSERT_THAT(BarDecl, NotNull());
3694         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
3695         ASSERT_THAT(ErrDecl, NotNull());
3696 
3697         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl));
3698         auto &ErrVal = *cast<BoolValue>(Env.getValue(*ErrDecl));
3699         EXPECT_TRUE(Env.flowConditionImplies(BarVal));
3700         // An unsound analysis, for example only evaluating the loop once, can
3701         // conclude that `Err` is false. So, we test that this conclusion is not
3702         // reached.
3703         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(ErrVal)));
3704       });
3705 }
3706 
3707 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
3708   std::string Code = R"(
3709     bool &foo();
3710 
3711     void target() {
3712        do {
3713         bool& Bar = foo();
3714         if (Bar) break;
3715         (void)Bar;
3716         /*[[p]]*/
3717       } while (true);
3718     }
3719   )";
3720   // The key property that we are verifying is that the analysis succeeds,
3721   // rather than hitting the maximum number of iterations.
3722   runDataflow(
3723       Code,
3724       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3725          ASTContext &ASTCtx) {
3726         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3727         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3728 
3729         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3730         ASSERT_THAT(BarDecl, NotNull());
3731 
3732         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl));
3733         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
3734       });
3735 }
3736 
3737 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
3738   std::string Code = R"(
3739     struct Lookup {
3740       int x;
3741     };
3742 
3743     void target(Lookup val, bool b) {
3744       const Lookup* l = nullptr;
3745       while (b) {
3746         l = &val;
3747         /*[[p-inner]]*/
3748       }
3749       (void)0;
3750       /*[[p-outer]]*/
3751     }
3752   )";
3753   // The key property that we are verifying is implicit in `runDataflow` --
3754   // namely, that the analysis succeeds, rather than hitting the maximum number
3755   // of iterations.
3756   runDataflow(
3757       Code,
3758       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3759          ASTContext &ASTCtx) {
3760         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
3761         const Environment &InnerEnv =
3762             getEnvironmentAtAnnotation(Results, "p-inner");
3763         const Environment &OuterEnv =
3764             getEnvironmentAtAnnotation(Results, "p-outer");
3765 
3766         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
3767         ASSERT_THAT(ValDecl, NotNull());
3768 
3769         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
3770         ASSERT_THAT(LDecl, NotNull());
3771 
3772         // Inner.
3773         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
3774         ASSERT_THAT(LVal, NotNull());
3775 
3776         EXPECT_EQ(&LVal->getPointeeLoc(),
3777                   InnerEnv.getStorageLocation(*ValDecl));
3778 
3779         // Outer.
3780         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
3781         ASSERT_THAT(LVal, NotNull());
3782 
3783         // The loop body may not have been executed, so we should not conclude
3784         // that `l` points to `val`.
3785         EXPECT_NE(&LVal->getPointeeLoc(),
3786                   OuterEnv.getStorageLocation(*ValDecl));
3787       });
3788 }
3789 
3790 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
3791   std::string Code = R"(
3792     union Union {
3793       int A;
3794       float B;
3795     };
3796 
3797     void foo() {
3798       Union A;
3799       Union B;
3800       A = B;
3801     }
3802   )";
3803   // This is a crash regression test when calling the transfer function on a
3804   // `CXXThisExpr` that refers to a union.
3805   runDataflow(
3806       Code,
3807       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
3808          ASTContext &) {},
3809       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
3810 }
3811 
3812 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
3813   std::string Code = R"(
3814     struct A {
3815       int Foo;
3816       int Bar;
3817     };
3818 
3819     void target() {
3820       int Qux;
3821       A Baz;
3822       Baz.Foo = Qux;
3823       auto &FooRef = Baz.Foo;
3824       auto &BarRef = Baz.Bar;
3825       auto &[BoundFooRef, BoundBarRef] = Baz;
3826       // [[p]]
3827     }
3828   )";
3829   runDataflow(
3830       Code,
3831       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3832          ASTContext &ASTCtx) {
3833         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3834         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3835 
3836         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3837         ASSERT_THAT(FooRefDecl, NotNull());
3838 
3839         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3840         ASSERT_THAT(BarRefDecl, NotNull());
3841 
3842         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3843         ASSERT_THAT(QuxDecl, NotNull());
3844 
3845         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3846         ASSERT_THAT(BoundFooRefDecl, NotNull());
3847 
3848         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3849         ASSERT_THAT(BoundBarRefDecl, NotNull());
3850 
3851         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
3852         ASSERT_THAT(FooRefLoc, NotNull());
3853 
3854         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
3855         ASSERT_THAT(BarRefLoc, NotNull());
3856 
3857         const Value *QuxVal = Env.getValue(*QuxDecl);
3858         ASSERT_THAT(QuxVal, NotNull());
3859 
3860         const StorageLocation *BoundFooRefLoc =
3861             Env.getStorageLocation(*BoundFooRefDecl);
3862         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3863 
3864         const StorageLocation *BoundBarRefLoc =
3865             Env.getStorageLocation(*BoundBarRefDecl);
3866         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3867 
3868         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
3869       });
3870 }
3871 
3872 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
3873   std::string Code = R"(
3874     struct A {
3875       int &Foo;
3876       int &Bar;
3877     };
3878 
3879     void target(A Baz) {
3880       int Qux;
3881       Baz.Foo = Qux;
3882       auto &FooRef = Baz.Foo;
3883       auto &BarRef = Baz.Bar;
3884       auto &[BoundFooRef, BoundBarRef] = Baz;
3885       // [[p]]
3886     }
3887   )";
3888   runDataflow(
3889       Code,
3890       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3891          ASTContext &ASTCtx) {
3892         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3893         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3894 
3895         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3896         ASSERT_THAT(FooRefDecl, NotNull());
3897 
3898         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3899         ASSERT_THAT(BarRefDecl, NotNull());
3900 
3901         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3902         ASSERT_THAT(QuxDecl, NotNull());
3903 
3904         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3905         ASSERT_THAT(BoundFooRefDecl, NotNull());
3906 
3907         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3908         ASSERT_THAT(BoundBarRefDecl, NotNull());
3909 
3910         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
3911         ASSERT_THAT(FooRefLoc, NotNull());
3912 
3913         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
3914         ASSERT_THAT(BarRefLoc, NotNull());
3915 
3916         const Value *QuxVal = Env.getValue(*QuxDecl);
3917         ASSERT_THAT(QuxVal, NotNull());
3918 
3919         const StorageLocation *BoundFooRefLoc =
3920             Env.getStorageLocation(*BoundFooRefDecl);
3921         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3922 
3923         const StorageLocation *BoundBarRefLoc =
3924             Env.getStorageLocation(*BoundBarRefDecl);
3925         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3926 
3927         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
3928       });
3929 }
3930 
3931 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
3932   std::string Code = R"(
3933     struct A {
3934       int Foo;
3935       int Bar;
3936     };
3937 
3938     void target() {
3939       int Qux;
3940       A Baz;
3941       Baz.Foo = Qux;
3942       auto &FooRef = Baz.Foo;
3943       auto &BarRef = Baz.Bar;
3944       auto [BoundFoo, BoundBar] = Baz;
3945       // [[p]]
3946     }
3947   )";
3948   runDataflow(
3949       Code,
3950       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3951          ASTContext &ASTCtx) {
3952         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3953         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3954 
3955         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3956         ASSERT_THAT(FooRefDecl, NotNull());
3957 
3958         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3959         ASSERT_THAT(BarRefDecl, NotNull());
3960 
3961         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
3962         ASSERT_THAT(BoundFooDecl, NotNull());
3963 
3964         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
3965         ASSERT_THAT(BoundBarDecl, NotNull());
3966 
3967         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3968         ASSERT_THAT(QuxDecl, NotNull());
3969 
3970         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
3971         ASSERT_THAT(FooRefLoc, NotNull());
3972 
3973         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
3974         ASSERT_THAT(BarRefLoc, NotNull());
3975 
3976         const Value *QuxVal = Env.getValue(*QuxDecl);
3977         ASSERT_THAT(QuxVal, NotNull());
3978 
3979         const StorageLocation *BoundFooLoc =
3980             Env.getStorageLocation(*BoundFooDecl);
3981         EXPECT_NE(BoundFooLoc, FooRefLoc);
3982 
3983         const StorageLocation *BoundBarLoc =
3984             Env.getStorageLocation(*BoundBarDecl);
3985         EXPECT_NE(BoundBarLoc, BarRefLoc);
3986 
3987         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
3988       });
3989 }
3990 
3991 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
3992   std::string Code = R"(
3993     namespace std {
3994     using size_t = int;
3995     template <class> struct tuple_size;
3996     template <std::size_t, class> struct tuple_element;
3997     template <class...> class tuple;
3998 
3999     namespace {
4000     template <class T, T v>
4001     struct size_helper { static const T value = v; };
4002     } // namespace
4003 
4004     template <class... T>
4005     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4006 
4007     template <std::size_t I, class... T>
4008     struct tuple_element<I, tuple<T...>> {
4009       using type =  __type_pack_element<I, T...>;
4010     };
4011 
4012     template <class...> class tuple {};
4013 
4014     template <std::size_t I, class... T>
4015     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4016     } // namespace std
4017 
4018     std::tuple<bool, int> makeTuple();
4019 
4020     void target(bool B) {
4021       auto [BoundFoo, BoundBar] = makeTuple();
4022       bool Baz;
4023       // Include if-then-else to test interaction of `BindingDecl` with join.
4024       if (B) {
4025         Baz = BoundFoo;
4026         (void)BoundBar;
4027         // [[p1]]
4028       } else {
4029         Baz = BoundFoo;
4030       }
4031       (void)0;
4032       // [[p2]]
4033     }
4034   )";
4035   runDataflow(
4036       Code,
4037       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4038          ASTContext &ASTCtx) {
4039         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4040         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4041 
4042         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4043         ASSERT_THAT(BoundFooDecl, NotNull());
4044 
4045         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4046         ASSERT_THAT(BoundBarDecl, NotNull());
4047 
4048         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4049         ASSERT_THAT(BazDecl, NotNull());
4050 
4051         // BindingDecls always map to references -- either lvalue or rvalue, so
4052         // we still need to skip here.
4053         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4054         ASSERT_THAT(BoundFooValue, NotNull());
4055         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4056 
4057         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4058         ASSERT_THAT(BoundBarValue, NotNull());
4059         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4060 
4061         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
4062         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4063 
4064         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4065 
4066         // Test that `BoundFooDecl` retains the value we expect, after the join.
4067         BoundFooValue = Env2.getValue(*BoundFooDecl);
4068         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4069       });
4070 }
4071 
4072 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
4073   std::string Code = R"(
4074     namespace std {
4075     using size_t = int;
4076     template <class> struct tuple_size;
4077     template <std::size_t, class> struct tuple_element;
4078     template <class...> class tuple;
4079 
4080     namespace {
4081     template <class T, T v>
4082     struct size_helper { static const T value = v; };
4083     } // namespace
4084 
4085     template <class... T>
4086     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4087 
4088     template <std::size_t I, class... T>
4089     struct tuple_element<I, tuple<T...>> {
4090       using type =  __type_pack_element<I, T...>;
4091     };
4092 
4093     template <class...> class tuple {};
4094 
4095     template <std::size_t I, class... T>
4096     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4097     } // namespace std
4098 
4099     std::tuple<bool, int> &getTuple();
4100 
4101     void target(bool B) {
4102       auto &[BoundFoo, BoundBar] = getTuple();
4103       bool Baz;
4104       // Include if-then-else to test interaction of `BindingDecl` with join.
4105       if (B) {
4106         Baz = BoundFoo;
4107         (void)BoundBar;
4108         // [[p1]]
4109       } else {
4110         Baz = BoundFoo;
4111       }
4112       (void)0;
4113       // [[p2]]
4114     }
4115   )";
4116   runDataflow(
4117       Code,
4118       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4119          ASTContext &ASTCtx) {
4120         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4121         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4122 
4123         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4124         ASSERT_THAT(BoundFooDecl, NotNull());
4125 
4126         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4127         ASSERT_THAT(BoundBarDecl, NotNull());
4128 
4129         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4130         ASSERT_THAT(BazDecl, NotNull());
4131 
4132         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4133         ASSERT_THAT(BoundFooValue, NotNull());
4134         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4135 
4136         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4137         ASSERT_THAT(BoundBarValue, NotNull());
4138         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4139 
4140         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
4141         // works as expected. We don't test aliasing properties of the
4142         // reference, because we don't model `std::get` and so have no way to
4143         // equate separate references into the tuple.
4144         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4145 
4146         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4147 
4148         // Test that `BoundFooDecl` retains the value we expect, after the join.
4149         BoundFooValue = Env2.getValue(*BoundFooDecl);
4150         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4151       });
4152 }
4153 
4154 TEST(TransferTest, BinaryOperatorComma) {
4155   std::string Code = R"(
4156     void target(int Foo, int Bar) {
4157       int &Baz = (Foo, Bar);
4158       // [[p]]
4159     }
4160   )";
4161   runDataflow(
4162       Code,
4163       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4164          ASTContext &ASTCtx) {
4165         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4166         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4167 
4168         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4169         ASSERT_THAT(BarDecl, NotNull());
4170 
4171         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4172         ASSERT_THAT(BazDecl, NotNull());
4173 
4174         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4175         ASSERT_THAT(BarLoc, NotNull());
4176 
4177         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
4178         EXPECT_EQ(BazLoc, BarLoc);
4179       });
4180 }
4181 
4182 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
4183   std::string Code = R"(
4184     void target(bool Foo) {
4185       if (Foo) {
4186         (void)0;
4187         // [[if_then]]
4188       } else {
4189         (void)0;
4190         // [[if_else]]
4191       }
4192     }
4193   )";
4194   runDataflow(
4195       Code,
4196       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4197          ASTContext &ASTCtx) {
4198         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
4199         const Environment &ThenEnv =
4200             getEnvironmentAtAnnotation(Results, "if_then");
4201         const Environment &ElseEnv =
4202             getEnvironmentAtAnnotation(Results, "if_else");
4203 
4204         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4205         ASSERT_THAT(FooDecl, NotNull());
4206 
4207         BoolValue &ThenFooVal = *cast<BoolValue>(ThenEnv.getValue(*FooDecl));
4208         EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal));
4209 
4210         BoolValue &ElseFooVal = *cast<BoolValue>(ElseEnv.getValue(*FooDecl));
4211         EXPECT_TRUE(ElseEnv.flowConditionImplies(ElseEnv.makeNot(ElseFooVal)));
4212       });
4213 }
4214 
4215 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
4216   std::string Code = R"(
4217     void target(bool Foo) {
4218       while (Foo) {
4219         (void)0;
4220         // [[loop_body]]
4221       }
4222       (void)0;
4223       // [[after_loop]]
4224     }
4225   )";
4226   runDataflow(
4227       Code,
4228       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4229          ASTContext &ASTCtx) {
4230         ASSERT_THAT(Results.keys(),
4231                     UnorderedElementsAre("loop_body", "after_loop"));
4232         const Environment &LoopBodyEnv =
4233             getEnvironmentAtAnnotation(Results, "loop_body");
4234         const Environment &AfterLoopEnv =
4235             getEnvironmentAtAnnotation(Results, "after_loop");
4236 
4237         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4238         ASSERT_THAT(FooDecl, NotNull());
4239 
4240         BoolValue &LoopBodyFooVal =
4241             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl));
4242         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4243 
4244         BoolValue &AfterLoopFooVal =
4245             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl));
4246         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4247             AfterLoopEnv.makeNot(AfterLoopFooVal)));
4248       });
4249 }
4250 
4251 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
4252   std::string Code = R"(
4253     void target(bool Foo) {
4254       bool Bar = true;
4255       do {
4256         (void)0;
4257         // [[loop_body]]
4258         Bar = false;
4259       } while (Foo);
4260       (void)0;
4261       // [[after_loop]]
4262     }
4263   )";
4264   runDataflow(
4265       Code,
4266       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4267          ASTContext &ASTCtx) {
4268         ASSERT_THAT(Results.keys(),
4269                     UnorderedElementsAre("loop_body", "after_loop"));
4270         const Environment &LoopBodyEnv =
4271             getEnvironmentAtAnnotation(Results, "loop_body");
4272         const Environment &AfterLoopEnv =
4273             getEnvironmentAtAnnotation(Results, "after_loop");
4274 
4275         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4276         ASSERT_THAT(FooDecl, NotNull());
4277 
4278         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4279         ASSERT_THAT(BarDecl, NotNull());
4280 
4281         BoolValue &LoopBodyFooVal =
4282             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl));
4283         BoolValue &LoopBodyBarVal =
4284             *cast<BoolValue>(LoopBodyEnv.getValue(*BarDecl));
4285         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(
4286             LoopBodyEnv.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
4287 
4288         BoolValue &AfterLoopFooVal =
4289             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl));
4290         BoolValue &AfterLoopBarVal =
4291             *cast<BoolValue>(AfterLoopEnv.getValue(*BarDecl));
4292         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4293             AfterLoopEnv.makeNot(AfterLoopFooVal)));
4294         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4295             AfterLoopEnv.makeNot(AfterLoopBarVal)));
4296       });
4297 }
4298 
4299 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
4300   std::string Code = R"(
4301     void target(bool Foo) {
4302       for (; Foo;) {
4303         (void)0;
4304         // [[loop_body]]
4305       }
4306       (void)0;
4307       // [[after_loop]]
4308     }
4309   )";
4310   runDataflow(
4311       Code,
4312       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4313          ASTContext &ASTCtx) {
4314         ASSERT_THAT(Results.keys(),
4315                     UnorderedElementsAre("loop_body", "after_loop"));
4316         const Environment &LoopBodyEnv =
4317             getEnvironmentAtAnnotation(Results, "loop_body");
4318         const Environment &AfterLoopEnv =
4319             getEnvironmentAtAnnotation(Results, "after_loop");
4320 
4321         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4322         ASSERT_THAT(FooDecl, NotNull());
4323 
4324         BoolValue &LoopBodyFooVal =
4325             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl));
4326         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4327 
4328         BoolValue &AfterLoopFooVal =
4329             *cast<BoolValue>(AfterLoopEnv.getValue(*FooDecl));
4330         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4331             AfterLoopEnv.makeNot(AfterLoopFooVal)));
4332       });
4333 }
4334 
4335 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
4336   std::string Code = R"(
4337     void target(bool Foo) {
4338       for (;;) {
4339         (void)0;
4340         // [[loop_body]]
4341       }
4342     }
4343   )";
4344   runDataflow(
4345       Code,
4346       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4347          ASTContext &ASTCtx) {
4348         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
4349         const Environment &LoopBodyEnv =
4350             getEnvironmentAtAnnotation(Results, "loop_body");
4351 
4352         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4353         ASSERT_THAT(FooDecl, NotNull());
4354 
4355         BoolValue &LoopBodyFooVal =
4356             *cast<BoolValue>(LoopBodyEnv.getValue(*FooDecl));
4357         EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4358       });
4359 }
4360 
4361 TEST(TransferTest, ContextSensitiveOptionDisabled) {
4362   std::string Code = R"(
4363     bool GiveBool();
4364     void SetBool(bool &Var) { Var = true; }
4365 
4366     void target() {
4367       bool Foo = GiveBool();
4368       SetBool(Foo);
4369       // [[p]]
4370     }
4371   )";
4372   runDataflow(
4373       Code,
4374       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4375          ASTContext &ASTCtx) {
4376         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4377         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4378 
4379         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4380         ASSERT_THAT(FooDecl, NotNull());
4381 
4382         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4383         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4384         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4385       },
4386       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
4387 }
4388 
4389 TEST(TransferTest, ContextSensitiveReturnReference) {
4390   std::string Code = R"(
4391     class S {};
4392     S& target(bool b, S &s) {
4393       return s;
4394       // [[p]]
4395     }
4396   )";
4397   runDataflow(
4398       Code,
4399       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4400          ASTContext &ASTCtx) {
4401         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4402 
4403         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4404         ASSERT_THAT(SDecl, NotNull());
4405 
4406         auto *SLoc = Env.getStorageLocation(*SDecl);
4407         ASSERT_THAT(SLoc, NotNull());
4408 
4409         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
4410       },
4411       {BuiltinOptions{ContextSensitiveOptions{}}});
4412 }
4413 
4414 // This test is a regression test, based on a real crash.
4415 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
4416   std::string Code = R"(
4417     class S {};
4418     S& target(bool b, S &s) {
4419       return b ? s : s;
4420       // [[p]]
4421     }
4422   )";
4423   runDataflow(
4424       Code,
4425       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4426          ASTContext &ASTCtx) {
4427         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4428         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4429 
4430         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4431         ASSERT_THAT(SDecl, NotNull());
4432 
4433         auto *SLoc = Env.getStorageLocation(*SDecl);
4434         ASSERT_THAT(SLoc, NotNull());
4435         EXPECT_THAT(Env.getValue(*SLoc), NotNull());
4436 
4437         auto *Loc = Env.getReturnStorageLocation();
4438         ASSERT_THAT(Loc, NotNull());
4439         EXPECT_THAT(Env.getValue(*Loc), NotNull());
4440 
4441         // TODO: We would really like to make this stronger assertion, but that
4442         // doesn't work because we don't propagate values correctly through
4443         // the conditional operator yet.
4444         // ASSERT_THAT(Loc, Eq(SLoc));
4445       },
4446       {BuiltinOptions{ContextSensitiveOptions{}}});
4447 }
4448 
4449 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
4450   std::string Code = R"(
4451     class S {};
4452     S &callee(bool b, S &s1_parm, S &s2_parm) {
4453       if (b)
4454         return s1_parm;
4455       else
4456         return s2_parm;
4457     }
4458     void target(bool b) {
4459       S s1;
4460       S s2;
4461       S &return_s1 = s1;
4462       S &return_s2 = s2;
4463       S &return_dont_know = callee(b, s1, s2);
4464       // [[p]]
4465     }
4466   )";
4467   runDataflow(
4468       Code,
4469       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4470          ASTContext &ASTCtx) {
4471         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4472 
4473         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
4474         ASSERT_THAT(S1, NotNull());
4475         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
4476         ASSERT_THAT(S2, NotNull());
4477         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
4478         ASSERT_THAT(ReturnS1, NotNull());
4479         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
4480         ASSERT_THAT(ReturnS2, NotNull());
4481         const ValueDecl *ReturnDontKnow =
4482             findValueDecl(ASTCtx, "return_dont_know");
4483         ASSERT_THAT(ReturnDontKnow, NotNull());
4484 
4485         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
4486         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
4487 
4488         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
4489         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
4490 
4491         // In the case where we don't have a consistent storage location for
4492         // the return value, the framework creates a new storage location, which
4493         // should be different from the storage locations of `s1` and `s2`.
4494         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
4495         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
4496       },
4497       {BuiltinOptions{ContextSensitiveOptions{}}});
4498 }
4499 
4500 TEST(TransferTest, ContextSensitiveDepthZero) {
4501   std::string Code = R"(
4502     bool GiveBool();
4503     void SetBool(bool &Var) { Var = true; }
4504 
4505     void target() {
4506       bool Foo = GiveBool();
4507       SetBool(Foo);
4508       // [[p]]
4509     }
4510   )";
4511   runDataflow(
4512       Code,
4513       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4514          ASTContext &ASTCtx) {
4515         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4516         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4517 
4518         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4519         ASSERT_THAT(FooDecl, NotNull());
4520 
4521         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4522         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4523         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4524       },
4525       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
4526 }
4527 
4528 TEST(TransferTest, ContextSensitiveSetTrue) {
4529   std::string Code = R"(
4530     bool GiveBool();
4531     void SetBool(bool &Var) { Var = true; }
4532 
4533     void target() {
4534       bool Foo = GiveBool();
4535       SetBool(Foo);
4536       // [[p]]
4537     }
4538   )";
4539   runDataflow(
4540       Code,
4541       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4542          ASTContext &ASTCtx) {
4543         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4544         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4545 
4546         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4547         ASSERT_THAT(FooDecl, NotNull());
4548 
4549         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4550         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4551       },
4552       {BuiltinOptions{ContextSensitiveOptions{}}});
4553 }
4554 
4555 TEST(TransferTest, ContextSensitiveSetFalse) {
4556   std::string Code = R"(
4557     bool GiveBool();
4558     void SetBool(bool &Var) { Var = false; }
4559 
4560     void target() {
4561       bool Foo = GiveBool();
4562       SetBool(Foo);
4563       // [[p]]
4564     }
4565   )";
4566   runDataflow(
4567       Code,
4568       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4569          ASTContext &ASTCtx) {
4570         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4571         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4572 
4573         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4574         ASSERT_THAT(FooDecl, NotNull());
4575 
4576         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4577         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4578       },
4579       {BuiltinOptions{ContextSensitiveOptions{}}});
4580 }
4581 
4582 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
4583   std::string Code = R"(
4584     bool GiveBool();
4585     void SetBool(bool &Var, bool Val) { Var = Val; }
4586 
4587     void target() {
4588       bool Foo = GiveBool();
4589       bool Bar = GiveBool();
4590       SetBool(Foo, true);
4591       SetBool(Bar, false);
4592       // [[p]]
4593     }
4594   )";
4595   runDataflow(
4596       Code,
4597       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4598          ASTContext &ASTCtx) {
4599         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4600         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4601 
4602         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4603         ASSERT_THAT(FooDecl, NotNull());
4604 
4605         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4606         ASSERT_THAT(BarDecl, NotNull());
4607 
4608         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4609         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4610         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4611 
4612         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl));
4613         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4614         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4615       },
4616       {BuiltinOptions{ContextSensitiveOptions{}}});
4617 }
4618 
4619 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
4620   std::string Code = R"(
4621     bool GiveBool();
4622     void SetBool1(bool &Var) { Var = true; }
4623     void SetBool2(bool &Var) { SetBool1(Var); }
4624 
4625     void target() {
4626       bool Foo = GiveBool();
4627       SetBool2(Foo);
4628       // [[p]]
4629     }
4630   )";
4631   runDataflow(
4632       Code,
4633       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4634          ASTContext &ASTCtx) {
4635         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4636         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4637 
4638         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4639         ASSERT_THAT(FooDecl, NotNull());
4640 
4641         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4642         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4643         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4644       },
4645       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
4646 }
4647 
4648 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
4649   std::string Code = R"(
4650     bool GiveBool();
4651     void SetBool1(bool &Var) { Var = true; }
4652     void SetBool2(bool &Var) { SetBool1(Var); }
4653 
4654     void target() {
4655       bool Foo = GiveBool();
4656       SetBool2(Foo);
4657       // [[p]]
4658     }
4659   )";
4660   runDataflow(
4661       Code,
4662       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4663          ASTContext &ASTCtx) {
4664         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4665         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4666 
4667         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4668         ASSERT_THAT(FooDecl, NotNull());
4669 
4670         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4671         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4672       },
4673       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4674 }
4675 
4676 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
4677   std::string Code = R"(
4678     bool GiveBool();
4679     void SetBool1(bool &Var) { Var = true; }
4680     void SetBool2(bool &Var) { SetBool1(Var); }
4681     void SetBool3(bool &Var) { SetBool2(Var); }
4682 
4683     void target() {
4684       bool Foo = GiveBool();
4685       SetBool3(Foo);
4686       // [[p]]
4687     }
4688   )";
4689   runDataflow(
4690       Code,
4691       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4692          ASTContext &ASTCtx) {
4693         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4694         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4695 
4696         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4697         ASSERT_THAT(FooDecl, NotNull());
4698 
4699         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4700         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4701         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4702       },
4703       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4704 }
4705 
4706 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
4707   std::string Code = R"(
4708     bool GiveBool();
4709     void SetBool1(bool &Var) { Var = true; }
4710     void SetBool2(bool &Var) { SetBool1(Var); }
4711     void SetBool3(bool &Var) { SetBool2(Var); }
4712 
4713     void target() {
4714       bool Foo = GiveBool();
4715       SetBool3(Foo);
4716       // [[p]]
4717     }
4718   )";
4719   runDataflow(
4720       Code,
4721       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4722          ASTContext &ASTCtx) {
4723         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4724         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4725 
4726         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4727         ASSERT_THAT(FooDecl, NotNull());
4728 
4729         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4730         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4731       },
4732       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
4733 }
4734 
4735 TEST(TransferTest, ContextSensitiveMutualRecursion) {
4736   std::string Code = R"(
4737     bool Pong(bool X, bool Y);
4738 
4739     bool Ping(bool X, bool Y) {
4740       if (X) {
4741         return Y;
4742       } else {
4743         return Pong(!X, Y);
4744       }
4745     }
4746 
4747     bool Pong(bool X, bool Y) {
4748       if (Y) {
4749         return X;
4750       } else {
4751         return Ping(X, !Y);
4752       }
4753     }
4754 
4755     void target() {
4756       bool Foo = Ping(false, false);
4757       // [[p]]
4758     }
4759   )";
4760   runDataflow(
4761       Code,
4762       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4763          ASTContext &ASTCtx) {
4764         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4765         // The analysis doesn't crash...
4766         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4767 
4768         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4769         ASSERT_THAT(FooDecl, NotNull());
4770 
4771         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4772         // ... but it also can't prove anything here.
4773         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4774         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4775       },
4776       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
4777 }
4778 
4779 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
4780   std::string Code = R"(
4781     void SetBools(bool &Var1, bool &Var2) {
4782       Var1 = true;
4783       Var2 = false;
4784     }
4785 
4786     void target() {
4787       bool Foo = false;
4788       bool Bar = true;
4789       SetBools(Foo, Bar);
4790       // [[p]]
4791     }
4792   )";
4793   runDataflow(
4794       Code,
4795       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4796          ASTContext &ASTCtx) {
4797         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4798         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4799 
4800         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4801         ASSERT_THAT(FooDecl, NotNull());
4802 
4803         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4804         ASSERT_THAT(BarDecl, NotNull());
4805 
4806         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4807         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4808         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4809 
4810         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl));
4811         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4812         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4813       },
4814       {BuiltinOptions{ContextSensitiveOptions{}}});
4815 }
4816 
4817 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
4818   std::string Code = R"(
4819     void IfCond(bool Cond, bool &Then, bool &Else) {
4820       if (Cond) {
4821         Then = true;
4822       } else {
4823         Else = true;
4824       }
4825     }
4826 
4827     void target() {
4828       bool Foo = false;
4829       bool Bar = false;
4830       bool Baz = false;
4831       IfCond(Foo, Bar, Baz);
4832       // [[p]]
4833     }
4834   )";
4835   runDataflow(
4836       Code,
4837       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4838          ASTContext &ASTCtx) {
4839         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4840         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4841 
4842         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4843         ASSERT_THAT(BarDecl, NotNull());
4844 
4845         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4846         ASSERT_THAT(BazDecl, NotNull());
4847 
4848         auto &BarVal = *cast<BoolValue>(Env.getValue(*BarDecl));
4849         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4850         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(BarVal)));
4851 
4852         auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl));
4853         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
4854         EXPECT_FALSE(Env.flowConditionImplies(Env.makeNot(BazVal)));
4855       },
4856       {BuiltinOptions{ContextSensitiveOptions{}}});
4857 }
4858 
4859 TEST(TransferTest, ContextSensitiveReturnVoid) {
4860   std::string Code = R"(
4861     void Noop() { return; }
4862 
4863     void target() {
4864       Noop();
4865       // [[p]]
4866     }
4867   )";
4868   runDataflow(
4869       Code,
4870       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4871          ASTContext &ASTCtx) {
4872         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4873         // This just tests that the analysis doesn't crash.
4874       },
4875       {BuiltinOptions{ContextSensitiveOptions{}}});
4876 }
4877 
4878 TEST(TransferTest, ContextSensitiveReturnTrue) {
4879   std::string Code = R"(
4880     bool GiveBool() { return true; }
4881 
4882     void target() {
4883       bool Foo = GiveBool();
4884       // [[p]]
4885     }
4886   )";
4887   runDataflow(
4888       Code,
4889       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4890          ASTContext &ASTCtx) {
4891         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4892         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4893 
4894         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4895         ASSERT_THAT(FooDecl, NotNull());
4896 
4897         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4898         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4899       },
4900       {BuiltinOptions{ContextSensitiveOptions{}}});
4901 }
4902 
4903 TEST(TransferTest, ContextSensitiveReturnFalse) {
4904   std::string Code = R"(
4905     bool GiveBool() { return false; }
4906 
4907     void target() {
4908       bool Foo = GiveBool();
4909       // [[p]]
4910     }
4911   )";
4912   runDataflow(
4913       Code,
4914       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4915          ASTContext &ASTCtx) {
4916         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4917         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4918 
4919         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4920         ASSERT_THAT(FooDecl, NotNull());
4921 
4922         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4923         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(FooVal)));
4924       },
4925       {BuiltinOptions{ContextSensitiveOptions{}}});
4926 }
4927 
4928 TEST(TransferTest, ContextSensitiveReturnArg) {
4929   std::string Code = R"(
4930     bool GiveBool();
4931     bool GiveBack(bool Arg) { return Arg; }
4932 
4933     void target() {
4934       bool Foo = GiveBool();
4935       bool Bar = GiveBack(Foo);
4936       bool Baz = Foo == Bar;
4937       // [[p]]
4938     }
4939   )";
4940   runDataflow(
4941       Code,
4942       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4943          ASTContext &ASTCtx) {
4944         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4945         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4946 
4947         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4948         ASSERT_THAT(BazDecl, NotNull());
4949 
4950         auto &BazVal = *cast<BoolValue>(Env.getValue(*BazDecl));
4951         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
4952       },
4953       {BuiltinOptions{ContextSensitiveOptions{}}});
4954 }
4955 
4956 TEST(TransferTest, ContextSensitiveReturnInt) {
4957   std::string Code = R"(
4958     int identity(int x) { return x; }
4959 
4960     void target() {
4961       int y = identity(42);
4962       // [[p]]
4963     }
4964   )";
4965   runDataflow(
4966       Code,
4967       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4968          ASTContext &ASTCtx) {
4969         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4970         // This just tests that the analysis doesn't crash.
4971       },
4972       {BuiltinOptions{ContextSensitiveOptions{}}});
4973 }
4974 
4975 TEST(TransferTest, ContextSensitiveMethodLiteral) {
4976   std::string Code = R"(
4977     class MyClass {
4978     public:
4979       bool giveBool() { return true; }
4980     };
4981 
4982     void target() {
4983       MyClass MyObj;
4984       bool Foo = MyObj.giveBool();
4985       // [[p]]
4986     }
4987   )";
4988   runDataflow(
4989       Code,
4990       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4991          ASTContext &ASTCtx) {
4992         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4993         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4994 
4995         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4996         ASSERT_THAT(FooDecl, NotNull());
4997 
4998         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
4999         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5000       },
5001       {BuiltinOptions{ContextSensitiveOptions{}}});
5002 }
5003 
5004 TEST(TransferTest, ContextSensitiveMethodGetter) {
5005   std::string Code = R"(
5006     class MyClass {
5007     public:
5008       bool getField() { return Field; }
5009 
5010       bool Field;
5011     };
5012 
5013     void target() {
5014       MyClass MyObj;
5015       MyObj.Field = true;
5016       bool Foo = MyObj.getField();
5017       // [[p]]
5018     }
5019   )";
5020   runDataflow(
5021       Code,
5022       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5023          ASTContext &ASTCtx) {
5024         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5025         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5026 
5027         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5028         ASSERT_THAT(FooDecl, NotNull());
5029 
5030         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5031         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5032       },
5033       {BuiltinOptions{ContextSensitiveOptions{}}});
5034 }
5035 
5036 TEST(TransferTest, ContextSensitiveMethodSetter) {
5037   std::string Code = R"(
5038     class MyClass {
5039     public:
5040       void setField(bool Val) { Field = Val; }
5041 
5042       bool Field;
5043     };
5044 
5045     void target() {
5046       MyClass MyObj;
5047       MyObj.setField(true);
5048       bool Foo = MyObj.Field;
5049       // [[p]]
5050     }
5051   )";
5052   runDataflow(
5053       Code,
5054       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5055          ASTContext &ASTCtx) {
5056         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5057         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5058 
5059         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5060         ASSERT_THAT(FooDecl, NotNull());
5061 
5062         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5063         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5064       },
5065       {BuiltinOptions{ContextSensitiveOptions{}}});
5066 }
5067 
5068 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
5069   std::string Code = R"(
5070     class MyClass {
5071     public:
5072       bool getField() { return Field; }
5073       void setField(bool Val) { Field = Val; }
5074 
5075     private:
5076       bool Field;
5077     };
5078 
5079     void target() {
5080       MyClass MyObj;
5081       MyObj.setField(true);
5082       bool Foo = MyObj.getField();
5083       // [[p]]
5084     }
5085   )";
5086   runDataflow(
5087       Code,
5088       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5089          ASTContext &ASTCtx) {
5090         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5091         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5092 
5093         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5094         ASSERT_THAT(FooDecl, NotNull());
5095 
5096         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5097         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5098       },
5099       {BuiltinOptions{ContextSensitiveOptions{}}});
5100 }
5101 
5102 
5103 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
5104   std::string Code = R"(
5105     class MyClass {
5106     public:
5107       void Inner() { MyField = true; }
5108       void Outer() { Inner(); }
5109 
5110       bool MyField;
5111     };
5112 
5113     void target() {
5114       MyClass MyObj;
5115       MyObj.Outer();
5116       bool Foo = MyObj.MyField;
5117       // [[p]]
5118     }
5119   )";
5120   runDataflow(
5121       Code,
5122       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5123          ASTContext &ASTCtx) {
5124         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5125         ;
5126         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5127 
5128         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5129         ASSERT_THAT(FooDecl, NotNull());
5130 
5131         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5132         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5133       },
5134       {BuiltinOptions{ContextSensitiveOptions{}}});
5135 }
5136 
5137 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
5138   std::string Code = R"(
5139     class MyClass {
5140     public:
5141       bool Inner() { return MyField; }
5142       bool Outer() { return Inner(); }
5143 
5144       bool MyField;
5145     };
5146 
5147     void target() {
5148       MyClass MyObj;
5149       MyObj.MyField = true;
5150       bool Foo = MyObj.Outer();
5151       // [[p]]
5152     }
5153   )";
5154   runDataflow(
5155       Code,
5156       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5157          ASTContext &ASTCtx) {
5158         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5159         ;
5160         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5161 
5162         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5163         ASSERT_THAT(FooDecl, NotNull());
5164 
5165         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5166         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5167       },
5168       {BuiltinOptions{ContextSensitiveOptions{}}});
5169 }
5170 
5171 TEST(TransferTest, ContextSensitiveConstructorBody) {
5172   std::string Code = R"(
5173     class MyClass {
5174     public:
5175       MyClass() { MyField = true; }
5176 
5177       bool MyField;
5178     };
5179 
5180     void target() {
5181       MyClass MyObj;
5182       bool Foo = MyObj.MyField;
5183       // [[p]]
5184     }
5185   )";
5186   runDataflow(
5187       Code,
5188       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5189          ASTContext &ASTCtx) {
5190         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5191         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5192 
5193         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5194         ASSERT_THAT(FooDecl, NotNull());
5195 
5196         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5197         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5198       },
5199       {BuiltinOptions{ContextSensitiveOptions{}}});
5200 }
5201 
5202 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
5203   std::string Code = R"(
5204     class MyClass {
5205     public:
5206       MyClass() : MyField(true) {}
5207 
5208       bool MyField;
5209     };
5210 
5211     void target() {
5212       MyClass MyObj;
5213       bool Foo = MyObj.MyField;
5214       // [[p]]
5215     }
5216   )";
5217   runDataflow(
5218       Code,
5219       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5220          ASTContext &ASTCtx) {
5221         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5222         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5223 
5224         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5225         ASSERT_THAT(FooDecl, NotNull());
5226 
5227         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5228         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5229       },
5230       {BuiltinOptions{ContextSensitiveOptions{}}});
5231 }
5232 
5233 TEST(TransferTest, ContextSensitiveConstructorDefault) {
5234   std::string Code = R"(
5235     class MyClass {
5236     public:
5237       MyClass() = default;
5238 
5239       bool MyField = true;
5240     };
5241 
5242     void target() {
5243       MyClass MyObj;
5244       bool Foo = MyObj.MyField;
5245       // [[p]]
5246     }
5247   )";
5248   runDataflow(
5249       Code,
5250       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5251          ASTContext &ASTCtx) {
5252         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5253         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5254 
5255         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5256         ASSERT_THAT(FooDecl, NotNull());
5257 
5258         auto &FooVal = *cast<BoolValue>(Env.getValue(*FooDecl));
5259         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5260       },
5261       {BuiltinOptions{ContextSensitiveOptions{}}});
5262 }
5263 
5264 TEST(TransferTest, UnnamedBitfieldInitializer) {
5265   std::string Code = R"(
5266     struct B {};
5267     struct A {
5268       unsigned a;
5269       unsigned : 4;
5270       unsigned c;
5271       B b;
5272     };
5273     void target() {
5274       A a = {};
5275       A test = a;
5276       (void)test.c;
5277     }
5278   )";
5279   runDataflow(
5280       Code,
5281       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5282          ASTContext &ASTCtx) {
5283         // This doesn't need a body because this test was crashing the framework
5284         // before handling correctly Unnamed bitfields in `InitListExpr`.
5285       });
5286 }
5287 
5288 // Repro for a crash that used to occur with chained short-circuiting logical
5289 // operators.
5290 TEST(TransferTest, ChainedLogicalOps) {
5291   std::string Code = R"(
5292     bool target() {
5293       bool b = true || false || false || false;
5294       // [[p]]
5295       return b;
5296     }
5297   )";
5298   runDataflow(
5299       Code,
5300       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5301          ASTContext &ASTCtx) {
5302         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5303         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b");
5304         EXPECT_TRUE(Env.flowConditionImplies(B));
5305       });
5306 }
5307 
5308 // Repro for a crash that used to occur when we call a `noreturn` function
5309 // within one of the operands of a `&&` or `||` operator.
5310 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
5311   std::string Code = R"(
5312     __attribute__((noreturn)) int doesnt_return();
5313     bool some_condition();
5314     void target(bool b1, bool b2) {
5315       // Neither of these should crash. In addition, if we don't terminate the
5316       // program, we know that the operators need to trigger the short-circuit
5317       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
5318       // will be true.
5319       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
5320       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
5321 
5322       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
5323       // entire expression unreachable. So we know that in both of the following
5324       // cases, if `target()` terminates, the `else` branch was taken.
5325       bool NoreturnOnLhsMakesAndUnreachable = false;
5326       if (some_condition())
5327          doesnt_return() > 0 && some_condition();
5328       else
5329          NoreturnOnLhsMakesAndUnreachable = true;
5330 
5331       bool NoreturnOnLhsMakesOrUnreachable = false;
5332       if (some_condition())
5333          doesnt_return() > 0 || some_condition();
5334       else
5335          NoreturnOnLhsMakesOrUnreachable = true;
5336 
5337       // [[p]]
5338     }
5339   )";
5340   runDataflow(
5341       Code,
5342       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5343          ASTContext &ASTCtx) {
5344         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5345         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5346 
5347         // Check that [[p]] is reachable with a non-false flow condition.
5348         EXPECT_FALSE(Env.flowConditionImplies(Env.getBoolLiteralValue(false)));
5349 
5350         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1");
5351         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(B1)));
5352 
5353         auto &NoreturnOnRhsOfAnd =
5354             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd");
5355         EXPECT_TRUE(Env.flowConditionImplies(Env.makeNot(NoreturnOnRhsOfAnd)));
5356 
5357         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2");
5358         EXPECT_TRUE(Env.flowConditionImplies(B2));
5359 
5360         auto &NoreturnOnRhsOfOr =
5361             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr");
5362         EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnRhsOfOr));
5363 
5364         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
5365             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable");
5366         EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesAndUnreachable));
5367 
5368         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
5369             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable");
5370         EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesOrUnreachable));
5371       });
5372 }
5373 
5374 TEST(TransferTest, NewExpressions) {
5375   std::string Code = R"(
5376     void target() {
5377       int *p = new int(42);
5378       // [[after_new]]
5379     }
5380   )";
5381   runDataflow(
5382       Code,
5383       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5384          ASTContext &ASTCtx) {
5385         const Environment &Env =
5386             getEnvironmentAtAnnotation(Results, "after_new");
5387 
5388         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5389 
5390         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
5391       });
5392 }
5393 
5394 TEST(TransferTest, NewExpressions_Structs) {
5395   std::string Code = R"(
5396     struct Inner {
5397       int InnerField;
5398     };
5399 
5400     struct Outer {
5401       Inner OuterField;
5402     };
5403 
5404     void target() {
5405       Outer *p = new Outer;
5406       // Access the fields to make sure the analysis actually generates children
5407       // for them in the `AggregateStorageLoc` and `StructValue`.
5408       p->OuterField.InnerField;
5409       // [[after_new]]
5410     }
5411   )";
5412   runDataflow(
5413       Code,
5414       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5415          ASTContext &ASTCtx) {
5416         const Environment &Env =
5417             getEnvironmentAtAnnotation(Results, "after_new");
5418 
5419         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
5420         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
5421 
5422         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5423 
5424         auto &OuterLoc = cast<AggregateStorageLocation>(P.getPointeeLoc());
5425         auto &OuterFieldLoc =
5426             cast<AggregateStorageLocation>(OuterLoc.getChild(*OuterField));
5427         auto &InnerFieldLoc = OuterFieldLoc.getChild(*InnerField);
5428 
5429         // Values for the struct and all fields exist after the new.
5430         EXPECT_THAT(Env.getValue(OuterLoc), NotNull());
5431         EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull());
5432         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
5433       });
5434 }
5435 
5436 TEST(TransferTest, FunctionToPointerDecayHasValue) {
5437   std::string Code = R"(
5438     struct A { static void static_member_func(); };
5439     void target() {
5440       // To check that we're treating function-to-pointer decay correctly,
5441       // create two pointers, then verify they refer to the same storage
5442       // location.
5443       // We need to do the test this way because even if an initializer (in this
5444       // case, the function-to-pointer decay) does not create a value, we still
5445       // create a value for the variable.
5446       void (*non_member_p1)() = target;
5447       void (*non_member_p2)() = target;
5448 
5449       // Do the same thing but for a static member function.
5450       void (*member_p1)() = A::static_member_func;
5451       void (*member_p2)() = A::static_member_func;
5452       // [[p]]
5453     }
5454   )";
5455   runDataflow(
5456       Code,
5457       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5458          ASTContext &ASTCtx) {
5459         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5460 
5461         auto &NonMemberP1 =
5462             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
5463         auto &NonMemberP2 =
5464             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
5465         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
5466 
5467         auto &MemberP1 =
5468             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
5469         auto &MemberP2 =
5470             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
5471         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
5472       });
5473 }
5474 
5475 // Check that the pointer that a builtin function decays to is associated with
5476 // a value.
5477 TEST(TransferTest, BuiltinFunctionModeled) {
5478   std::string Code = R"(
5479     void target() {
5480       __builtin_expect(0, 0);
5481       // [[p]]
5482     }
5483   )";
5484   runDataflow(
5485       Code,
5486       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5487          ASTContext &ASTCtx) {
5488         using ast_matchers::selectFirst;
5489         using ast_matchers::match;
5490         using ast_matchers::traverse;
5491         using ast_matchers::implicitCastExpr;
5492         using ast_matchers::hasCastKind;
5493 
5494         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5495 
5496         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
5497             "implicit_cast",
5498             match(traverse(TK_AsIs,
5499                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
5500                                .bind("implicit_cast")),
5501                   ASTCtx));
5502 
5503         ASSERT_THAT(ImplicitCast, NotNull());
5504         EXPECT_THAT(Env.getValueStrict(*ImplicitCast), NotNull());
5505       });
5506 }
5507 
5508 // Check that fields of anonymous records are modeled.
5509 TEST(TransferTest, AnonymousStruct) {
5510   std::string Code = R"(
5511     struct S {
5512       struct {
5513         bool b;
5514       };
5515     };
5516     void target() {
5517       S s;
5518       s.b = true;
5519       // [[p]]
5520     }
5521   )";
5522   runDataflow(
5523       Code,
5524       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5525          ASTContext &ASTCtx) {
5526         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5527         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5528         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
5529         const IndirectFieldDecl *IndirectField =
5530             findIndirectFieldDecl(ASTCtx, "b");
5531 
5532         auto *S =
5533             cast<AggregateStorageLocation>(Env.getStorageLocation(*SDecl));
5534         auto &AnonStruct = cast<AggregateStorageLocation>(
5535             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
5536 
5537         auto *B = cast<BoolValue>(Env.getValue(AnonStruct.getChild(*BDecl)));
5538         ASSERT_TRUE(Env.flowConditionImplies(*B));
5539       });
5540 }
5541 
5542 TEST(TransferTest, AnonymousStructWithInitializer) {
5543   std::string Code = R"(
5544     struct target {
5545       target() {
5546         (void)0;
5547         // [[p]]
5548       }
5549       struct {
5550         bool b = true;
5551       };
5552     };
5553   )";
5554   runDataflow(
5555       Code,
5556       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5557          ASTContext &ASTCtx) {
5558         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5559         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
5560         const IndirectFieldDecl *IndirectField =
5561             findIndirectFieldDecl(ASTCtx, "b");
5562 
5563         auto *ThisLoc =
5564             cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation());
5565         auto &AnonStruct = cast<AggregateStorageLocation>(ThisLoc->getChild(
5566             *cast<ValueDecl>(IndirectField->chain().front())));
5567 
5568         auto *B = cast<BoolValue>(Env.getValue(AnonStruct.getChild(*BDecl)));
5569         ASSERT_TRUE(Env.flowConditionImplies(*B));
5570       });
5571 }
5572 
5573 TEST(TransferTest, AnonymousStructWithReferenceField) {
5574   std::string Code = R"(
5575     int global_i = 0;
5576     struct target {
5577       target() {
5578         (void)0;
5579         // [[p]]
5580       }
5581       struct {
5582         int &i = global_i;
5583       };
5584     };
5585   )";
5586   runDataflow(
5587       Code,
5588       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5589          ASTContext &ASTCtx) {
5590         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5591         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
5592         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
5593         const IndirectFieldDecl *IndirectField =
5594             findIndirectFieldDecl(ASTCtx, "i");
5595 
5596         auto *ThisLoc =
5597             cast<AggregateStorageLocation>(Env.getThisPointeeStorageLocation());
5598         auto &AnonStruct = cast<AggregateStorageLocation>(ThisLoc->getChild(
5599             *cast<ValueDecl>(IndirectField->chain().front())));
5600 
5601         auto *RefVal =
5602             cast<ReferenceValue>(Env.getValue(AnonStruct.getChild(*IDecl)));
5603 
5604         ASSERT_EQ(&RefVal->getReferentLoc(),
5605                   Env.getStorageLocation(*GlobalIDecl));
5606       });
5607 }
5608 
5609 } // namespace
5610