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