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