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