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