xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision 9ecdbe3855a8048989a507ff8d470aee4d407589)
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 &) {
1422                 return NoopAnalysis(C, /*ApplyBuiltinTransfer=*/true);
1423               })
1424               .withASTBuildArgs(
1425                   {"-fsyntax-only", "-fno-delayed-template-parsing",
1426                    "-std=" + std::string(LangStandard::getLangStandardForKind(
1427                                              LangStandard::lang_cxx17)
1428                                              .getName())}),
1429           /*VerifyResults=*/
1430           [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1431              const AnalysisOutputs &) {
1432             // Regression test to verify that base-class initializers do not
1433             // trigger an assertion. If we add support for such initializers in
1434             // the future, we can expand this test to check more specific
1435             // properties.
1436             EXPECT_THAT(Results.keys(), UnorderedElementsAre("p"));
1437           }),
1438       llvm::Succeeded());
1439 }
1440 
1441 TEST(TransferTest, ReferenceMember) {
1442   std::string Code = R"(
1443     struct A {
1444       int &Bar;
1445     };
1446 
1447     void target(A Foo) {
1448       int Baz = Foo.Bar;
1449       // [[p]]
1450     }
1451   )";
1452   runDataflow(
1453       Code,
1454       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1455          ASTContext &ASTCtx) {
1456         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1457         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1458 
1459         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1460         ASSERT_THAT(FooDecl, NotNull());
1461 
1462         ASSERT_TRUE(FooDecl->getType()->isStructureType());
1463         auto FooFields = FooDecl->getType()->getAsRecordDecl()->fields();
1464 
1465         FieldDecl *BarDecl = nullptr;
1466         for (FieldDecl *Field : FooFields) {
1467           if (Field->getNameAsString() == "Bar") {
1468             BarDecl = Field;
1469           } else {
1470             FAIL() << "Unexpected field: " << Field->getNameAsString();
1471           }
1472         }
1473         ASSERT_THAT(BarDecl, NotNull());
1474 
1475         const auto *FooLoc =
1476             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1477         const auto *BarReferentVal =
1478             cast<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env));
1479 
1480         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1481         ASSERT_THAT(BazDecl, NotNull());
1482 
1483         EXPECT_EQ(Env.getValue(*BazDecl), BarReferentVal);
1484       });
1485 }
1486 
1487 TEST(TransferTest, StructThisMember) {
1488   std::string Code = R"(
1489     struct A {
1490       int Bar;
1491 
1492       struct B {
1493         int Baz;
1494       };
1495 
1496       B Qux;
1497 
1498       void target() {
1499         int Foo = Bar;
1500         int Quux = Qux.Baz;
1501         // [[p]]
1502       }
1503     };
1504   )";
1505   runDataflow(
1506       Code,
1507       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1508          ASTContext &ASTCtx) {
1509         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1510         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1511 
1512         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1513         ASSERT_THAT(ThisLoc, NotNull());
1514 
1515         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1516         ASSERT_THAT(BarDecl, NotNull());
1517 
1518         const auto *BarLoc =
1519             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1520         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1521 
1522         const Value *BarVal = Env.getValue(*BarLoc);
1523         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1524 
1525         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1526         ASSERT_THAT(FooDecl, NotNull());
1527         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1528 
1529         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1530         ASSERT_THAT(QuxDecl, NotNull());
1531 
1532         ASSERT_TRUE(QuxDecl->getType()->isStructureType());
1533         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1534 
1535         FieldDecl *BazDecl = nullptr;
1536         for (FieldDecl *Field : QuxFields) {
1537           if (Field->getNameAsString() == "Baz") {
1538             BazDecl = Field;
1539           } else {
1540             FAIL() << "Unexpected field: " << Field->getNameAsString();
1541           }
1542         }
1543         ASSERT_THAT(BazDecl, NotNull());
1544 
1545         const auto *QuxLoc =
1546             cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl));
1547         EXPECT_THAT(dyn_cast<RecordValue>(Env.getValue(*QuxLoc)), NotNull());
1548 
1549         const auto *BazVal =
1550             cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env));
1551 
1552         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1553         ASSERT_THAT(QuuxDecl, NotNull());
1554         EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal);
1555       });
1556 }
1557 
1558 TEST(TransferTest, ClassThisMember) {
1559   std::string Code = R"(
1560     class A {
1561       int Bar;
1562 
1563       class B {
1564       public:
1565         int Baz;
1566       };
1567 
1568       B Qux;
1569 
1570       void target() {
1571         int Foo = Bar;
1572         int Quux = Qux.Baz;
1573         // [[p]]
1574       }
1575     };
1576   )";
1577   runDataflow(
1578       Code,
1579       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1580          ASTContext &ASTCtx) {
1581         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1582         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1583 
1584         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1585 
1586         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1587         ASSERT_THAT(BarDecl, NotNull());
1588 
1589         const auto *BarLoc =
1590             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1591         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1592 
1593         const Value *BarVal = Env.getValue(*BarLoc);
1594         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1595 
1596         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1597         ASSERT_THAT(FooDecl, NotNull());
1598         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1599 
1600         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1601         ASSERT_THAT(QuxDecl, NotNull());
1602 
1603         ASSERT_TRUE(QuxDecl->getType()->isClassType());
1604         auto QuxFields = QuxDecl->getType()->getAsRecordDecl()->fields();
1605 
1606         FieldDecl *BazDecl = nullptr;
1607         for (FieldDecl *Field : QuxFields) {
1608           if (Field->getNameAsString() == "Baz") {
1609             BazDecl = Field;
1610           } else {
1611             FAIL() << "Unexpected field: " << Field->getNameAsString();
1612           }
1613         }
1614         ASSERT_THAT(BazDecl, NotNull());
1615 
1616         const auto *QuxLoc =
1617             cast<RecordStorageLocation>(ThisLoc->getChild(*QuxDecl));
1618         EXPECT_THAT(dyn_cast<RecordValue>(Env.getValue(*QuxLoc)), NotNull());
1619 
1620         const auto *BazVal =
1621             cast<IntegerValue>(getFieldValue(QuxLoc, *BazDecl, Env));
1622 
1623         const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
1624         ASSERT_THAT(QuuxDecl, NotNull());
1625         EXPECT_EQ(Env.getValue(*QuuxDecl), BazVal);
1626       });
1627 }
1628 
1629 TEST(TransferTest, UnionThisMember) {
1630   std::string Code = R"(
1631     union A {
1632       int Foo;
1633       int Bar;
1634 
1635       void target() {
1636         A a;
1637         // Mention the fields to ensure they're included in the analysis.
1638         (void)a.Foo;
1639         (void)a.Bar;
1640         // [[p]]
1641       }
1642     };
1643   )";
1644   runDataflow(
1645       Code,
1646       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1647          ASTContext &ASTCtx) {
1648         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1649         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1650 
1651         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1652         ASSERT_THAT(ThisLoc, NotNull());
1653 
1654         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1655         ASSERT_THAT(FooDecl, NotNull());
1656 
1657         const auto *FooLoc =
1658             cast<ScalarStorageLocation>(ThisLoc->getChild(*FooDecl));
1659         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
1660 
1661         const Value *FooVal = Env.getValue(*FooLoc);
1662         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
1663 
1664         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1665         ASSERT_THAT(BarDecl, NotNull());
1666 
1667         const auto *BarLoc =
1668             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1669         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1670 
1671         const Value *BarVal = Env.getValue(*BarLoc);
1672         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1673       });
1674 }
1675 
1676 TEST(TransferTest, StructThisInLambda) {
1677   std::string ThisCaptureCode = R"(
1678     struct A {
1679       void frob() {
1680         [this]() {
1681           int Foo = Bar;
1682           // [[p1]]
1683         }();
1684       }
1685 
1686       int Bar;
1687     };
1688   )";
1689   runDataflow(
1690       ThisCaptureCode,
1691       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1692          ASTContext &ASTCtx) {
1693         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1"));
1694         const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
1695 
1696         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1697         ASSERT_THAT(ThisLoc, NotNull());
1698 
1699         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1700         ASSERT_THAT(BarDecl, NotNull());
1701 
1702         const auto *BarLoc =
1703             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1704         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1705 
1706         const Value *BarVal = Env.getValue(*BarLoc);
1707         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1708 
1709         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1710         ASSERT_THAT(FooDecl, NotNull());
1711         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1712       },
1713       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1714 
1715   std::string RefCaptureDefaultCode = R"(
1716     struct A {
1717       void frob() {
1718         [&]() {
1719           int Foo = Bar;
1720           // [[p2]]
1721         }();
1722       }
1723 
1724       int Bar;
1725     };
1726   )";
1727   runDataflow(
1728       RefCaptureDefaultCode,
1729       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1730          ASTContext &ASTCtx) {
1731         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p2"));
1732         const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
1733 
1734         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1735         ASSERT_THAT(ThisLoc, NotNull());
1736 
1737         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1738         ASSERT_THAT(BarDecl, NotNull());
1739 
1740         const auto *BarLoc =
1741             cast<ScalarStorageLocation>(ThisLoc->getChild(*BarDecl));
1742         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
1743 
1744         const Value *BarVal = Env.getValue(*BarLoc);
1745         ASSERT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
1746 
1747         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1748         ASSERT_THAT(FooDecl, NotNull());
1749         EXPECT_EQ(Env.getValue(*FooDecl), BarVal);
1750       },
1751       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1752 
1753   std::string FreeFunctionLambdaCode = R"(
1754     void foo() {
1755       int Bar;
1756       [&]() {
1757         int Foo = Bar;
1758         // [[p3]]
1759       }();
1760     }
1761   )";
1762   runDataflow(
1763       FreeFunctionLambdaCode,
1764       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1765          ASTContext &ASTCtx) {
1766         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p3"));
1767         const Environment &Env = getEnvironmentAtAnnotation(Results, "p3");
1768 
1769         EXPECT_THAT(Env.getThisPointeeStorageLocation(), IsNull());
1770       },
1771       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator()");
1772 }
1773 
1774 TEST(TransferTest, ConstructorInitializer) {
1775   std::string Code = R"(
1776     struct target {
1777       int Bar;
1778 
1779       target(int Foo) : Bar(Foo) {
1780         int Qux = Bar;
1781         // [[p]]
1782       }
1783     };
1784   )";
1785   runDataflow(
1786       Code,
1787       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1788          ASTContext &ASTCtx) {
1789         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1790         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1791 
1792         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1793         ASSERT_THAT(ThisLoc, NotNull());
1794 
1795         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1796         ASSERT_THAT(FooDecl, NotNull());
1797 
1798         const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl));
1799 
1800         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1801         ASSERT_THAT(QuxDecl, NotNull());
1802         EXPECT_EQ(Env.getValue(*QuxDecl), FooVal);
1803       });
1804 }
1805 
1806 TEST(TransferTest, DefaultInitializer) {
1807   std::string Code = R"(
1808     struct target {
1809       int Bar;
1810       int Baz = Bar;
1811 
1812       target(int Foo) : Bar(Foo) {
1813         int Qux = Baz;
1814         // [[p]]
1815       }
1816     };
1817   )";
1818   runDataflow(
1819       Code,
1820       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1821          ASTContext &ASTCtx) {
1822         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1823         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1824 
1825         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1826         ASSERT_THAT(ThisLoc, NotNull());
1827 
1828         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1829         ASSERT_THAT(FooDecl, NotNull());
1830 
1831         const auto *FooVal = cast<IntegerValue>(Env.getValue(*FooDecl));
1832 
1833         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1834         ASSERT_THAT(QuxDecl, NotNull());
1835         EXPECT_EQ(Env.getValue(*QuxDecl), FooVal);
1836       });
1837 }
1838 
1839 TEST(TransferTest, DefaultInitializerReference) {
1840   std::string Code = R"(
1841     struct target {
1842       int &Bar;
1843       int &Baz = Bar;
1844 
1845       target(int &Foo) : Bar(Foo) {
1846         int &Qux = Baz;
1847         // [[p]]
1848       }
1849     };
1850   )";
1851   runDataflow(
1852       Code,
1853       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1854          ASTContext &ASTCtx) {
1855         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1856         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1857 
1858         const auto *ThisLoc = Env.getThisPointeeStorageLocation();
1859         ASSERT_THAT(ThisLoc, NotNull());
1860 
1861         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1862         ASSERT_THAT(FooDecl, NotNull());
1863 
1864         const auto *FooLoc = Env.getStorageLocation(*FooDecl);
1865 
1866         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
1867         ASSERT_THAT(QuxDecl, NotNull());
1868 
1869         const auto *QuxLoc = Env.getStorageLocation(*QuxDecl);
1870         EXPECT_EQ(QuxLoc, FooLoc);
1871       });
1872 }
1873 
1874 TEST(TransferTest, TemporaryObject) {
1875   std::string Code = R"(
1876     struct A {
1877       int Bar;
1878     };
1879 
1880     void target() {
1881       A Foo = A();
1882       (void)Foo.Bar;
1883       // [[p]]
1884     }
1885   )";
1886   runDataflow(
1887       Code,
1888       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1889          ASTContext &ASTCtx) {
1890         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1891         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1892 
1893         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1894         ASSERT_THAT(FooDecl, NotNull());
1895 
1896         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1897         ASSERT_THAT(BarDecl, NotNull());
1898 
1899         const auto *FooLoc =
1900             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1901         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
1902       });
1903 }
1904 
1905 TEST(TransferTest, ElidableConstructor) {
1906   // This test is effectively the same as TransferTest.TemporaryObject, but
1907   // the code is compiled as C++ 14.
1908   std::string Code = R"(
1909     struct A {
1910       int Bar;
1911     };
1912 
1913     void target() {
1914       A Foo = A();
1915       (void)Foo.Bar;
1916       // [[p]]
1917     }
1918   )";
1919   runDataflow(
1920       Code,
1921       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1922          ASTContext &ASTCtx) {
1923         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
1924         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
1925 
1926         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1927         ASSERT_THAT(FooDecl, NotNull());
1928 
1929         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1930         ASSERT_THAT(BarDecl, NotNull());
1931 
1932         const auto *FooLoc =
1933             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
1934         EXPECT_TRUE(isa<IntegerValue>(getFieldValue(FooLoc, *BarDecl, Env)));
1935       },
1936       LangStandard::lang_cxx14);
1937 }
1938 
1939 TEST(TransferTest, AssignmentOperator) {
1940   std::string Code = R"(
1941     struct A {
1942       int Baz;
1943     };
1944 
1945     void target() {
1946       A Foo = { 1 };
1947       A Bar = { 2 };
1948       // [[p1]]
1949       Foo = Bar;
1950       // [[p2]]
1951       Foo.Baz = 3;
1952       // [[p3]]
1953     }
1954   )";
1955   runDataflow(
1956       Code,
1957       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
1958          ASTContext &ASTCtx) {
1959         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
1960         ASSERT_THAT(FooDecl, NotNull());
1961 
1962         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
1963         ASSERT_THAT(BarDecl, NotNull());
1964 
1965         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
1966         ASSERT_THAT(BazDecl, NotNull());
1967 
1968         // Before copy assignment.
1969         {
1970           const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
1971 
1972           const auto *FooLoc1 =
1973               cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
1974           const auto *BarLoc1 =
1975               cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
1976           EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
1977 
1978           const auto *FooBazVal1 =
1979               cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1));
1980           const auto *BarBazVal1 =
1981               cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1));
1982           EXPECT_NE(FooBazVal1, BarBazVal1);
1983         }
1984 
1985         // After copy assignment.
1986         {
1987           const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
1988 
1989           const auto *FooLoc2 =
1990               cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
1991           const auto *BarLoc2 =
1992               cast<RecordStorageLocation>(Env2.getStorageLocation(*BarDecl));
1993 
1994           const auto *FooVal2 = cast<RecordValue>(Env2.getValue(*FooLoc2));
1995           const auto *BarVal2 = cast<RecordValue>(Env2.getValue(*BarLoc2));
1996           EXPECT_NE(FooVal2, BarVal2);
1997 
1998           EXPECT_TRUE(recordsEqual(*FooLoc2, *BarLoc2, Env2));
1999 
2000           const auto *FooBazVal2 =
2001               cast<IntegerValue>(getFieldValue(FooLoc2, *BazDecl, Env2));
2002           const auto *BarBazVal2 =
2003               cast<IntegerValue>(getFieldValue(BarLoc2, *BazDecl, Env2));
2004           EXPECT_EQ(FooBazVal2, BarBazVal2);
2005         }
2006 
2007         // After value update.
2008         {
2009           const Environment &Env3 = getEnvironmentAtAnnotation(Results, "p3");
2010 
2011           const auto *FooLoc3 =
2012               cast<RecordStorageLocation>(Env3.getStorageLocation(*FooDecl));
2013           const auto *BarLoc3 =
2014               cast<RecordStorageLocation>(Env3.getStorageLocation(*BarDecl));
2015           EXPECT_FALSE(recordsEqual(*FooLoc3, *BarLoc3, Env3));
2016 
2017           const auto *FooBazVal3 =
2018               cast<IntegerValue>(getFieldValue(FooLoc3, *BazDecl, Env3));
2019           const auto *BarBazVal3 =
2020               cast<IntegerValue>(getFieldValue(BarLoc3, *BazDecl, Env3));
2021           EXPECT_NE(FooBazVal3, BarBazVal3);
2022         }
2023       });
2024 }
2025 
2026 TEST(TransferTest, AssignmentOperatorFromCallResult) {
2027   std::string Code = R"(
2028     struct A {};
2029     A ReturnA();
2030 
2031     void target() {
2032       A MyA;
2033       MyA = ReturnA();
2034     }
2035   )";
2036   runDataflow(
2037       Code,
2038       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2039          ASTContext &ASTCtx) {
2040         // As of this writing, we don't produce a `Value` for the call
2041         // `ReturnA()`. The only condition we're testing for is that the
2042         // analysis should not crash in this case.
2043       });
2044 }
2045 
2046 TEST(TransferTest, CopyConstructor) {
2047   std::string Code = R"(
2048     struct A {
2049       int Baz;
2050     };
2051 
2052     void target() {
2053       A Foo = { 1 };
2054       A Bar = Foo;
2055       // [[after_copy]]
2056       Foo.Baz = 2;
2057       // [[after_update]]
2058     }
2059   )";
2060   runDataflow(
2061       Code,
2062       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2063          ASTContext &ASTCtx) {
2064         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2065         ASSERT_THAT(FooDecl, NotNull());
2066 
2067         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2068         ASSERT_THAT(BarDecl, NotNull());
2069 
2070         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2071         ASSERT_THAT(BazDecl, NotNull());
2072 
2073         // after_copy
2074         {
2075           const Environment &Env =
2076               getEnvironmentAtAnnotation(Results, "after_copy");
2077 
2078           const auto *FooLoc =
2079               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2080           const auto *BarLoc =
2081               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2082 
2083           // `Foo` and `Bar` have different `RecordValue`s associated with them.
2084           const auto *FooVal = cast<RecordValue>(Env.getValue(*FooLoc));
2085           const auto *BarVal = cast<RecordValue>(Env.getValue(*BarLoc));
2086           EXPECT_NE(FooVal, BarVal);
2087 
2088           // But the records compare equal.
2089           EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2090 
2091           // In particular, the value of `Baz` in both records is the same.
2092           const auto *FooBazVal =
2093               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2094           const auto *BarBazVal =
2095               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2096           EXPECT_EQ(FooBazVal, BarBazVal);
2097         }
2098 
2099         // after_update
2100         {
2101           const Environment &Env =
2102               getEnvironmentAtAnnotation(Results, "after_update");
2103 
2104           const auto *FooLoc =
2105               cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2106           const auto *BarLoc =
2107               cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2108 
2109           EXPECT_FALSE(recordsEqual(*FooLoc, *BarLoc, Env));
2110 
2111           const auto *FooBazVal =
2112               cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2113           const auto *BarBazVal =
2114               cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2115           EXPECT_NE(FooBazVal, BarBazVal);
2116         }
2117       });
2118 }
2119 
2120 TEST(TransferTest, CopyConstructorWithDefaultArgument) {
2121   std::string Code = R"(
2122     struct A {
2123       int Baz;
2124       A() = default;
2125       A(const A& a, bool def = true) { Baz = a.Baz; }
2126     };
2127 
2128     void target() {
2129       A Foo;
2130       (void)Foo.Baz;
2131       A Bar = Foo;
2132       // [[p]]
2133     }
2134   )";
2135   runDataflow(
2136       Code,
2137       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2138          ASTContext &ASTCtx) {
2139         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2140         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2141 
2142         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2143         ASSERT_THAT(FooDecl, NotNull());
2144 
2145         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2146         ASSERT_THAT(BarDecl, NotNull());
2147 
2148         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2149         ASSERT_THAT(BazDecl, NotNull());
2150 
2151         const auto *FooLoc =
2152             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2153         const auto *BarLoc =
2154             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2155         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2156 
2157         const auto *FooBazVal =
2158             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2159         const auto *BarBazVal =
2160             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2161         EXPECT_EQ(FooBazVal, BarBazVal);
2162       });
2163 }
2164 
2165 TEST(TransferTest, CopyConstructorWithParens) {
2166   std::string Code = R"(
2167     struct A {
2168       int Baz;
2169     };
2170 
2171     void target() {
2172       A Foo;
2173       (void)Foo.Baz;
2174       A Bar((A(Foo)));
2175       // [[p]]
2176     }
2177   )";
2178   runDataflow(
2179       Code,
2180       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2181          ASTContext &ASTCtx) {
2182         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2183         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2184 
2185         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2186         ASSERT_THAT(FooDecl, NotNull());
2187 
2188         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2189         ASSERT_THAT(BarDecl, NotNull());
2190 
2191         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2192         ASSERT_THAT(BazDecl, NotNull());
2193 
2194         const auto *FooLoc =
2195             cast<RecordStorageLocation>(Env.getStorageLocation(*FooDecl));
2196         const auto *BarLoc =
2197             cast<RecordStorageLocation>(Env.getStorageLocation(*BarDecl));
2198         EXPECT_TRUE(recordsEqual(*FooLoc, *BarLoc, Env));
2199 
2200         const auto *FooBazVal =
2201             cast<IntegerValue>(getFieldValue(FooLoc, *BazDecl, Env));
2202         const auto *BarBazVal =
2203             cast<IntegerValue>(getFieldValue(BarLoc, *BazDecl, Env));
2204         EXPECT_EQ(FooBazVal, BarBazVal);
2205       });
2206 }
2207 
2208 TEST(TransferTest, CopyConstructorWithInitializerListAsSyntacticSugar) {
2209   std::string Code = R"(
2210   struct A {
2211     int Baz;
2212   };
2213   void target() {
2214     A Foo = {3};
2215     (void)Foo.Baz;
2216     A Bar = {A(Foo)};
2217     // [[p]]
2218   }
2219   )";
2220   runDataflow(
2221       Code,
2222       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2223          ASTContext &ASTCtx) {
2224         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2225 
2226         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2227 
2228         const auto &FooLoc =
2229             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Foo");
2230         const auto &BarLoc =
2231             getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "Bar");
2232 
2233         const auto *FooBazVal =
2234             cast<IntegerValue>(getFieldValue(&FooLoc, *BazDecl, Env));
2235         const auto *BarBazVal =
2236             cast<IntegerValue>(getFieldValue(&BarLoc, *BazDecl, Env));
2237         EXPECT_EQ(FooBazVal, BarBazVal);
2238       });
2239 }
2240 
2241 TEST(TransferTest, CopyConstructorArgIsRefReturnedByFunction) {
2242   // This is a crash repro.
2243   std::string Code = R"(
2244     struct S {};
2245     const S &returnsSRef();
2246     void target() {
2247       S s(returnsSRef());
2248     }
2249   )";
2250   runDataflow(
2251       Code,
2252       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2253          ASTContext &ASTCtx) {});
2254 }
2255 
2256 TEST(TransferTest, MoveConstructor) {
2257   std::string Code = R"(
2258     namespace std {
2259 
2260     template <typename T> struct remove_reference      { using type = T; };
2261     template <typename T> struct remove_reference<T&>  { using type = T; };
2262     template <typename T> struct remove_reference<T&&> { using type = T; };
2263 
2264     template <typename T>
2265     using remove_reference_t = typename remove_reference<T>::type;
2266 
2267     template <typename T>
2268     std::remove_reference_t<T>&& move(T&& x);
2269 
2270     } // namespace std
2271 
2272     struct A {
2273       int Baz;
2274     };
2275 
2276     void target() {
2277       A Foo;
2278       A Bar;
2279       (void)Foo.Baz;
2280       // [[p1]]
2281       Foo = std::move(Bar);
2282       // [[p2]]
2283     }
2284   )";
2285   runDataflow(
2286       Code,
2287       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2288          ASTContext &ASTCtx) {
2289         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
2290         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
2291         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
2292 
2293         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2294         ASSERT_THAT(FooDecl, NotNull());
2295 
2296         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2297         ASSERT_THAT(BarDecl, NotNull());
2298 
2299         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2300         ASSERT_THAT(BazDecl, NotNull());
2301 
2302         const auto *FooLoc1 =
2303             cast<RecordStorageLocation>(Env1.getStorageLocation(*FooDecl));
2304         const auto *BarLoc1 =
2305             cast<RecordStorageLocation>(Env1.getStorageLocation(*BarDecl));
2306 
2307         EXPECT_FALSE(recordsEqual(*FooLoc1, *BarLoc1, Env1));
2308 
2309         const auto *FooVal1 = cast<RecordValue>(Env1.getValue(*FooLoc1));
2310         const auto *BarVal1 = cast<RecordValue>(Env1.getValue(*BarLoc1));
2311         EXPECT_NE(FooVal1, BarVal1);
2312 
2313         const auto *FooBazVal1 =
2314             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env1));
2315         const auto *BarBazVal1 =
2316             cast<IntegerValue>(getFieldValue(BarLoc1, *BazDecl, Env1));
2317         EXPECT_NE(FooBazVal1, BarBazVal1);
2318 
2319         const auto *FooLoc2 =
2320             cast<RecordStorageLocation>(Env2.getStorageLocation(*FooDecl));
2321         const auto *FooVal2 = cast<RecordValue>(Env2.getValue(*FooLoc2));
2322         EXPECT_NE(FooVal2, BarVal1);
2323         EXPECT_TRUE(recordsEqual(*FooLoc2, Env2, *BarLoc1, Env1));
2324 
2325         const auto *FooBazVal2 =
2326             cast<IntegerValue>(getFieldValue(FooLoc1, *BazDecl, Env2));
2327         EXPECT_EQ(FooBazVal2, BarBazVal1);
2328       });
2329 }
2330 
2331 TEST(TransferTest, BindTemporary) {
2332   std::string Code = R"(
2333     struct A {
2334       virtual ~A() = default;
2335 
2336       int Baz;
2337     };
2338 
2339     void target(A Foo) {
2340       int Bar = A(Foo).Baz;
2341       // [[p]]
2342     }
2343   )";
2344   runDataflow(
2345       Code,
2346       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2347          ASTContext &ASTCtx) {
2348         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2349         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2350 
2351         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2352         ASSERT_THAT(FooDecl, NotNull());
2353 
2354         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2355         ASSERT_THAT(BarDecl, NotNull());
2356 
2357         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2358         ASSERT_THAT(BazDecl, NotNull());
2359 
2360         const auto &FooVal = *cast<RecordValue>(Env.getValue(*FooDecl));
2361         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
2362         EXPECT_EQ(BarVal, getFieldValue(&FooVal, *BazDecl, Env));
2363       });
2364 }
2365 
2366 TEST(TransferTest, StaticCast) {
2367   std::string Code = R"(
2368     void target(int Foo) {
2369       int Bar = static_cast<int>(Foo);
2370       // [[p]]
2371     }
2372   )";
2373   runDataflow(
2374       Code,
2375       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2376          ASTContext &ASTCtx) {
2377         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2378         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2379 
2380         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2381         ASSERT_THAT(FooDecl, NotNull());
2382 
2383         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2384         ASSERT_THAT(BarDecl, NotNull());
2385 
2386         const auto *FooVal = Env.getValue(*FooDecl);
2387         const auto *BarVal = Env.getValue(*BarDecl);
2388         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2389         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2390         EXPECT_EQ(FooVal, BarVal);
2391       });
2392 }
2393 
2394 TEST(TransferTest, IntegralCast) {
2395   std::string Code = R"(
2396     void target(int Foo) {
2397       long Bar = Foo;
2398       // [[p]]
2399     }
2400   )";
2401   runDataflow(
2402       Code,
2403       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2404          ASTContext &ASTCtx) {
2405         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2406         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2407 
2408         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2409         ASSERT_THAT(FooDecl, NotNull());
2410 
2411         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2412         ASSERT_THAT(BarDecl, NotNull());
2413 
2414         const auto *FooVal = Env.getValue(*FooDecl);
2415         const auto *BarVal = Env.getValue(*BarDecl);
2416         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2417         EXPECT_TRUE(isa<IntegerValue>(BarVal));
2418         EXPECT_EQ(FooVal, BarVal);
2419       });
2420 }
2421 
2422 TEST(TransferTest, IntegraltoBooleanCast) {
2423   std::string Code = R"(
2424     void target(int Foo) {
2425       bool Bar = Foo;
2426       // [[p]]
2427     }
2428   )";
2429   runDataflow(
2430       Code,
2431       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2432          ASTContext &ASTCtx) {
2433         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2434         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2435 
2436         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2437         ASSERT_THAT(FooDecl, NotNull());
2438 
2439         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2440         ASSERT_THAT(BarDecl, NotNull());
2441 
2442         const auto *FooVal = Env.getValue(*FooDecl);
2443         const auto *BarVal = Env.getValue(*BarDecl);
2444         EXPECT_TRUE(isa<IntegerValue>(FooVal));
2445         EXPECT_TRUE(isa<BoolValue>(BarVal));
2446       });
2447 }
2448 
2449 TEST(TransferTest, IntegralToBooleanCastFromBool) {
2450   std::string Code = R"(
2451     void target(bool Foo) {
2452       int Zab = Foo;
2453       bool Bar = Zab;
2454       // [[p]]
2455     }
2456   )";
2457   runDataflow(
2458       Code,
2459       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2460          ASTContext &ASTCtx) {
2461         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2462         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2463 
2464         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2465         ASSERT_THAT(FooDecl, NotNull());
2466 
2467         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2468         ASSERT_THAT(BarDecl, NotNull());
2469 
2470         const auto *FooVal = Env.getValue(*FooDecl);
2471         const auto *BarVal = Env.getValue(*BarDecl);
2472         EXPECT_TRUE(isa<BoolValue>(FooVal));
2473         EXPECT_TRUE(isa<BoolValue>(BarVal));
2474         EXPECT_EQ(FooVal, BarVal);
2475       });
2476 }
2477 
2478 TEST(TransferTest, NullToPointerCast) {
2479   std::string Code = R"(
2480     using my_nullptr_t = decltype(nullptr);
2481     struct Baz {};
2482     void target() {
2483       int *FooX = nullptr;
2484       int *FooY = nullptr;
2485       bool **Bar = nullptr;
2486       Baz *Baz = nullptr;
2487       my_nullptr_t Null = 0;
2488       // [[p]]
2489     }
2490   )";
2491   runDataflow(
2492       Code,
2493       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2494          ASTContext &ASTCtx) {
2495         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2496         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2497 
2498         const ValueDecl *FooXDecl = findValueDecl(ASTCtx, "FooX");
2499         ASSERT_THAT(FooXDecl, NotNull());
2500 
2501         const ValueDecl *FooYDecl = findValueDecl(ASTCtx, "FooY");
2502         ASSERT_THAT(FooYDecl, NotNull());
2503 
2504         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2505         ASSERT_THAT(BarDecl, NotNull());
2506 
2507         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2508         ASSERT_THAT(BazDecl, NotNull());
2509 
2510         const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null");
2511         ASSERT_THAT(NullDecl, NotNull());
2512 
2513         const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl));
2514         const auto *FooYVal = cast<PointerValue>(Env.getValue(*FooYDecl));
2515         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
2516         const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl));
2517         const auto *NullVal = cast<PointerValue>(Env.getValue(*NullDecl));
2518 
2519         EXPECT_EQ(FooXVal, FooYVal);
2520         EXPECT_NE(FooXVal, BarVal);
2521         EXPECT_NE(FooXVal, BazVal);
2522         EXPECT_NE(BarVal, BazVal);
2523 
2524         const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
2525         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
2526         EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
2527 
2528         const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
2529         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
2530         EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
2531 
2532         const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
2533         EXPECT_TRUE(isa<RecordStorageLocation>(BazPointeeLoc));
2534         EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull());
2535 
2536         const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
2537         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
2538         EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
2539       });
2540 }
2541 
2542 TEST(TransferTest, PointerToMemberVariable) {
2543   std::string Code = R"(
2544     struct S {
2545       int i;
2546     };
2547     void target() {
2548       int S::*MemberPointer = &S::i;
2549       // [[p]]
2550     }
2551   )";
2552   runDataflow(
2553       Code,
2554       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2555          ASTContext &ASTCtx) {
2556         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2557 
2558         const ValueDecl *MemberPointerDecl =
2559             findValueDecl(ASTCtx, "MemberPointer");
2560         ASSERT_THAT(MemberPointerDecl, NotNull());
2561         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
2562       });
2563 }
2564 
2565 TEST(TransferTest, PointerToMemberFunction) {
2566   std::string Code = R"(
2567     struct S {
2568       void Method();
2569     };
2570     void target() {
2571       void (S::*MemberPointer)() = &S::Method;
2572       // [[p]]
2573     }
2574   )";
2575   runDataflow(
2576       Code,
2577       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2578          ASTContext &ASTCtx) {
2579         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2580 
2581         const ValueDecl *MemberPointerDecl =
2582             findValueDecl(ASTCtx, "MemberPointer");
2583         ASSERT_THAT(MemberPointerDecl, NotNull());
2584         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
2585       });
2586 }
2587 
2588 TEST(TransferTest, NullToMemberPointerCast) {
2589   std::string Code = R"(
2590     struct Foo {};
2591     void target() {
2592       int Foo::*MemberPointer = nullptr;
2593       // [[p]]
2594     }
2595   )";
2596   runDataflow(
2597       Code,
2598       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2599          ASTContext &ASTCtx) {
2600         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2601         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2602 
2603         const ValueDecl *MemberPointerDecl =
2604             findValueDecl(ASTCtx, "MemberPointer");
2605         ASSERT_THAT(MemberPointerDecl, NotNull());
2606         ASSERT_THAT(Env.getValue(*MemberPointerDecl), IsNull());
2607       });
2608 }
2609 
2610 TEST(TransferTest, AddrOfValue) {
2611   std::string Code = R"(
2612     void target() {
2613       int Foo;
2614       int *Bar = &Foo;
2615       // [[p]]
2616     }
2617   )";
2618   runDataflow(
2619       Code,
2620       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2621          ASTContext &ASTCtx) {
2622         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2623         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2624 
2625         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2626         ASSERT_THAT(FooDecl, NotNull());
2627 
2628         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2629         ASSERT_THAT(BarDecl, NotNull());
2630 
2631         const auto *FooLoc =
2632             cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
2633         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
2634         EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
2635       });
2636 }
2637 
2638 TEST(TransferTest, AddrOfReference) {
2639   std::string Code = R"(
2640     void target(int *Foo) {
2641       int *Bar = &(*Foo);
2642       // [[p]]
2643     }
2644   )";
2645   runDataflow(
2646       Code,
2647       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2648          ASTContext &ASTCtx) {
2649         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2650         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2651 
2652         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2653         ASSERT_THAT(FooDecl, NotNull());
2654 
2655         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2656         ASSERT_THAT(BarDecl, NotNull());
2657 
2658         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl));
2659         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
2660         EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
2661       });
2662 }
2663 
2664 TEST(TransferTest, CannotAnalyzeFunctionTemplate) {
2665   std::string Code = R"(
2666     template <typename T>
2667     void target() {}
2668   )";
2669   ASSERT_THAT_ERROR(
2670       checkDataflowWithNoopAnalysis(
2671           Code,
2672           [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2673              ASTContext &ASTCtx) {},
2674           {BuiltinOptions()}),
2675       llvm::FailedWithMessage("Cannot analyze templated declarations"));
2676 }
2677 
2678 TEST(TransferTest, CannotAnalyzeMethodOfClassTemplate) {
2679   std::string Code = R"(
2680     template <typename T>
2681     struct A {
2682       void target() {}
2683     };
2684   )";
2685   ASSERT_THAT_ERROR(
2686       checkDataflowWithNoopAnalysis(
2687           Code,
2688           [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2689              ASTContext &ASTCtx) {},
2690           {BuiltinOptions()}),
2691       llvm::FailedWithMessage("Cannot analyze templated declarations"));
2692 }
2693 
2694 TEST(TransferTest, VarDeclInitAssignConditionalOperator) {
2695   std::string Code = R"(
2696     struct A {};
2697 
2698     void target(A Foo, A Bar, bool Cond) {
2699       A Baz = Cond ?  Foo : Bar;
2700       /*[[p]]*/
2701     }
2702   )";
2703   runDataflow(
2704       Code,
2705       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2706          ASTContext &ASTCtx) {
2707         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2708         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2709 
2710         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2711         ASSERT_THAT(FooDecl, NotNull());
2712 
2713         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2714         ASSERT_THAT(BarDecl, NotNull());
2715 
2716         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2717         ASSERT_THAT(BazDecl, NotNull());
2718 
2719         const auto *FooVal = cast<RecordValue>(Env.getValue(*FooDecl));
2720         const auto *BarVal = cast<RecordValue>(Env.getValue(*BarDecl));
2721 
2722         const auto *BazVal = dyn_cast<RecordValue>(Env.getValue(*BazDecl));
2723         ASSERT_THAT(BazVal, NotNull());
2724 
2725         EXPECT_NE(BazVal, FooVal);
2726         EXPECT_NE(BazVal, BarVal);
2727       });
2728 }
2729 
2730 TEST(TransferTest, VarDeclInDoWhile) {
2731   std::string Code = R"(
2732     void target(int *Foo) {
2733       do {
2734         int Bar = *Foo;
2735         // [[in_loop]]
2736       } while (false);
2737       (void)0;
2738       // [[after_loop]]
2739     }
2740   )";
2741   runDataflow(
2742       Code,
2743       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2744          ASTContext &ASTCtx) {
2745         const Environment &EnvInLoop =
2746             getEnvironmentAtAnnotation(Results, "in_loop");
2747         const Environment &EnvAfterLoop =
2748             getEnvironmentAtAnnotation(Results, "after_loop");
2749 
2750         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2751         ASSERT_THAT(FooDecl, NotNull());
2752 
2753         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2754         ASSERT_THAT(BarDecl, NotNull());
2755 
2756         const auto *FooVal =
2757             cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl));
2758         const auto *FooPointeeVal =
2759             cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc()));
2760 
2761         const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl));
2762         EXPECT_EQ(BarVal, FooPointeeVal);
2763 
2764         // FIXME: This assertion documents current behavior, but we would prefer
2765         // declarations to be removed from the environment when their lifetime
2766         // ends. Once this is the case, change this assertion accordingly.
2767         ASSERT_THAT(EnvAfterLoop.getValue(*BarDecl), BarVal);
2768       });
2769 }
2770 
2771 TEST(TransferTest, UnreachableAfterWhileTrue) {
2772   std::string Code = R"(
2773     void target() {
2774       while (true) {}
2775       (void)0;
2776       /*[[p]]*/
2777     }
2778   )";
2779   runDataflow(
2780       Code,
2781       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2782          ASTContext &ASTCtx) {
2783         // The node after the while-true is pruned because it is trivially
2784         // known to be unreachable.
2785         ASSERT_TRUE(Results.empty());
2786       });
2787 }
2788 
2789 TEST(TransferTest, AggregateInitialization) {
2790   std::string BracesCode = R"(
2791     struct A {
2792       int Foo;
2793     };
2794 
2795     struct B {
2796       int Bar;
2797       A Baz;
2798       int Qux;
2799     };
2800 
2801     void target(int BarArg, int FooArg, int QuxArg) {
2802       B Quux{BarArg, {FooArg}, QuxArg};
2803       B OtherB;
2804       /*[[p]]*/
2805     }
2806   )";
2807   std::string BraceElisionCode = R"(
2808     struct A {
2809       int Foo;
2810     };
2811 
2812     struct B {
2813       int Bar;
2814       A Baz;
2815       int Qux;
2816     };
2817 
2818     void target(int BarArg, int FooArg, int QuxArg) {
2819       B Quux = {BarArg, FooArg, QuxArg};
2820       B OtherB;
2821       /*[[p]]*/
2822     }
2823   )";
2824   for (const std::string &Code : {BracesCode, BraceElisionCode}) {
2825     runDataflow(
2826         Code,
2827         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2828            ASTContext &ASTCtx) {
2829           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2830           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2831 
2832           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
2833           ASSERT_THAT(FooDecl, NotNull());
2834 
2835           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2836           ASSERT_THAT(BarDecl, NotNull());
2837 
2838           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2839           ASSERT_THAT(BazDecl, NotNull());
2840 
2841           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
2842           ASSERT_THAT(QuxDecl, NotNull());
2843 
2844           const ValueDecl *FooArgDecl = findValueDecl(ASTCtx, "FooArg");
2845           ASSERT_THAT(FooArgDecl, NotNull());
2846 
2847           const ValueDecl *BarArgDecl = findValueDecl(ASTCtx, "BarArg");
2848           ASSERT_THAT(BarArgDecl, NotNull());
2849 
2850           const ValueDecl *QuxArgDecl = findValueDecl(ASTCtx, "QuxArg");
2851           ASSERT_THAT(QuxArgDecl, NotNull());
2852 
2853           const ValueDecl *QuuxDecl = findValueDecl(ASTCtx, "Quux");
2854           ASSERT_THAT(QuuxDecl, NotNull());
2855 
2856           const auto *FooArgVal = cast<IntegerValue>(Env.getValue(*FooArgDecl));
2857           const auto *BarArgVal = cast<IntegerValue>(Env.getValue(*BarArgDecl));
2858           const auto *QuxArgVal = cast<IntegerValue>(Env.getValue(*QuxArgDecl));
2859 
2860           const auto *QuuxVal = cast<RecordValue>(Env.getValue(*QuuxDecl));
2861           ASSERT_THAT(QuuxVal, NotNull());
2862 
2863           const auto *BazVal =
2864               cast<RecordValue>(getFieldValue(QuuxVal, *BazDecl, Env));
2865           ASSERT_THAT(BazVal, NotNull());
2866 
2867           EXPECT_EQ(getFieldValue(QuuxVal, *BarDecl, Env), BarArgVal);
2868           EXPECT_EQ(getFieldValue(BazVal, *FooDecl, Env), FooArgVal);
2869           EXPECT_EQ(getFieldValue(QuuxVal, *QuxDecl, Env), QuxArgVal);
2870 
2871           // Check that fields initialized in an initializer list are always
2872           // modeled in other instances of the same type.
2873           const auto &OtherBVal =
2874               getValueForDecl<RecordValue>(ASTCtx, Env, "OtherB");
2875           EXPECT_THAT(OtherBVal.getChild(*BarDecl), NotNull());
2876           EXPECT_THAT(OtherBVal.getChild(*BazDecl), NotNull());
2877           EXPECT_THAT(OtherBVal.getChild(*QuxDecl), NotNull());
2878         });
2879   }
2880 }
2881 
2882 TEST(TransferTest, AggregateInitializationReferenceField) {
2883   std::string Code = R"(
2884     struct S {
2885       int &RefField;
2886     };
2887 
2888     void target(int i) {
2889       S s = { i };
2890       /*[[p]]*/
2891     }
2892   )";
2893   runDataflow(
2894       Code,
2895       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2896          ASTContext &ASTCtx) {
2897         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2898 
2899         const ValueDecl *RefFieldDecl = findValueDecl(ASTCtx, "RefField");
2900 
2901         auto &ILoc = getLocForDecl<StorageLocation>(ASTCtx, Env, "i");
2902         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
2903 
2904         EXPECT_EQ(SLoc.getChild(*RefFieldDecl), &ILoc);
2905       });
2906 }
2907 
2908 TEST(TransferTest, AggregateInitialization_NotExplicitlyInitializedField) {
2909   std::string Code = R"(
2910     struct S {
2911       int i1;
2912       int i2;
2913     };
2914 
2915     void target(int i) {
2916       S s = { i };
2917       /*[[p]]*/
2918     }
2919   )";
2920   runDataflow(
2921       Code,
2922       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2923          ASTContext &ASTCtx) {
2924         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2925 
2926         const ValueDecl *I1FieldDecl = findValueDecl(ASTCtx, "i1");
2927         const ValueDecl *I2FieldDecl = findValueDecl(ASTCtx, "i2");
2928 
2929         auto &SLoc = getLocForDecl<RecordStorageLocation>(ASTCtx, Env, "s");
2930 
2931         auto &IValue = getValueForDecl<IntegerValue>(ASTCtx, Env, "i");
2932         auto &I1Value =
2933             *cast<IntegerValue>(getFieldValue(&SLoc, *I1FieldDecl, Env));
2934         EXPECT_EQ(&I1Value, &IValue);
2935         auto &I2Value =
2936             *cast<IntegerValue>(getFieldValue(&SLoc, *I2FieldDecl, Env));
2937         EXPECT_NE(&I2Value, &IValue);
2938       });
2939 }
2940 
2941 TEST(TransferTest, AssignToUnionMember) {
2942   std::string Code = R"(
2943     union A {
2944       int Foo;
2945     };
2946 
2947     void target(int Bar) {
2948       A Baz;
2949       Baz.Foo = Bar;
2950       // [[p]]
2951     }
2952   )";
2953   runDataflow(
2954       Code,
2955       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
2956          ASTContext &ASTCtx) {
2957         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
2958         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
2959 
2960         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
2961         ASSERT_THAT(BazDecl, NotNull());
2962         ASSERT_TRUE(BazDecl->getType()->isUnionType());
2963 
2964         auto BazFields = BazDecl->getType()->getAsRecordDecl()->fields();
2965         FieldDecl *FooDecl = nullptr;
2966         for (FieldDecl *Field : BazFields) {
2967           if (Field->getNameAsString() == "Foo") {
2968             FooDecl = Field;
2969           } else {
2970             FAIL() << "Unexpected field: " << Field->getNameAsString();
2971           }
2972         }
2973         ASSERT_THAT(FooDecl, NotNull());
2974 
2975         const auto *BazLoc = dyn_cast_or_null<RecordStorageLocation>(
2976             Env.getStorageLocation(*BazDecl));
2977         ASSERT_THAT(BazLoc, NotNull());
2978         ASSERT_THAT(Env.getValue(*BazLoc), NotNull());
2979 
2980         const auto *FooVal =
2981             cast<IntegerValue>(getFieldValue(BazLoc, *FooDecl, Env));
2982 
2983         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
2984         ASSERT_THAT(BarDecl, NotNull());
2985         const auto *BarLoc = Env.getStorageLocation(*BarDecl);
2986         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
2987 
2988         EXPECT_EQ(Env.getValue(*BarLoc), FooVal);
2989       });
2990 }
2991 
2992 TEST(TransferTest, AssignFromBoolLiteral) {
2993   std::string Code = R"(
2994     void target() {
2995       bool Foo = true;
2996       bool Bar = false;
2997       // [[p]]
2998     }
2999   )";
3000   runDataflow(
3001       Code,
3002       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3003          ASTContext &ASTCtx) {
3004         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3005         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3006 
3007         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3008         ASSERT_THAT(FooDecl, NotNull());
3009 
3010         const auto *FooVal =
3011             dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl));
3012         ASSERT_THAT(FooVal, NotNull());
3013 
3014         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3015         ASSERT_THAT(BarDecl, NotNull());
3016 
3017         const auto *BarVal =
3018             dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*BarDecl));
3019         ASSERT_THAT(BarVal, NotNull());
3020 
3021         EXPECT_EQ(FooVal, &Env.getBoolLiteralValue(true));
3022         EXPECT_EQ(BarVal, &Env.getBoolLiteralValue(false));
3023       });
3024 }
3025 
3026 TEST(TransferTest, AssignFromCompositeBoolExpression) {
3027   {
3028     std::string Code = R"(
3029     void target(bool Foo, bool Bar, bool Qux) {
3030       bool Baz = (Foo) && (Bar || Qux);
3031       // [[p]]
3032     }
3033   )";
3034     runDataflow(
3035         Code,
3036         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3037            ASTContext &ASTCtx) {
3038           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3039           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3040 
3041           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3042           ASSERT_THAT(FooDecl, NotNull());
3043 
3044           const auto *FooVal =
3045               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3046           ASSERT_THAT(FooVal, NotNull());
3047 
3048           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3049           ASSERT_THAT(BarDecl, NotNull());
3050 
3051           const auto *BarVal =
3052               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3053           ASSERT_THAT(BarVal, NotNull());
3054 
3055           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3056           ASSERT_THAT(QuxDecl, NotNull());
3057 
3058           const auto *QuxVal =
3059               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3060           ASSERT_THAT(QuxVal, NotNull());
3061 
3062           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3063           ASSERT_THAT(BazDecl, NotNull());
3064 
3065           const auto *BazVal =
3066               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3067           ASSERT_THAT(BazVal, NotNull());
3068           auto &A = Env.arena();
3069           EXPECT_EQ(&BazVal->formula(),
3070                     &A.makeAnd(FooVal->formula(),
3071                                A.makeOr(BarVal->formula(), QuxVal->formula())));
3072         });
3073   }
3074 
3075   {
3076     std::string Code = R"(
3077     void target(bool Foo, bool Bar, bool Qux) {
3078       bool Baz = (Foo && Qux) || (Bar);
3079       // [[p]]
3080     }
3081   )";
3082     runDataflow(
3083         Code,
3084         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3085            ASTContext &ASTCtx) {
3086           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3087           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3088 
3089           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3090           ASSERT_THAT(FooDecl, NotNull());
3091 
3092           const auto *FooVal =
3093               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3094           ASSERT_THAT(FooVal, NotNull());
3095 
3096           const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3097           ASSERT_THAT(BarDecl, NotNull());
3098 
3099           const auto *BarVal =
3100               dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3101           ASSERT_THAT(BarVal, NotNull());
3102 
3103           const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3104           ASSERT_THAT(QuxDecl, NotNull());
3105 
3106           const auto *QuxVal =
3107               dyn_cast_or_null<BoolValue>(Env.getValue(*QuxDecl));
3108           ASSERT_THAT(QuxVal, NotNull());
3109 
3110           const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3111           ASSERT_THAT(BazDecl, NotNull());
3112 
3113           const auto *BazVal =
3114               dyn_cast_or_null<BoolValue>(Env.getValue(*BazDecl));
3115           ASSERT_THAT(BazVal, NotNull());
3116           auto &A = Env.arena();
3117           EXPECT_EQ(&BazVal->formula(),
3118                     &A.makeOr(A.makeAnd(FooVal->formula(), QuxVal->formula()),
3119                               BarVal->formula()));
3120         });
3121   }
3122 
3123   {
3124     std::string Code = R"(
3125       void target(bool A, bool B, bool C, bool D) {
3126         bool Foo = ((A && B) && C) && D;
3127         // [[p]]
3128       }
3129     )";
3130     runDataflow(
3131         Code,
3132         [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3133            ASTContext &ASTCtx) {
3134           ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3135           const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3136 
3137           const ValueDecl *ADecl = findValueDecl(ASTCtx, "A");
3138           ASSERT_THAT(ADecl, NotNull());
3139 
3140           const auto *AVal = dyn_cast_or_null<BoolValue>(Env.getValue(*ADecl));
3141           ASSERT_THAT(AVal, NotNull());
3142 
3143           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3144           ASSERT_THAT(BDecl, NotNull());
3145 
3146           const auto *BVal = dyn_cast_or_null<BoolValue>(Env.getValue(*BDecl));
3147           ASSERT_THAT(BVal, NotNull());
3148 
3149           const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3150           ASSERT_THAT(CDecl, NotNull());
3151 
3152           const auto *CVal = dyn_cast_or_null<BoolValue>(Env.getValue(*CDecl));
3153           ASSERT_THAT(CVal, NotNull());
3154 
3155           const ValueDecl *DDecl = findValueDecl(ASTCtx, "D");
3156           ASSERT_THAT(DDecl, NotNull());
3157 
3158           const auto *DVal = dyn_cast_or_null<BoolValue>(Env.getValue(*DDecl));
3159           ASSERT_THAT(DVal, NotNull());
3160 
3161           const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3162           ASSERT_THAT(FooDecl, NotNull());
3163 
3164           const auto *FooVal =
3165               dyn_cast_or_null<BoolValue>(Env.getValue(*FooDecl));
3166           ASSERT_THAT(FooVal, NotNull());
3167           auto &A = Env.arena();
3168           EXPECT_EQ(
3169               &FooVal->formula(),
3170               &A.makeAnd(A.makeAnd(A.makeAnd(AVal->formula(), BVal->formula()),
3171                                    CVal->formula()),
3172                          DVal->formula()));
3173         });
3174   }
3175 }
3176 
3177 TEST(TransferTest, AssignFromBoolNegation) {
3178   std::string Code = R"(
3179     void target() {
3180       bool Foo = true;
3181       bool Bar = !(Foo);
3182       // [[p]]
3183     }
3184   )";
3185   runDataflow(
3186       Code,
3187       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3188          ASTContext &ASTCtx) {
3189         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3190         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3191 
3192         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3193         ASSERT_THAT(FooDecl, NotNull());
3194 
3195         const auto *FooVal =
3196             dyn_cast_or_null<AtomicBoolValue>(Env.getValue(*FooDecl));
3197         ASSERT_THAT(FooVal, NotNull());
3198 
3199         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3200         ASSERT_THAT(BarDecl, NotNull());
3201 
3202         const auto *BarVal =
3203             dyn_cast_or_null<BoolValue>(Env.getValue(*BarDecl));
3204         ASSERT_THAT(BarVal, NotNull());
3205         auto &A = Env.arena();
3206         EXPECT_EQ(&BarVal->formula(), &A.makeNot(FooVal->formula()));
3207       });
3208 }
3209 
3210 TEST(TransferTest, BuiltinExpect) {
3211   std::string Code = R"(
3212     void target(long Foo) {
3213       long Bar = __builtin_expect(Foo, true);
3214       /*[[p]]*/
3215     }
3216   )";
3217   runDataflow(
3218       Code,
3219       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3220          ASTContext &ASTCtx) {
3221         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3222         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3223 
3224         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3225         ASSERT_THAT(FooDecl, NotNull());
3226 
3227         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3228         ASSERT_THAT(BarDecl, NotNull());
3229 
3230         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3231       });
3232 }
3233 
3234 // `__builtin_expect` takes and returns a `long` argument, so other types
3235 // involve casts. This verifies that we identify the input and output in that
3236 // case.
3237 TEST(TransferTest, BuiltinExpectBoolArg) {
3238   std::string Code = R"(
3239     void target(bool Foo) {
3240       bool Bar = __builtin_expect(Foo, true);
3241       /*[[p]]*/
3242     }
3243   )";
3244   runDataflow(
3245       Code,
3246       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3247          ASTContext &ASTCtx) {
3248         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3249         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3250 
3251         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3252         ASSERT_THAT(FooDecl, NotNull());
3253 
3254         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3255         ASSERT_THAT(BarDecl, NotNull());
3256 
3257         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3258       });
3259 }
3260 
3261 TEST(TransferTest, BuiltinUnreachable) {
3262   std::string Code = R"(
3263     void target(bool Foo) {
3264       bool Bar = false;
3265       if (Foo)
3266         Bar = Foo;
3267       else
3268         __builtin_unreachable();
3269       (void)0;
3270       /*[[p]]*/
3271     }
3272   )";
3273   runDataflow(
3274       Code,
3275       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3276          ASTContext &ASTCtx) {
3277         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3278         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3279 
3280         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3281         ASSERT_THAT(FooDecl, NotNull());
3282 
3283         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3284         ASSERT_THAT(BarDecl, NotNull());
3285 
3286         // `__builtin_unreachable` promises that the code is
3287         // unreachable, so the compiler treats the "then" branch as the
3288         // only possible predecessor of this statement.
3289         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3290       });
3291 }
3292 
3293 TEST(TransferTest, BuiltinTrap) {
3294   std::string Code = R"(
3295     void target(bool Foo) {
3296       bool Bar = false;
3297       if (Foo)
3298         Bar = Foo;
3299       else
3300         __builtin_trap();
3301       (void)0;
3302       /*[[p]]*/
3303     }
3304   )";
3305   runDataflow(
3306       Code,
3307       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3308          ASTContext &ASTCtx) {
3309         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3310         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3311 
3312         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3313         ASSERT_THAT(FooDecl, NotNull());
3314 
3315         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3316         ASSERT_THAT(BarDecl, NotNull());
3317 
3318         // `__builtin_trap` ensures program termination, so only the
3319         // "then" branch is a predecessor of this statement.
3320         EXPECT_EQ(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3321       });
3322 }
3323 
3324 TEST(TransferTest, BuiltinDebugTrap) {
3325   std::string Code = R"(
3326     void target(bool Foo) {
3327       bool Bar = false;
3328       if (Foo)
3329         Bar = Foo;
3330       else
3331         __builtin_debugtrap();
3332       (void)0;
3333       /*[[p]]*/
3334     }
3335   )";
3336   runDataflow(
3337       Code,
3338       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3339          ASTContext &ASTCtx) {
3340         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3341         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3342 
3343         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3344         ASSERT_THAT(FooDecl, NotNull());
3345 
3346         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3347         ASSERT_THAT(BarDecl, NotNull());
3348 
3349         // `__builtin_debugtrap` doesn't ensure program termination.
3350         EXPECT_NE(Env.getValue(*FooDecl), Env.getValue(*BarDecl));
3351       });
3352 }
3353 
3354 TEST(TransferTest, StaticIntSingleVarDecl) {
3355   std::string Code = R"(
3356     void target() {
3357       static int Foo;
3358       // [[p]]
3359     }
3360   )";
3361   runDataflow(
3362       Code,
3363       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3364          ASTContext &ASTCtx) {
3365         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3366         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3367 
3368         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3369         ASSERT_THAT(FooDecl, NotNull());
3370 
3371         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3372         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3373 
3374         const Value *FooVal = Env.getValue(*FooLoc);
3375         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3376       });
3377 }
3378 
3379 TEST(TransferTest, StaticIntGroupVarDecl) {
3380   std::string Code = R"(
3381     void target() {
3382       static int Foo, Bar;
3383       (void)0;
3384       // [[p]]
3385     }
3386   )";
3387   runDataflow(
3388       Code,
3389       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3390          ASTContext &ASTCtx) {
3391         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3392         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3393 
3394         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3395         ASSERT_THAT(FooDecl, NotNull());
3396 
3397         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3398         ASSERT_THAT(BarDecl, NotNull());
3399 
3400         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
3401         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
3402 
3403         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
3404         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(BarLoc));
3405 
3406         const Value *FooVal = Env.getValue(*FooLoc);
3407         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
3408 
3409         const Value *BarVal = Env.getValue(*BarLoc);
3410         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(BarVal));
3411 
3412         EXPECT_NE(FooVal, BarVal);
3413       });
3414 }
3415 
3416 TEST(TransferTest, GlobalIntVarDecl) {
3417   std::string Code = R"(
3418     static int Foo;
3419 
3420     void target() {
3421       int Bar = Foo;
3422       int Baz = Foo;
3423       // [[p]]
3424     }
3425   )";
3426   runDataflow(
3427       Code,
3428       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3429          ASTContext &ASTCtx) {
3430         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3431         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3432 
3433         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3434         ASSERT_THAT(BarDecl, NotNull());
3435 
3436         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3437         ASSERT_THAT(BazDecl, NotNull());
3438 
3439         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3440         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3441         EXPECT_EQ(BarVal, BazVal);
3442       });
3443 }
3444 
3445 TEST(TransferTest, StaticMemberIntVarDecl) {
3446   std::string Code = R"(
3447     struct A {
3448       static int Foo;
3449     };
3450 
3451     void target(A a) {
3452       int Bar = a.Foo;
3453       int Baz = a.Foo;
3454       // [[p]]
3455     }
3456   )";
3457   runDataflow(
3458       Code,
3459       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3460          ASTContext &ASTCtx) {
3461         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3462         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3463 
3464         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3465         ASSERT_THAT(BarDecl, NotNull());
3466 
3467         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3468         ASSERT_THAT(BazDecl, NotNull());
3469 
3470         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3471         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3472         EXPECT_EQ(BarVal, BazVal);
3473       });
3474 }
3475 
3476 TEST(TransferTest, StaticMemberRefVarDecl) {
3477   std::string Code = R"(
3478     struct A {
3479       static int &Foo;
3480     };
3481 
3482     void target(A a) {
3483       int Bar = a.Foo;
3484       int Baz = a.Foo;
3485       // [[p]]
3486     }
3487   )";
3488   runDataflow(
3489       Code,
3490       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3491          ASTContext &ASTCtx) {
3492         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3493         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3494 
3495         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3496         ASSERT_THAT(BarDecl, NotNull());
3497 
3498         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
3499         ASSERT_THAT(BazDecl, NotNull());
3500 
3501         const Value *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3502         const Value *BazVal = cast<IntegerValue>(Env.getValue(*BazDecl));
3503         EXPECT_EQ(BarVal, BazVal);
3504       });
3505 }
3506 
3507 TEST(TransferTest, AssignMemberBeforeCopy) {
3508   std::string Code = R"(
3509     struct A {
3510       int Foo;
3511     };
3512 
3513     void target() {
3514       A A1;
3515       A A2;
3516       int Bar;
3517       A1.Foo = Bar;
3518       A2 = A1;
3519       // [[p]]
3520     }
3521   )";
3522   runDataflow(
3523       Code,
3524       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3525          ASTContext &ASTCtx) {
3526         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3527         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3528 
3529         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
3530         ASSERT_THAT(FooDecl, NotNull());
3531 
3532         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3533         ASSERT_THAT(BarDecl, NotNull());
3534 
3535         const ValueDecl *A1Decl = findValueDecl(ASTCtx, "A1");
3536         ASSERT_THAT(A1Decl, NotNull());
3537 
3538         const ValueDecl *A2Decl = findValueDecl(ASTCtx, "A2");
3539         ASSERT_THAT(A2Decl, NotNull());
3540 
3541         const auto *BarVal = cast<IntegerValue>(Env.getValue(*BarDecl));
3542 
3543         const auto *A2Val = cast<RecordValue>(Env.getValue(*A2Decl));
3544         EXPECT_EQ(getFieldValue(A2Val, *FooDecl, Env), BarVal);
3545       });
3546 }
3547 
3548 TEST(TransferTest, BooleanEquality) {
3549   std::string Code = R"(
3550     void target(bool Bar) {
3551       bool Foo = true;
3552       if (Bar == Foo) {
3553         (void)0;
3554         /*[[p-then]]*/
3555       } else {
3556         (void)0;
3557         /*[[p-else]]*/
3558       }
3559     }
3560   )";
3561   runDataflow(
3562       Code,
3563       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3564          ASTContext &ASTCtx) {
3565         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3566         const Environment &EnvThen =
3567             getEnvironmentAtAnnotation(Results, "p-then");
3568         const Environment &EnvElse =
3569             getEnvironmentAtAnnotation(Results, "p-else");
3570 
3571         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3572         ASSERT_THAT(BarDecl, NotNull());
3573 
3574         auto &BarValThen = getFormula(*BarDecl, EnvThen);
3575         EXPECT_TRUE(EnvThen.flowConditionImplies(BarValThen));
3576 
3577         auto &BarValElse = getFormula(*BarDecl, EnvElse);
3578         EXPECT_TRUE(
3579             EnvElse.flowConditionImplies(EnvElse.arena().makeNot(BarValElse)));
3580       });
3581 }
3582 
3583 TEST(TransferTest, BooleanInequality) {
3584   std::string Code = R"(
3585     void target(bool Bar) {
3586       bool Foo = true;
3587       if (Bar != Foo) {
3588         (void)0;
3589         /*[[p-then]]*/
3590       } else {
3591         (void)0;
3592         /*[[p-else]]*/
3593       }
3594     }
3595   )";
3596   runDataflow(
3597       Code,
3598       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3599          ASTContext &ASTCtx) {
3600         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3601         const Environment &EnvThen =
3602             getEnvironmentAtAnnotation(Results, "p-then");
3603         const Environment &EnvElse =
3604             getEnvironmentAtAnnotation(Results, "p-else");
3605 
3606         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3607         ASSERT_THAT(BarDecl, NotNull());
3608 
3609         auto &BarValThen = getFormula(*BarDecl, EnvThen);
3610         EXPECT_TRUE(
3611             EnvThen.flowConditionImplies(EnvThen.arena().makeNot(BarValThen)));
3612 
3613         auto &BarValElse = getFormula(*BarDecl, EnvElse);
3614         EXPECT_TRUE(EnvElse.flowConditionImplies(BarValElse));
3615       });
3616 }
3617 
3618 TEST(TransferTest, IntegerLiteralEquality) {
3619   std::string Code = R"(
3620     void target() {
3621       bool equal = (42 == 42);
3622       // [[p]]
3623     }
3624   )";
3625   runDataflow(
3626       Code,
3627       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3628          ASTContext &ASTCtx) {
3629         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3630 
3631         auto &Equal =
3632             getValueForDecl<BoolValue>(ASTCtx, Env, "equal").formula();
3633         EXPECT_TRUE(Env.flowConditionImplies(Equal));
3634       });
3635 }
3636 
3637 TEST(TransferTest, CorrelatedBranches) {
3638   std::string Code = R"(
3639     void target(bool B, bool C) {
3640       if (B) {
3641         return;
3642       }
3643       (void)0;
3644       /*[[p0]]*/
3645       if (C) {
3646         B = true;
3647         /*[[p1]]*/
3648       }
3649       if (B) {
3650         (void)0;
3651         /*[[p2]]*/
3652       }
3653     }
3654   )";
3655   runDataflow(
3656       Code,
3657       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3658          ASTContext &ASTCtx) {
3659         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
3660 
3661         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3662         ASSERT_THAT(CDecl, NotNull());
3663 
3664         {
3665           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
3666           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3667           ASSERT_THAT(BDecl, NotNull());
3668           auto &BVal = getFormula(*BDecl, Env);
3669 
3670           EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BVal)));
3671         }
3672 
3673         {
3674           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
3675           auto &CVal = getFormula(*CDecl, Env);
3676           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3677         }
3678 
3679         {
3680           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
3681           auto &CVal = getFormula(*CDecl, Env);
3682           EXPECT_TRUE(Env.flowConditionImplies(CVal));
3683         }
3684       });
3685 }
3686 
3687 TEST(TransferTest, LoopWithAssignmentConverges) {
3688   std::string Code = R"(
3689     bool foo();
3690 
3691     void target() {
3692        do {
3693         bool Bar = foo();
3694         if (Bar) break;
3695         (void)Bar;
3696         /*[[p]]*/
3697       } while (true);
3698     }
3699   )";
3700   // The key property that we are verifying is implicit in `runDataflow` --
3701   // namely, that the analysis succeeds, rather than hitting the maximum number
3702   // of iterations.
3703   runDataflow(
3704       Code,
3705       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3706          ASTContext &ASTCtx) {
3707         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3708         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3709 
3710         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3711         ASSERT_THAT(BarDecl, NotNull());
3712 
3713         auto &BarVal = getFormula(*BarDecl, Env);
3714         EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal)));
3715       });
3716 }
3717 
3718 TEST(TransferTest, LoopWithStagedAssignments) {
3719   std::string Code = R"(
3720     bool foo();
3721 
3722     void target() {
3723       bool Bar = false;
3724       bool Err = false;
3725       while (foo()) {
3726         if (Bar)
3727           Err = true;
3728         Bar = true;
3729         /*[[p]]*/
3730       }
3731     }
3732   )";
3733   runDataflow(
3734       Code,
3735       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3736          ASTContext &ASTCtx) {
3737         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3738         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3739 
3740         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3741         ASSERT_THAT(BarDecl, NotNull());
3742         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
3743         ASSERT_THAT(ErrDecl, NotNull());
3744 
3745         auto &BarVal = getFormula(*BarDecl, Env);
3746         auto &ErrVal = getFormula(*ErrDecl, Env);
3747         EXPECT_TRUE(Env.flowConditionImplies(BarVal));
3748         // An unsound analysis, for example only evaluating the loop once, can
3749         // conclude that `Err` is false. So, we test that this conclusion is not
3750         // reached.
3751         EXPECT_FALSE(
3752             Env.flowConditionImplies(Env.arena().makeNot(ErrVal)));
3753       });
3754 }
3755 
3756 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
3757   std::string Code = R"(
3758     bool &foo();
3759 
3760     void target() {
3761        do {
3762         bool& Bar = foo();
3763         if (Bar) break;
3764         (void)Bar;
3765         /*[[p]]*/
3766       } while (true);
3767     }
3768   )";
3769   // The key property that we are verifying is that the analysis succeeds,
3770   // rather than hitting the maximum number of iterations.
3771   runDataflow(
3772       Code,
3773       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3774          ASTContext &ASTCtx) {
3775         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3776         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3777 
3778         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3779         ASSERT_THAT(BarDecl, NotNull());
3780 
3781         auto &BarVal = getFormula(*BarDecl, Env);
3782         EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal)));
3783       });
3784 }
3785 
3786 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
3787   std::string Code = R"(
3788     struct Lookup {
3789       int x;
3790     };
3791 
3792     void target(Lookup val, bool b) {
3793       const Lookup* l = nullptr;
3794       while (b) {
3795         l = &val;
3796         /*[[p-inner]]*/
3797       }
3798       (void)0;
3799       /*[[p-outer]]*/
3800     }
3801   )";
3802   // The key property that we are verifying is implicit in `runDataflow` --
3803   // namely, that the analysis succeeds, rather than hitting the maximum number
3804   // of iterations.
3805   runDataflow(
3806       Code,
3807       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3808          ASTContext &ASTCtx) {
3809         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
3810         const Environment &InnerEnv =
3811             getEnvironmentAtAnnotation(Results, "p-inner");
3812         const Environment &OuterEnv =
3813             getEnvironmentAtAnnotation(Results, "p-outer");
3814 
3815         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
3816         ASSERT_THAT(ValDecl, NotNull());
3817 
3818         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
3819         ASSERT_THAT(LDecl, NotNull());
3820 
3821         // Inner.
3822         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
3823         ASSERT_THAT(LVal, NotNull());
3824 
3825         EXPECT_EQ(&LVal->getPointeeLoc(),
3826                   InnerEnv.getStorageLocation(*ValDecl));
3827 
3828         // Outer.
3829         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
3830         ASSERT_THAT(LVal, NotNull());
3831 
3832         // The loop body may not have been executed, so we should not conclude
3833         // that `l` points to `val`.
3834         EXPECT_NE(&LVal->getPointeeLoc(),
3835                   OuterEnv.getStorageLocation(*ValDecl));
3836       });
3837 }
3838 
3839 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
3840   std::string Code = R"(
3841     union Union {
3842       int A;
3843       float B;
3844     };
3845 
3846     void foo() {
3847       Union A;
3848       Union B;
3849       A = B;
3850     }
3851   )";
3852   // This is a crash regression test when calling the transfer function on a
3853   // `CXXThisExpr` that refers to a union.
3854   runDataflow(
3855       Code,
3856       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
3857          ASTContext &) {},
3858       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
3859 }
3860 
3861 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
3862   std::string Code = R"(
3863     struct A {
3864       int Foo;
3865       int Bar;
3866     };
3867 
3868     void target() {
3869       int Qux;
3870       A Baz;
3871       Baz.Foo = Qux;
3872       auto &FooRef = Baz.Foo;
3873       auto &BarRef = Baz.Bar;
3874       auto &[BoundFooRef, BoundBarRef] = Baz;
3875       // [[p]]
3876     }
3877   )";
3878   runDataflow(
3879       Code,
3880       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3881          ASTContext &ASTCtx) {
3882         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3883         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3884 
3885         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3886         ASSERT_THAT(FooRefDecl, NotNull());
3887 
3888         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3889         ASSERT_THAT(BarRefDecl, NotNull());
3890 
3891         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3892         ASSERT_THAT(QuxDecl, NotNull());
3893 
3894         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3895         ASSERT_THAT(BoundFooRefDecl, NotNull());
3896 
3897         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3898         ASSERT_THAT(BoundBarRefDecl, NotNull());
3899 
3900         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
3901         ASSERT_THAT(FooRefLoc, NotNull());
3902 
3903         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
3904         ASSERT_THAT(BarRefLoc, NotNull());
3905 
3906         const Value *QuxVal = Env.getValue(*QuxDecl);
3907         ASSERT_THAT(QuxVal, NotNull());
3908 
3909         const StorageLocation *BoundFooRefLoc =
3910             Env.getStorageLocation(*BoundFooRefDecl);
3911         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3912 
3913         const StorageLocation *BoundBarRefLoc =
3914             Env.getStorageLocation(*BoundBarRefDecl);
3915         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3916 
3917         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
3918       });
3919 }
3920 
3921 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
3922   std::string Code = R"(
3923     struct A {
3924       int &Foo;
3925       int &Bar;
3926     };
3927 
3928     void target(A Baz) {
3929       int Qux;
3930       Baz.Foo = Qux;
3931       auto &FooRef = Baz.Foo;
3932       auto &BarRef = Baz.Bar;
3933       auto &[BoundFooRef, BoundBarRef] = Baz;
3934       // [[p]]
3935     }
3936   )";
3937   runDataflow(
3938       Code,
3939       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3940          ASTContext &ASTCtx) {
3941         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3942         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3943 
3944         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
3945         ASSERT_THAT(FooRefDecl, NotNull());
3946 
3947         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
3948         ASSERT_THAT(BarRefDecl, NotNull());
3949 
3950         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
3951         ASSERT_THAT(QuxDecl, NotNull());
3952 
3953         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
3954         ASSERT_THAT(BoundFooRefDecl, NotNull());
3955 
3956         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
3957         ASSERT_THAT(BoundBarRefDecl, NotNull());
3958 
3959         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
3960         ASSERT_THAT(FooRefLoc, NotNull());
3961 
3962         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
3963         ASSERT_THAT(BarRefLoc, NotNull());
3964 
3965         const Value *QuxVal = Env.getValue(*QuxDecl);
3966         ASSERT_THAT(QuxVal, NotNull());
3967 
3968         const StorageLocation *BoundFooRefLoc =
3969             Env.getStorageLocation(*BoundFooRefDecl);
3970         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
3971 
3972         const StorageLocation *BoundBarRefLoc =
3973             Env.getStorageLocation(*BoundBarRefDecl);
3974         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
3975 
3976         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
3977       });
3978 }
3979 
3980 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
3981   std::string Code = R"(
3982     struct A {
3983       int Foo;
3984       int Bar;
3985     };
3986 
3987     void target() {
3988       int Qux;
3989       A Baz;
3990       Baz.Foo = Qux;
3991       auto &FooRef = Baz.Foo;
3992       auto &BarRef = Baz.Bar;
3993       auto [BoundFoo, BoundBar] = Baz;
3994       // [[p]]
3995     }
3996   )";
3997   runDataflow(
3998       Code,
3999       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4000          ASTContext &ASTCtx) {
4001         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4002         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4003 
4004         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4005         ASSERT_THAT(FooRefDecl, NotNull());
4006 
4007         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4008         ASSERT_THAT(BarRefDecl, NotNull());
4009 
4010         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4011         ASSERT_THAT(BoundFooDecl, NotNull());
4012 
4013         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4014         ASSERT_THAT(BoundBarDecl, NotNull());
4015 
4016         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4017         ASSERT_THAT(QuxDecl, NotNull());
4018 
4019         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4020         ASSERT_THAT(FooRefLoc, NotNull());
4021 
4022         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4023         ASSERT_THAT(BarRefLoc, NotNull());
4024 
4025         const Value *QuxVal = Env.getValue(*QuxDecl);
4026         ASSERT_THAT(QuxVal, NotNull());
4027 
4028         const StorageLocation *BoundFooLoc =
4029             Env.getStorageLocation(*BoundFooDecl);
4030         EXPECT_NE(BoundFooLoc, FooRefLoc);
4031 
4032         const StorageLocation *BoundBarLoc =
4033             Env.getStorageLocation(*BoundBarDecl);
4034         EXPECT_NE(BoundBarLoc, BarRefLoc);
4035 
4036         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
4037       });
4038 }
4039 
4040 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
4041   std::string Code = R"(
4042     namespace std {
4043     using size_t = int;
4044     template <class> struct tuple_size;
4045     template <std::size_t, class> struct tuple_element;
4046     template <class...> class tuple;
4047 
4048     namespace {
4049     template <class T, T v>
4050     struct size_helper { static const T value = v; };
4051     } // namespace
4052 
4053     template <class... T>
4054     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4055 
4056     template <std::size_t I, class... T>
4057     struct tuple_element<I, tuple<T...>> {
4058       using type =  __type_pack_element<I, T...>;
4059     };
4060 
4061     template <class...> class tuple {};
4062 
4063     template <std::size_t I, class... T>
4064     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4065     } // namespace std
4066 
4067     std::tuple<bool, int> makeTuple();
4068 
4069     void target(bool B) {
4070       auto [BoundFoo, BoundBar] = makeTuple();
4071       bool Baz;
4072       // Include if-then-else to test interaction of `BindingDecl` with join.
4073       if (B) {
4074         Baz = BoundFoo;
4075         (void)BoundBar;
4076         // [[p1]]
4077       } else {
4078         Baz = BoundFoo;
4079       }
4080       (void)0;
4081       // [[p2]]
4082     }
4083   )";
4084   runDataflow(
4085       Code,
4086       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4087          ASTContext &ASTCtx) {
4088         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4089         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4090 
4091         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4092         ASSERT_THAT(BoundFooDecl, NotNull());
4093 
4094         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4095         ASSERT_THAT(BoundBarDecl, NotNull());
4096 
4097         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4098         ASSERT_THAT(BazDecl, NotNull());
4099 
4100         // BindingDecls always map to references -- either lvalue or rvalue, so
4101         // we still need to skip here.
4102         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4103         ASSERT_THAT(BoundFooValue, NotNull());
4104         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4105 
4106         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4107         ASSERT_THAT(BoundBarValue, NotNull());
4108         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4109 
4110         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
4111         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4112 
4113         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4114 
4115         // Test that `BoundFooDecl` retains the value we expect, after the join.
4116         BoundFooValue = Env2.getValue(*BoundFooDecl);
4117         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4118       });
4119 }
4120 
4121 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
4122   std::string Code = R"(
4123     namespace std {
4124     using size_t = int;
4125     template <class> struct tuple_size;
4126     template <std::size_t, class> struct tuple_element;
4127     template <class...> class tuple;
4128 
4129     namespace {
4130     template <class T, T v>
4131     struct size_helper { static const T value = v; };
4132     } // namespace
4133 
4134     template <class... T>
4135     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4136 
4137     template <std::size_t I, class... T>
4138     struct tuple_element<I, tuple<T...>> {
4139       using type =  __type_pack_element<I, T...>;
4140     };
4141 
4142     template <class...> class tuple {};
4143 
4144     template <std::size_t I, class... T>
4145     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4146     } // namespace std
4147 
4148     std::tuple<bool, int> &getTuple();
4149 
4150     void target(bool B) {
4151       auto &[BoundFoo, BoundBar] = getTuple();
4152       bool Baz;
4153       // Include if-then-else to test interaction of `BindingDecl` with join.
4154       if (B) {
4155         Baz = BoundFoo;
4156         (void)BoundBar;
4157         // [[p1]]
4158       } else {
4159         Baz = BoundFoo;
4160       }
4161       (void)0;
4162       // [[p2]]
4163     }
4164   )";
4165   runDataflow(
4166       Code,
4167       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4168          ASTContext &ASTCtx) {
4169         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4170         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4171 
4172         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4173         ASSERT_THAT(BoundFooDecl, NotNull());
4174 
4175         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4176         ASSERT_THAT(BoundBarDecl, NotNull());
4177 
4178         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4179         ASSERT_THAT(BazDecl, NotNull());
4180 
4181         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4182         ASSERT_THAT(BoundFooValue, NotNull());
4183         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4184 
4185         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4186         ASSERT_THAT(BoundBarValue, NotNull());
4187         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4188 
4189         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
4190         // works as expected. We don't test aliasing properties of the
4191         // reference, because we don't model `std::get` and so have no way to
4192         // equate separate references into the tuple.
4193         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4194 
4195         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4196 
4197         // Test that `BoundFooDecl` retains the value we expect, after the join.
4198         BoundFooValue = Env2.getValue(*BoundFooDecl);
4199         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4200       });
4201 }
4202 
4203 TEST(TransferTest, BinaryOperatorComma) {
4204   std::string Code = R"(
4205     void target(int Foo, int Bar) {
4206       int &Baz = (Foo, Bar);
4207       // [[p]]
4208     }
4209   )";
4210   runDataflow(
4211       Code,
4212       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4213          ASTContext &ASTCtx) {
4214         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4215         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4216 
4217         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4218         ASSERT_THAT(BarDecl, NotNull());
4219 
4220         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4221         ASSERT_THAT(BazDecl, NotNull());
4222 
4223         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4224         ASSERT_THAT(BarLoc, NotNull());
4225 
4226         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
4227         EXPECT_EQ(BazLoc, BarLoc);
4228       });
4229 }
4230 
4231 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
4232   std::string Code = R"(
4233     void target(bool Foo) {
4234       if (Foo) {
4235         (void)0;
4236         // [[if_then]]
4237       } else {
4238         (void)0;
4239         // [[if_else]]
4240       }
4241     }
4242   )";
4243   runDataflow(
4244       Code,
4245       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4246          ASTContext &ASTCtx) {
4247         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
4248         const Environment &ThenEnv =
4249             getEnvironmentAtAnnotation(Results, "if_then");
4250         const Environment &ElseEnv =
4251             getEnvironmentAtAnnotation(Results, "if_else");
4252 
4253         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4254         ASSERT_THAT(FooDecl, NotNull());
4255 
4256         auto &ThenFooVal= getFormula(*FooDecl, ThenEnv);
4257         EXPECT_TRUE(ThenEnv.flowConditionImplies(ThenFooVal));
4258 
4259         auto &ElseFooVal = getFormula(*FooDecl, ElseEnv);
4260         EXPECT_TRUE(
4261             ElseEnv.flowConditionImplies(ElseEnv.arena().makeNot(ElseFooVal)));
4262       });
4263 }
4264 
4265 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
4266   std::string Code = R"(
4267     void target(bool Foo) {
4268       while (Foo) {
4269         (void)0;
4270         // [[loop_body]]
4271       }
4272       (void)0;
4273       // [[after_loop]]
4274     }
4275   )";
4276   runDataflow(
4277       Code,
4278       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4279          ASTContext &ASTCtx) {
4280         ASSERT_THAT(Results.keys(),
4281                     UnorderedElementsAre("loop_body", "after_loop"));
4282         const Environment &LoopBodyEnv =
4283             getEnvironmentAtAnnotation(Results, "loop_body");
4284         const Environment &AfterLoopEnv =
4285             getEnvironmentAtAnnotation(Results, "after_loop");
4286 
4287         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4288         ASSERT_THAT(FooDecl, NotNull());
4289 
4290         auto &LoopBodyFooVal = getFormula(*FooDecl, LoopBodyEnv);
4291         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4292 
4293         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4294         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4295             AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
4296       });
4297 }
4298 
4299 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
4300   std::string Code = R"(
4301     void target(bool Foo) {
4302       bool Bar = true;
4303       do {
4304         (void)0;
4305         // [[loop_body]]
4306         Bar = false;
4307       } while (Foo);
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         auto &A = AfterLoopEnv.arena();
4323 
4324         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4325         ASSERT_THAT(FooDecl, NotNull());
4326 
4327         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4328         ASSERT_THAT(BarDecl, NotNull());
4329 
4330         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4331         auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv);
4332         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(
4333             A.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
4334 
4335         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4336         auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv);
4337         EXPECT_TRUE(
4338             AfterLoopEnv.flowConditionImplies(A.makeNot(AfterLoopFooVal)));
4339         EXPECT_TRUE(
4340             AfterLoopEnv.flowConditionImplies(A.makeNot(AfterLoopBarVal)));
4341       });
4342 }
4343 
4344 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
4345   std::string Code = R"(
4346     void target(bool Foo) {
4347       for (; Foo;) {
4348         (void)0;
4349         // [[loop_body]]
4350       }
4351       (void)0;
4352       // [[after_loop]]
4353     }
4354   )";
4355   runDataflow(
4356       Code,
4357       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4358          ASTContext &ASTCtx) {
4359         ASSERT_THAT(Results.keys(),
4360                     UnorderedElementsAre("loop_body", "after_loop"));
4361         const Environment &LoopBodyEnv =
4362             getEnvironmentAtAnnotation(Results, "loop_body");
4363         const Environment &AfterLoopEnv =
4364             getEnvironmentAtAnnotation(Results, "after_loop");
4365 
4366         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4367         ASSERT_THAT(FooDecl, NotNull());
4368 
4369         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4370         EXPECT_TRUE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4371 
4372         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4373         EXPECT_TRUE(AfterLoopEnv.flowConditionImplies(
4374             AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
4375       });
4376 }
4377 
4378 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
4379   std::string Code = R"(
4380     void target(bool Foo) {
4381       for (;;) {
4382         (void)0;
4383         // [[loop_body]]
4384       }
4385     }
4386   )";
4387   runDataflow(
4388       Code,
4389       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4390          ASTContext &ASTCtx) {
4391         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
4392         const Environment &LoopBodyEnv =
4393             getEnvironmentAtAnnotation(Results, "loop_body");
4394 
4395         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4396         ASSERT_THAT(FooDecl, NotNull());
4397 
4398         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4399         EXPECT_FALSE(LoopBodyEnv.flowConditionImplies(LoopBodyFooVal));
4400       });
4401 }
4402 
4403 TEST(TransferTest, ContextSensitiveOptionDisabled) {
4404   std::string Code = R"(
4405     bool GiveBool();
4406     void SetBool(bool &Var) { Var = true; }
4407 
4408     void target() {
4409       bool Foo = GiveBool();
4410       SetBool(Foo);
4411       // [[p]]
4412     }
4413   )";
4414   runDataflow(
4415       Code,
4416       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4417          ASTContext &ASTCtx) {
4418         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4419         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4420 
4421         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4422         ASSERT_THAT(FooDecl, NotNull());
4423 
4424         auto &FooVal = getFormula(*FooDecl, Env);
4425         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4426         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4427       },
4428       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
4429 }
4430 
4431 TEST(TransferTest, ContextSensitiveReturnReference) {
4432   std::string Code = R"(
4433     class S {};
4434     S& target(bool b, S &s) {
4435       return s;
4436       // [[p]]
4437     }
4438   )";
4439   runDataflow(
4440       Code,
4441       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4442          ASTContext &ASTCtx) {
4443         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4444 
4445         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4446         ASSERT_THAT(SDecl, NotNull());
4447 
4448         auto *SLoc = Env.getStorageLocation(*SDecl);
4449         ASSERT_THAT(SLoc, NotNull());
4450 
4451         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
4452       },
4453       {BuiltinOptions{ContextSensitiveOptions{}}});
4454 }
4455 
4456 // This test is a regression test, based on a real crash.
4457 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
4458   std::string Code = R"(
4459     class S {};
4460     S& target(bool b, S &s) {
4461       return b ? s : s;
4462       // [[p]]
4463     }
4464   )";
4465   runDataflow(
4466       Code,
4467       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4468          ASTContext &ASTCtx) {
4469         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4470         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4471 
4472         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4473         ASSERT_THAT(SDecl, NotNull());
4474 
4475         auto *SLoc = Env.getStorageLocation(*SDecl);
4476         ASSERT_THAT(SLoc, NotNull());
4477         EXPECT_THAT(Env.getValue(*SLoc), NotNull());
4478 
4479         auto *Loc = Env.getReturnStorageLocation();
4480         ASSERT_THAT(Loc, NotNull());
4481         EXPECT_THAT(Env.getValue(*Loc), NotNull());
4482 
4483         // TODO: We would really like to make this stronger assertion, but that
4484         // doesn't work because we don't propagate values correctly through
4485         // the conditional operator yet.
4486         // ASSERT_THAT(Loc, Eq(SLoc));
4487       },
4488       {BuiltinOptions{ContextSensitiveOptions{}}});
4489 }
4490 
4491 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
4492   std::string Code = R"(
4493     class S {};
4494     S &callee(bool b, S &s1_parm, S &s2_parm) {
4495       if (b)
4496         return s1_parm;
4497       else
4498         return s2_parm;
4499     }
4500     void target(bool b) {
4501       S s1;
4502       S s2;
4503       S &return_s1 = s1;
4504       S &return_s2 = s2;
4505       S &return_dont_know = callee(b, s1, s2);
4506       // [[p]]
4507     }
4508   )";
4509   runDataflow(
4510       Code,
4511       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4512          ASTContext &ASTCtx) {
4513         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4514 
4515         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
4516         ASSERT_THAT(S1, NotNull());
4517         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
4518         ASSERT_THAT(S2, NotNull());
4519         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
4520         ASSERT_THAT(ReturnS1, NotNull());
4521         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
4522         ASSERT_THAT(ReturnS2, NotNull());
4523         const ValueDecl *ReturnDontKnow =
4524             findValueDecl(ASTCtx, "return_dont_know");
4525         ASSERT_THAT(ReturnDontKnow, NotNull());
4526 
4527         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
4528         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
4529 
4530         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
4531         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
4532 
4533         // In the case where we don't have a consistent storage location for
4534         // the return value, the framework creates a new storage location, which
4535         // should be different from the storage locations of `s1` and `s2`.
4536         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
4537         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
4538       },
4539       {BuiltinOptions{ContextSensitiveOptions{}}});
4540 }
4541 
4542 TEST(TransferTest, ContextSensitiveDepthZero) {
4543   std::string Code = R"(
4544     bool GiveBool();
4545     void SetBool(bool &Var) { Var = true; }
4546 
4547     void target() {
4548       bool Foo = GiveBool();
4549       SetBool(Foo);
4550       // [[p]]
4551     }
4552   )";
4553   runDataflow(
4554       Code,
4555       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4556          ASTContext &ASTCtx) {
4557         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4558         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4559 
4560         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4561         ASSERT_THAT(FooDecl, NotNull());
4562 
4563         auto &FooVal = getFormula(*FooDecl, Env);
4564         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4565         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4566       },
4567       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
4568 }
4569 
4570 TEST(TransferTest, ContextSensitiveSetTrue) {
4571   std::string Code = R"(
4572     bool GiveBool();
4573     void SetBool(bool &Var) { Var = true; }
4574 
4575     void target() {
4576       bool Foo = GiveBool();
4577       SetBool(Foo);
4578       // [[p]]
4579     }
4580   )";
4581   runDataflow(
4582       Code,
4583       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4584          ASTContext &ASTCtx) {
4585         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4586         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4587 
4588         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4589         ASSERT_THAT(FooDecl, NotNull());
4590 
4591         auto &FooVal = getFormula(*FooDecl, Env);
4592         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4593       },
4594       {BuiltinOptions{ContextSensitiveOptions{}}});
4595 }
4596 
4597 TEST(TransferTest, ContextSensitiveSetFalse) {
4598   std::string Code = R"(
4599     bool GiveBool();
4600     void SetBool(bool &Var) { Var = false; }
4601 
4602     void target() {
4603       bool Foo = GiveBool();
4604       SetBool(Foo);
4605       // [[p]]
4606     }
4607   )";
4608   runDataflow(
4609       Code,
4610       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4611          ASTContext &ASTCtx) {
4612         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4613         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4614 
4615         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4616         ASSERT_THAT(FooDecl, NotNull());
4617 
4618         auto &FooVal = getFormula(*FooDecl, Env);
4619         EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4620       },
4621       {BuiltinOptions{ContextSensitiveOptions{}}});
4622 }
4623 
4624 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
4625   std::string Code = R"(
4626     bool GiveBool();
4627     void SetBool(bool &Var, bool Val) { Var = Val; }
4628 
4629     void target() {
4630       bool Foo = GiveBool();
4631       bool Bar = GiveBool();
4632       SetBool(Foo, true);
4633       SetBool(Bar, false);
4634       // [[p]]
4635     }
4636   )";
4637   runDataflow(
4638       Code,
4639       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4640          ASTContext &ASTCtx) {
4641         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4642         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4643         auto &A = Env.arena();
4644 
4645         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4646         ASSERT_THAT(FooDecl, NotNull());
4647 
4648         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4649         ASSERT_THAT(BarDecl, NotNull());
4650 
4651         auto &FooVal = getFormula(*FooDecl, Env);
4652         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4653         EXPECT_FALSE(Env.flowConditionImplies(A.makeNot(FooVal)));
4654 
4655         auto &BarVal = getFormula(*BarDecl, Env);
4656         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4657         EXPECT_TRUE(Env.flowConditionImplies(A.makeNot(BarVal)));
4658       },
4659       {BuiltinOptions{ContextSensitiveOptions{}}});
4660 }
4661 
4662 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
4663   std::string Code = R"(
4664     bool GiveBool();
4665     void SetBool1(bool &Var) { Var = true; }
4666     void SetBool2(bool &Var) { SetBool1(Var); }
4667 
4668     void target() {
4669       bool Foo = GiveBool();
4670       SetBool2(Foo);
4671       // [[p]]
4672     }
4673   )";
4674   runDataflow(
4675       Code,
4676       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4677          ASTContext &ASTCtx) {
4678         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4679         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4680 
4681         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4682         ASSERT_THAT(FooDecl, NotNull());
4683 
4684         auto &FooVal = getFormula(*FooDecl, Env);
4685         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4686         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4687       },
4688       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
4689 }
4690 
4691 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
4692   std::string Code = R"(
4693     bool GiveBool();
4694     void SetBool1(bool &Var) { Var = true; }
4695     void SetBool2(bool &Var) { SetBool1(Var); }
4696 
4697     void target() {
4698       bool Foo = GiveBool();
4699       SetBool2(Foo);
4700       // [[p]]
4701     }
4702   )";
4703   runDataflow(
4704       Code,
4705       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4706          ASTContext &ASTCtx) {
4707         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4708         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4709 
4710         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4711         ASSERT_THAT(FooDecl, NotNull());
4712 
4713         auto &FooVal = getFormula(*FooDecl, Env);
4714         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4715       },
4716       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4717 }
4718 
4719 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
4720   std::string Code = R"(
4721     bool GiveBool();
4722     void SetBool1(bool &Var) { Var = true; }
4723     void SetBool2(bool &Var) { SetBool1(Var); }
4724     void SetBool3(bool &Var) { SetBool2(Var); }
4725 
4726     void target() {
4727       bool Foo = GiveBool();
4728       SetBool3(Foo);
4729       // [[p]]
4730     }
4731   )";
4732   runDataflow(
4733       Code,
4734       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4735          ASTContext &ASTCtx) {
4736         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4737         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4738 
4739         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4740         ASSERT_THAT(FooDecl, NotNull());
4741 
4742         auto &FooVal = getFormula(*FooDecl, Env);
4743         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4744         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4745       },
4746       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4747 }
4748 
4749 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
4750   std::string Code = R"(
4751     bool GiveBool();
4752     void SetBool1(bool &Var) { Var = true; }
4753     void SetBool2(bool &Var) { SetBool1(Var); }
4754     void SetBool3(bool &Var) { SetBool2(Var); }
4755 
4756     void target() {
4757       bool Foo = GiveBool();
4758       SetBool3(Foo);
4759       // [[p]]
4760     }
4761   )";
4762   runDataflow(
4763       Code,
4764       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4765          ASTContext &ASTCtx) {
4766         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4767         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4768 
4769         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4770         ASSERT_THAT(FooDecl, NotNull());
4771 
4772         auto &FooVal = getFormula(*FooDecl, Env);
4773         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4774       },
4775       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
4776 }
4777 
4778 TEST(TransferTest, ContextSensitiveMutualRecursion) {
4779   std::string Code = R"(
4780     bool Pong(bool X, bool Y);
4781 
4782     bool Ping(bool X, bool Y) {
4783       if (X) {
4784         return Y;
4785       } else {
4786         return Pong(!X, Y);
4787       }
4788     }
4789 
4790     bool Pong(bool X, bool Y) {
4791       if (Y) {
4792         return X;
4793       } else {
4794         return Ping(X, !Y);
4795       }
4796     }
4797 
4798     void target() {
4799       bool Foo = Ping(false, false);
4800       // [[p]]
4801     }
4802   )";
4803   runDataflow(
4804       Code,
4805       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4806          ASTContext &ASTCtx) {
4807         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4808         // The analysis doesn't crash...
4809         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4810 
4811         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4812         ASSERT_THAT(FooDecl, NotNull());
4813 
4814         auto &FooVal = getFormula(*FooDecl, Env);
4815         // ... but it also can't prove anything here.
4816         EXPECT_FALSE(Env.flowConditionImplies(FooVal));
4817         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4818       },
4819       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
4820 }
4821 
4822 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
4823   std::string Code = R"(
4824     void SetBools(bool &Var1, bool &Var2) {
4825       Var1 = true;
4826       Var2 = false;
4827     }
4828 
4829     void target() {
4830       bool Foo = false;
4831       bool Bar = true;
4832       SetBools(Foo, Bar);
4833       // [[p]]
4834     }
4835   )";
4836   runDataflow(
4837       Code,
4838       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4839          ASTContext &ASTCtx) {
4840         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4841         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4842 
4843         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4844         ASSERT_THAT(FooDecl, NotNull());
4845 
4846         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4847         ASSERT_THAT(BarDecl, NotNull());
4848 
4849         auto &FooVal = getFormula(*FooDecl, Env);
4850         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4851         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4852 
4853         auto &BarVal = getFormula(*BarDecl, Env);
4854         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4855         EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal)));
4856       },
4857       {BuiltinOptions{ContextSensitiveOptions{}}});
4858 }
4859 
4860 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
4861   std::string Code = R"(
4862     void IfCond(bool Cond, bool &Then, bool &Else) {
4863       if (Cond) {
4864         Then = true;
4865       } else {
4866         Else = true;
4867       }
4868     }
4869 
4870     void target() {
4871       bool Foo = false;
4872       bool Bar = false;
4873       bool Baz = false;
4874       IfCond(Foo, Bar, Baz);
4875       // [[p]]
4876     }
4877   )";
4878   runDataflow(
4879       Code,
4880       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4881          ASTContext &ASTCtx) {
4882         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4883         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4884 
4885         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4886         ASSERT_THAT(BarDecl, NotNull());
4887 
4888         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4889         ASSERT_THAT(BazDecl, NotNull());
4890 
4891         auto &BarVal = getFormula(*BarDecl, Env);
4892         EXPECT_FALSE(Env.flowConditionImplies(BarVal));
4893         EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(BarVal)));
4894 
4895         auto &BazVal = getFormula(*BazDecl, Env);
4896         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
4897         EXPECT_FALSE(Env.flowConditionImplies(Env.arena().makeNot(BazVal)));
4898       },
4899       {BuiltinOptions{ContextSensitiveOptions{}}});
4900 }
4901 
4902 TEST(TransferTest, ContextSensitiveReturnVoid) {
4903   std::string Code = R"(
4904     void Noop() { return; }
4905 
4906     void target() {
4907       Noop();
4908       // [[p]]
4909     }
4910   )";
4911   runDataflow(
4912       Code,
4913       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4914          ASTContext &ASTCtx) {
4915         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4916         // This just tests that the analysis doesn't crash.
4917       },
4918       {BuiltinOptions{ContextSensitiveOptions{}}});
4919 }
4920 
4921 TEST(TransferTest, ContextSensitiveReturnTrue) {
4922   std::string Code = R"(
4923     bool GiveBool() { return true; }
4924 
4925     void target() {
4926       bool Foo = GiveBool();
4927       // [[p]]
4928     }
4929   )";
4930   runDataflow(
4931       Code,
4932       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4933          ASTContext &ASTCtx) {
4934         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4935         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4936 
4937         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4938         ASSERT_THAT(FooDecl, NotNull());
4939 
4940         auto &FooVal = getFormula(*FooDecl, Env);
4941         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
4942       },
4943       {BuiltinOptions{ContextSensitiveOptions{}}});
4944 }
4945 
4946 TEST(TransferTest, ContextSensitiveReturnFalse) {
4947   std::string Code = R"(
4948     bool GiveBool() { return false; }
4949 
4950     void target() {
4951       bool Foo = GiveBool();
4952       // [[p]]
4953     }
4954   )";
4955   runDataflow(
4956       Code,
4957       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4958          ASTContext &ASTCtx) {
4959         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4960         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4961 
4962         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4963         ASSERT_THAT(FooDecl, NotNull());
4964 
4965         auto &FooVal = getFormula(*FooDecl, Env);
4966         EXPECT_TRUE(Env.flowConditionImplies(Env.arena().makeNot(FooVal)));
4967       },
4968       {BuiltinOptions{ContextSensitiveOptions{}}});
4969 }
4970 
4971 TEST(TransferTest, ContextSensitiveReturnArg) {
4972   std::string Code = R"(
4973     bool GiveBool();
4974     bool GiveBack(bool Arg) { return Arg; }
4975 
4976     void target() {
4977       bool Foo = GiveBool();
4978       bool Bar = GiveBack(Foo);
4979       bool Baz = Foo == Bar;
4980       // [[p]]
4981     }
4982   )";
4983   runDataflow(
4984       Code,
4985       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4986          ASTContext &ASTCtx) {
4987         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4988         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4989 
4990         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4991         ASSERT_THAT(BazDecl, NotNull());
4992 
4993         auto &BazVal = getFormula(*BazDecl, Env);
4994         EXPECT_TRUE(Env.flowConditionImplies(BazVal));
4995       },
4996       {BuiltinOptions{ContextSensitiveOptions{}}});
4997 }
4998 
4999 TEST(TransferTest, ContextSensitiveReturnInt) {
5000   std::string Code = R"(
5001     int identity(int x) { return x; }
5002 
5003     void target() {
5004       int y = identity(42);
5005       // [[p]]
5006     }
5007   )";
5008   runDataflow(
5009       Code,
5010       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5011          ASTContext &ASTCtx) {
5012         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5013         // This just tests that the analysis doesn't crash.
5014       },
5015       {BuiltinOptions{ContextSensitiveOptions{}}});
5016 }
5017 
5018 TEST(TransferTest, ContextSensitiveMethodLiteral) {
5019   std::string Code = R"(
5020     class MyClass {
5021     public:
5022       bool giveBool() { return true; }
5023     };
5024 
5025     void target() {
5026       MyClass MyObj;
5027       bool Foo = MyObj.giveBool();
5028       // [[p]]
5029     }
5030   )";
5031   runDataflow(
5032       Code,
5033       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5034          ASTContext &ASTCtx) {
5035         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5036         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5037 
5038         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5039         ASSERT_THAT(FooDecl, NotNull());
5040 
5041         auto &FooVal = getFormula(*FooDecl, Env);
5042         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5043       },
5044       {BuiltinOptions{ContextSensitiveOptions{}}});
5045 }
5046 
5047 TEST(TransferTest, ContextSensitiveMethodGetter) {
5048   std::string Code = R"(
5049     class MyClass {
5050     public:
5051       bool getField() { return Field; }
5052 
5053       bool Field;
5054     };
5055 
5056     void target() {
5057       MyClass MyObj;
5058       MyObj.Field = true;
5059       bool Foo = MyObj.getField();
5060       // [[p]]
5061     }
5062   )";
5063   runDataflow(
5064       Code,
5065       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5066          ASTContext &ASTCtx) {
5067         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5068         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5069 
5070         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5071         ASSERT_THAT(FooDecl, NotNull());
5072 
5073         auto &FooVal = getFormula(*FooDecl, Env);
5074         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5075       },
5076       {BuiltinOptions{ContextSensitiveOptions{}}});
5077 }
5078 
5079 TEST(TransferTest, ContextSensitiveMethodSetter) {
5080   std::string Code = R"(
5081     class MyClass {
5082     public:
5083       void setField(bool Val) { Field = Val; }
5084 
5085       bool Field;
5086     };
5087 
5088     void target() {
5089       MyClass MyObj;
5090       MyObj.setField(true);
5091       bool Foo = MyObj.Field;
5092       // [[p]]
5093     }
5094   )";
5095   runDataflow(
5096       Code,
5097       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5098          ASTContext &ASTCtx) {
5099         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5100         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5101 
5102         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5103         ASSERT_THAT(FooDecl, NotNull());
5104 
5105         auto &FooVal = getFormula(*FooDecl, Env);
5106         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5107       },
5108       {BuiltinOptions{ContextSensitiveOptions{}}});
5109 }
5110 
5111 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
5112   std::string Code = R"(
5113     class MyClass {
5114     public:
5115       bool getField() { return Field; }
5116       void setField(bool Val) { Field = Val; }
5117 
5118     private:
5119       bool Field;
5120     };
5121 
5122     void target() {
5123       MyClass MyObj;
5124       MyObj.setField(true);
5125       bool Foo = MyObj.getField();
5126       // [[p]]
5127     }
5128   )";
5129   runDataflow(
5130       Code,
5131       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5132          ASTContext &ASTCtx) {
5133         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5134         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5135 
5136         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5137         ASSERT_THAT(FooDecl, NotNull());
5138 
5139         auto &FooVal = getFormula(*FooDecl, Env);
5140         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5141       },
5142       {BuiltinOptions{ContextSensitiveOptions{}}});
5143 }
5144 
5145 
5146 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
5147   std::string Code = R"(
5148     class MyClass {
5149     public:
5150       void Inner() { MyField = true; }
5151       void Outer() { Inner(); }
5152 
5153       bool MyField;
5154     };
5155 
5156     void target() {
5157       MyClass MyObj;
5158       MyObj.Outer();
5159       bool Foo = MyObj.MyField;
5160       // [[p]]
5161     }
5162   )";
5163   runDataflow(
5164       Code,
5165       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5166          ASTContext &ASTCtx) {
5167         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5168         ;
5169         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5170 
5171         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5172         ASSERT_THAT(FooDecl, NotNull());
5173 
5174         auto &FooVal = getFormula(*FooDecl, Env);
5175         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5176       },
5177       {BuiltinOptions{ContextSensitiveOptions{}}});
5178 }
5179 
5180 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
5181   std::string Code = R"(
5182     class MyClass {
5183     public:
5184       bool Inner() { return MyField; }
5185       bool Outer() { return Inner(); }
5186 
5187       bool MyField;
5188     };
5189 
5190     void target() {
5191       MyClass MyObj;
5192       MyObj.MyField = true;
5193       bool Foo = MyObj.Outer();
5194       // [[p]]
5195     }
5196   )";
5197   runDataflow(
5198       Code,
5199       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5200          ASTContext &ASTCtx) {
5201         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5202         ;
5203         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5204 
5205         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5206         ASSERT_THAT(FooDecl, NotNull());
5207 
5208         auto &FooVal = getFormula(*FooDecl, Env);
5209         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5210       },
5211       {BuiltinOptions{ContextSensitiveOptions{}}});
5212 }
5213 
5214 TEST(TransferTest, ContextSensitiveConstructorBody) {
5215   std::string Code = R"(
5216     class MyClass {
5217     public:
5218       MyClass() { MyField = true; }
5219 
5220       bool MyField;
5221     };
5222 
5223     void target() {
5224       MyClass MyObj;
5225       bool Foo = MyObj.MyField;
5226       // [[p]]
5227     }
5228   )";
5229   runDataflow(
5230       Code,
5231       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5232          ASTContext &ASTCtx) {
5233         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5234         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5235 
5236         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5237         ASSERT_THAT(FooDecl, NotNull());
5238 
5239         auto &FooVal = getFormula(*FooDecl, Env);
5240         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5241       },
5242       {BuiltinOptions{ContextSensitiveOptions{}}});
5243 }
5244 
5245 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
5246   std::string Code = R"(
5247     class MyClass {
5248     public:
5249       MyClass() : MyField(true) {}
5250 
5251       bool MyField;
5252     };
5253 
5254     void target() {
5255       MyClass MyObj;
5256       bool Foo = MyObj.MyField;
5257       // [[p]]
5258     }
5259   )";
5260   runDataflow(
5261       Code,
5262       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5263          ASTContext &ASTCtx) {
5264         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5265         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5266 
5267         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5268         ASSERT_THAT(FooDecl, NotNull());
5269 
5270         auto &FooVal = getFormula(*FooDecl, Env);
5271         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5272       },
5273       {BuiltinOptions{ContextSensitiveOptions{}}});
5274 }
5275 
5276 TEST(TransferTest, ContextSensitiveConstructorDefault) {
5277   std::string Code = R"(
5278     class MyClass {
5279     public:
5280       MyClass() = default;
5281 
5282       bool MyField = true;
5283     };
5284 
5285     void target() {
5286       MyClass MyObj;
5287       bool Foo = MyObj.MyField;
5288       // [[p]]
5289     }
5290   )";
5291   runDataflow(
5292       Code,
5293       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5294          ASTContext &ASTCtx) {
5295         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5296         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5297 
5298         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5299         ASSERT_THAT(FooDecl, NotNull());
5300 
5301         auto &FooVal = getFormula(*FooDecl, Env);
5302         EXPECT_TRUE(Env.flowConditionImplies(FooVal));
5303       },
5304       {BuiltinOptions{ContextSensitiveOptions{}}});
5305 }
5306 
5307 TEST(TransferTest, UnnamedBitfieldInitializer) {
5308   std::string Code = R"(
5309     struct B {};
5310     struct A {
5311       unsigned a;
5312       unsigned : 4;
5313       unsigned c;
5314       B b;
5315     };
5316     void target() {
5317       A a = {};
5318       A test = a;
5319       (void)test.c;
5320     }
5321   )";
5322   runDataflow(
5323       Code,
5324       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5325          ASTContext &ASTCtx) {
5326         // This doesn't need a body because this test was crashing the framework
5327         // before handling correctly Unnamed bitfields in `InitListExpr`.
5328       });
5329 }
5330 
5331 // Repro for a crash that used to occur with chained short-circuiting logical
5332 // operators.
5333 TEST(TransferTest, ChainedLogicalOps) {
5334   std::string Code = R"(
5335     bool target() {
5336       bool b = true || false || false || false;
5337       // [[p]]
5338       return b;
5339     }
5340   )";
5341   runDataflow(
5342       Code,
5343       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5344          ASTContext &ASTCtx) {
5345         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5346         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
5347         EXPECT_TRUE(Env.flowConditionImplies(B));
5348       });
5349 }
5350 
5351 // Repro for a crash that used to occur when we call a `noreturn` function
5352 // within one of the operands of a `&&` or `||` operator.
5353 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
5354   std::string Code = R"(
5355     __attribute__((noreturn)) int doesnt_return();
5356     bool some_condition();
5357     void target(bool b1, bool b2) {
5358       // Neither of these should crash. In addition, if we don't terminate the
5359       // program, we know that the operators need to trigger the short-circuit
5360       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
5361       // will be true.
5362       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
5363       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
5364 
5365       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
5366       // entire expression unreachable. So we know that in both of the following
5367       // cases, if `target()` terminates, the `else` branch was taken.
5368       bool NoreturnOnLhsMakesAndUnreachable = false;
5369       if (some_condition())
5370          doesnt_return() > 0 && some_condition();
5371       else
5372          NoreturnOnLhsMakesAndUnreachable = true;
5373 
5374       bool NoreturnOnLhsMakesOrUnreachable = false;
5375       if (some_condition())
5376          doesnt_return() > 0 || some_condition();
5377       else
5378          NoreturnOnLhsMakesOrUnreachable = true;
5379 
5380       // [[p]]
5381     }
5382   )";
5383   runDataflow(
5384       Code,
5385       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5386          ASTContext &ASTCtx) {
5387         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5388         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5389         auto &A = Env.arena();
5390 
5391         // Check that [[p]] is reachable with a non-false flow condition.
5392         EXPECT_FALSE(Env.flowConditionImplies(A.makeLiteral(false)));
5393 
5394         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula();
5395         EXPECT_TRUE(Env.flowConditionImplies(A.makeNot(B1)));
5396 
5397         auto &NoreturnOnRhsOfAnd =
5398             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula();
5399         EXPECT_TRUE(Env.flowConditionImplies(A.makeNot(NoreturnOnRhsOfAnd)));
5400 
5401         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula();
5402         EXPECT_TRUE(Env.flowConditionImplies(B2));
5403 
5404         auto &NoreturnOnRhsOfOr =
5405             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr")
5406                 .formula();
5407         EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnRhsOfOr));
5408 
5409         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
5410             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula();
5411         EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesAndUnreachable));
5412 
5413         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
5414             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula();
5415         EXPECT_TRUE(Env.flowConditionImplies(NoreturnOnLhsMakesOrUnreachable));
5416       });
5417 }
5418 
5419 TEST(TransferTest, NewExpressions) {
5420   std::string Code = R"(
5421     void target() {
5422       int *p = new int(42);
5423       // [[after_new]]
5424     }
5425   )";
5426   runDataflow(
5427       Code,
5428       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5429          ASTContext &ASTCtx) {
5430         const Environment &Env =
5431             getEnvironmentAtAnnotation(Results, "after_new");
5432 
5433         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5434 
5435         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
5436       });
5437 }
5438 
5439 TEST(TransferTest, NewExpressions_Structs) {
5440   std::string Code = R"(
5441     struct Inner {
5442       int InnerField;
5443     };
5444 
5445     struct Outer {
5446       Inner OuterField;
5447     };
5448 
5449     void target() {
5450       Outer *p = new Outer;
5451       // Access the fields to make sure the analysis actually generates children
5452       // for them in the `RecordStorageLocation` and `RecordValue`.
5453       p->OuterField.InnerField;
5454       // [[after_new]]
5455     }
5456   )";
5457   runDataflow(
5458       Code,
5459       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5460          ASTContext &ASTCtx) {
5461         const Environment &Env =
5462             getEnvironmentAtAnnotation(Results, "after_new");
5463 
5464         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
5465         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
5466 
5467         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5468 
5469         auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
5470         auto &OuterFieldLoc =
5471             *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
5472         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
5473 
5474         // Values for the struct and all fields exist after the new.
5475         EXPECT_THAT(Env.getValue(OuterLoc), NotNull());
5476         EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull());
5477         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
5478       });
5479 }
5480 
5481 TEST(TransferTest, FunctionToPointerDecayHasValue) {
5482   std::string Code = R"(
5483     struct A { static void static_member_func(); };
5484     void target() {
5485       // To check that we're treating function-to-pointer decay correctly,
5486       // create two pointers, then verify they refer to the same storage
5487       // location.
5488       // We need to do the test this way because even if an initializer (in this
5489       // case, the function-to-pointer decay) does not create a value, we still
5490       // create a value for the variable.
5491       void (*non_member_p1)() = target;
5492       void (*non_member_p2)() = target;
5493 
5494       // Do the same thing but for a static member function.
5495       void (*member_p1)() = A::static_member_func;
5496       void (*member_p2)() = A::static_member_func;
5497       // [[p]]
5498     }
5499   )";
5500   runDataflow(
5501       Code,
5502       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5503          ASTContext &ASTCtx) {
5504         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5505 
5506         auto &NonMemberP1 =
5507             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
5508         auto &NonMemberP2 =
5509             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
5510         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
5511 
5512         auto &MemberP1 =
5513             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
5514         auto &MemberP2 =
5515             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
5516         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
5517       });
5518 }
5519 
5520 // Check that a builtin function is not associated with a value. (It's only
5521 // possible to call builtin functions directly, not take their address.)
5522 TEST(TransferTest, BuiltinFunctionModeled) {
5523   std::string Code = R"(
5524     void target() {
5525       __builtin_expect(0, 0);
5526       // [[p]]
5527     }
5528   )";
5529   runDataflow(
5530       Code,
5531       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5532          ASTContext &ASTCtx) {
5533         using ast_matchers::selectFirst;
5534         using ast_matchers::match;
5535         using ast_matchers::traverse;
5536         using ast_matchers::implicitCastExpr;
5537         using ast_matchers::hasCastKind;
5538 
5539         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5540 
5541         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
5542             "implicit_cast",
5543             match(traverse(TK_AsIs,
5544                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
5545                                .bind("implicit_cast")),
5546                   ASTCtx));
5547 
5548         ASSERT_THAT(ImplicitCast, NotNull());
5549         EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull());
5550       });
5551 }
5552 
5553 // Check that fields of anonymous records are modeled.
5554 TEST(TransferTest, AnonymousStruct) {
5555   std::string Code = R"(
5556     struct S {
5557       struct {
5558         bool b;
5559       };
5560     };
5561     void target() {
5562       S s;
5563       s.b = true;
5564       // [[p]]
5565     }
5566   )";
5567   runDataflow(
5568       Code,
5569       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5570          ASTContext &ASTCtx) {
5571         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5572         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5573         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
5574         const IndirectFieldDecl *IndirectField =
5575             findIndirectFieldDecl(ASTCtx, "b");
5576 
5577         auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl));
5578         auto &AnonStruct = *cast<RecordStorageLocation>(
5579             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
5580 
5581         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
5582         ASSERT_TRUE(Env.flowConditionImplies(B->formula()));
5583       });
5584 }
5585 
5586 TEST(TransferTest, AnonymousStructWithInitializer) {
5587   std::string Code = R"(
5588     struct target {
5589       target() {
5590         (void)0;
5591         // [[p]]
5592       }
5593       struct {
5594         bool b = true;
5595       };
5596     };
5597   )";
5598   runDataflow(
5599       Code,
5600       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5601          ASTContext &ASTCtx) {
5602         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5603         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
5604         const IndirectFieldDecl *IndirectField =
5605             findIndirectFieldDecl(ASTCtx, "b");
5606 
5607         auto *ThisLoc =
5608             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
5609         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
5610             *cast<ValueDecl>(IndirectField->chain().front())));
5611 
5612         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
5613         ASSERT_TRUE(Env.flowConditionImplies(B->formula()));
5614       });
5615 }
5616 
5617 TEST(TransferTest, AnonymousStructWithReferenceField) {
5618   std::string Code = R"(
5619     int global_i = 0;
5620     struct target {
5621       target() {
5622         (void)0;
5623         // [[p]]
5624       }
5625       struct {
5626         int &i = global_i;
5627       };
5628     };
5629   )";
5630   runDataflow(
5631       Code,
5632       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5633          ASTContext &ASTCtx) {
5634         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5635         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
5636         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
5637         const IndirectFieldDecl *IndirectField =
5638             findIndirectFieldDecl(ASTCtx, "i");
5639 
5640         auto *ThisLoc =
5641             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
5642         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
5643             *cast<ValueDecl>(IndirectField->chain().front())));
5644 
5645         ASSERT_EQ(AnonStruct.getChild(*IDecl),
5646                   Env.getStorageLocation(*GlobalIDecl));
5647       });
5648 }
5649 
5650 } // namespace
5651