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