xref: /llvm-project/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp (revision 526c9b7e37fa12abc17eebc68f21c1d213477ba8)
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.proves(BarValThen));
3799 
3800         auto &BarValElse = getFormula(*BarDecl, EnvElse);
3801         EXPECT_TRUE(EnvElse.proves(EnvElse.arena().makeNot(BarValElse)));
3802       });
3803 }
3804 
3805 TEST(TransferTest, BooleanInequality) {
3806   std::string Code = R"(
3807     void target(bool Bar) {
3808       bool Foo = true;
3809       if (Bar != Foo) {
3810         (void)0;
3811         /*[[p-then]]*/
3812       } else {
3813         (void)0;
3814         /*[[p-else]]*/
3815       }
3816     }
3817   )";
3818   runDataflow(
3819       Code,
3820       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3821          ASTContext &ASTCtx) {
3822         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-then", "p-else"));
3823         const Environment &EnvThen =
3824             getEnvironmentAtAnnotation(Results, "p-then");
3825         const Environment &EnvElse =
3826             getEnvironmentAtAnnotation(Results, "p-else");
3827 
3828         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3829         ASSERT_THAT(BarDecl, NotNull());
3830 
3831         auto &BarValThen = getFormula(*BarDecl, EnvThen);
3832         EXPECT_TRUE(EnvThen.proves(EnvThen.arena().makeNot(BarValThen)));
3833 
3834         auto &BarValElse = getFormula(*BarDecl, EnvElse);
3835         EXPECT_TRUE(EnvElse.proves(BarValElse));
3836       });
3837 }
3838 
3839 TEST(TransferTest, IntegerLiteralEquality) {
3840   std::string Code = R"(
3841     void target() {
3842       bool equal = (42 == 42);
3843       // [[p]]
3844     }
3845   )";
3846   runDataflow(
3847       Code,
3848       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3849          ASTContext &ASTCtx) {
3850         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3851 
3852         auto &Equal =
3853             getValueForDecl<BoolValue>(ASTCtx, Env, "equal").formula();
3854         EXPECT_TRUE(Env.proves(Equal));
3855       });
3856 }
3857 
3858 TEST(TransferTest, CorrelatedBranches) {
3859   std::string Code = R"(
3860     void target(bool B, bool C) {
3861       if (B) {
3862         return;
3863       }
3864       (void)0;
3865       /*[[p0]]*/
3866       if (C) {
3867         B = true;
3868         /*[[p1]]*/
3869       }
3870       if (B) {
3871         (void)0;
3872         /*[[p2]]*/
3873       }
3874     }
3875   )";
3876   runDataflow(
3877       Code,
3878       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3879          ASTContext &ASTCtx) {
3880         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p0", "p1", "p2"));
3881 
3882         const ValueDecl *CDecl = findValueDecl(ASTCtx, "C");
3883         ASSERT_THAT(CDecl, NotNull());
3884 
3885         {
3886           const Environment &Env = getEnvironmentAtAnnotation(Results, "p0");
3887           const ValueDecl *BDecl = findValueDecl(ASTCtx, "B");
3888           ASSERT_THAT(BDecl, NotNull());
3889           auto &BVal = getFormula(*BDecl, Env);
3890 
3891           EXPECT_TRUE(Env.proves(Env.arena().makeNot(BVal)));
3892         }
3893 
3894         {
3895           const Environment &Env = getEnvironmentAtAnnotation(Results, "p1");
3896           auto &CVal = getFormula(*CDecl, Env);
3897           EXPECT_TRUE(Env.proves(CVal));
3898         }
3899 
3900         {
3901           const Environment &Env = getEnvironmentAtAnnotation(Results, "p2");
3902           auto &CVal = getFormula(*CDecl, Env);
3903           EXPECT_TRUE(Env.proves(CVal));
3904         }
3905       });
3906 }
3907 
3908 TEST(TransferTest, LoopWithAssignmentConverges) {
3909   std::string Code = R"(
3910     bool foo();
3911 
3912     void target() {
3913        do {
3914         bool Bar = foo();
3915         if (Bar) break;
3916         (void)Bar;
3917         /*[[p]]*/
3918       } while (true);
3919     }
3920   )";
3921   // The key property that we are verifying is implicit in `runDataflow` --
3922   // namely, that the analysis succeeds, rather than hitting the maximum number
3923   // of iterations.
3924   runDataflow(
3925       Code,
3926       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3927          ASTContext &ASTCtx) {
3928         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3929         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3930 
3931         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3932         ASSERT_THAT(BarDecl, NotNull());
3933 
3934         auto &BarVal = getFormula(*BarDecl, Env);
3935         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
3936       });
3937 }
3938 
3939 TEST(TransferTest, LoopWithStagedAssignments) {
3940   std::string Code = R"(
3941     bool foo();
3942 
3943     void target() {
3944       bool Bar = false;
3945       bool Err = false;
3946       while (foo()) {
3947         if (Bar)
3948           Err = true;
3949         Bar = true;
3950         /*[[p]]*/
3951       }
3952     }
3953   )";
3954   runDataflow(
3955       Code,
3956       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3957          ASTContext &ASTCtx) {
3958         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3959         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3960 
3961         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3962         ASSERT_THAT(BarDecl, NotNull());
3963         const ValueDecl *ErrDecl = findValueDecl(ASTCtx, "Err");
3964         ASSERT_THAT(ErrDecl, NotNull());
3965 
3966         auto &BarVal = getFormula(*BarDecl, Env);
3967         auto &ErrVal = getFormula(*ErrDecl, Env);
3968         EXPECT_TRUE(Env.proves(BarVal));
3969         // An unsound analysis, for example only evaluating the loop once, can
3970         // conclude that `Err` is false. So, we test that this conclusion is not
3971         // reached.
3972         EXPECT_FALSE(Env.proves(Env.arena().makeNot(ErrVal)));
3973       });
3974 }
3975 
3976 TEST(TransferTest, LoopWithReferenceAssignmentConverges) {
3977   std::string Code = R"(
3978     bool &foo();
3979 
3980     void target() {
3981        do {
3982         bool& Bar = foo();
3983         if (Bar) break;
3984         (void)Bar;
3985         /*[[p]]*/
3986       } while (true);
3987     }
3988   )";
3989   // The key property that we are verifying is that the analysis succeeds,
3990   // rather than hitting the maximum number of iterations.
3991   runDataflow(
3992       Code,
3993       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
3994          ASTContext &ASTCtx) {
3995         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
3996         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
3997 
3998         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
3999         ASSERT_THAT(BarDecl, NotNull());
4000 
4001         auto &BarVal = getFormula(*BarDecl, Env);
4002         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
4003       });
4004 }
4005 
4006 TEST(TransferTest, LoopWithStructReferenceAssignmentConverges) {
4007   std::string Code = R"(
4008     struct Lookup {
4009       int x;
4010     };
4011 
4012     void target(Lookup val, bool b) {
4013       const Lookup* l = nullptr;
4014       while (b) {
4015         l = &val;
4016         /*[[p-inner]]*/
4017       }
4018       (void)0;
4019       /*[[p-outer]]*/
4020     }
4021   )";
4022   // The key property that we are verifying is implicit in `runDataflow` --
4023   // namely, that the analysis succeeds, rather than hitting the maximum number
4024   // of iterations.
4025   runDataflow(
4026       Code,
4027       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4028          ASTContext &ASTCtx) {
4029         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p-inner", "p-outer"));
4030         const Environment &InnerEnv =
4031             getEnvironmentAtAnnotation(Results, "p-inner");
4032         const Environment &OuterEnv =
4033             getEnvironmentAtAnnotation(Results, "p-outer");
4034 
4035         const ValueDecl *ValDecl = findValueDecl(ASTCtx, "val");
4036         ASSERT_THAT(ValDecl, NotNull());
4037 
4038         const ValueDecl *LDecl = findValueDecl(ASTCtx, "l");
4039         ASSERT_THAT(LDecl, NotNull());
4040 
4041         // Inner.
4042         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
4043         ASSERT_THAT(LVal, NotNull());
4044 
4045         EXPECT_EQ(&LVal->getPointeeLoc(),
4046                   InnerEnv.getStorageLocation(*ValDecl));
4047 
4048         // Outer.
4049         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
4050         ASSERT_THAT(LVal, NotNull());
4051 
4052         // The loop body may not have been executed, so we should not conclude
4053         // that `l` points to `val`.
4054         EXPECT_NE(&LVal->getPointeeLoc(),
4055                   OuterEnv.getStorageLocation(*ValDecl));
4056       });
4057 }
4058 
4059 TEST(TransferTest, LoopDereferencingChangingPointerConverges) {
4060   std::string Code = R"cc(
4061     bool some_condition();
4062 
4063     void target(int i1, int i2) {
4064       int *p = &i1;
4065       while (true) {
4066         (void)*p;
4067         if (some_condition())
4068           p = &i1;
4069         else
4070           p = &i2;
4071       }
4072     }
4073   )cc";
4074   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4075 }
4076 
4077 TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
4078   std::string Code = R"cc(
4079     struct Lookup {
4080       int x;
4081     };
4082 
4083     bool some_condition();
4084 
4085     void target(Lookup l1, Lookup l2) {
4086       Lookup *l = &l1;
4087       while (true) {
4088         (void)l->x;
4089         if (some_condition())
4090           l = &l1;
4091         else
4092           l = &l2;
4093       }
4094     }
4095   )cc";
4096   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4097 }
4098 
4099 TEST(TransferTest, LoopWithShortCircuitedConditionConverges) {
4100   std::string Code = R"cc(
4101     bool foo();
4102 
4103     void target() {
4104       bool c = false;
4105       while (foo() || foo()) {
4106         c = true;
4107       }
4108     }
4109   )cc";
4110   ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
4111 }
4112 
4113 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
4114   std::string Code = R"(
4115     union Union {
4116       int A;
4117       float B;
4118     };
4119 
4120     void foo() {
4121       Union A;
4122       Union B;
4123       A = B;
4124     }
4125   )";
4126   // This is a crash regression test when calling the transfer function on a
4127   // `CXXThisExpr` that refers to a union.
4128   runDataflow(
4129       Code,
4130       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
4131          ASTContext &) {},
4132       LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator=");
4133 }
4134 
4135 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
4136   std::string Code = R"(
4137     struct A {
4138       int Foo;
4139       int Bar;
4140     };
4141 
4142     void target() {
4143       int Qux;
4144       A Baz;
4145       Baz.Foo = Qux;
4146       auto &FooRef = Baz.Foo;
4147       auto &BarRef = Baz.Bar;
4148       auto &[BoundFooRef, BoundBarRef] = Baz;
4149       // [[p]]
4150     }
4151   )";
4152   runDataflow(
4153       Code,
4154       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4155          ASTContext &ASTCtx) {
4156         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4157         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4158 
4159         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4160         ASSERT_THAT(FooRefDecl, NotNull());
4161 
4162         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4163         ASSERT_THAT(BarRefDecl, NotNull());
4164 
4165         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4166         ASSERT_THAT(QuxDecl, NotNull());
4167 
4168         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4169         ASSERT_THAT(BoundFooRefDecl, NotNull());
4170 
4171         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4172         ASSERT_THAT(BoundBarRefDecl, NotNull());
4173 
4174         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4175         ASSERT_THAT(FooRefLoc, NotNull());
4176 
4177         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4178         ASSERT_THAT(BarRefLoc, NotNull());
4179 
4180         const Value *QuxVal = Env.getValue(*QuxDecl);
4181         ASSERT_THAT(QuxVal, NotNull());
4182 
4183         const StorageLocation *BoundFooRefLoc =
4184             Env.getStorageLocation(*BoundFooRefDecl);
4185         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4186 
4187         const StorageLocation *BoundBarRefLoc =
4188             Env.getStorageLocation(*BoundBarRefDecl);
4189         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4190 
4191         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4192       });
4193 }
4194 
4195 TEST(TransferTest, StructuredBindingAssignFromStructRefMembersToRefs) {
4196   std::string Code = R"(
4197     struct A {
4198       int &Foo;
4199       int &Bar;
4200     };
4201 
4202     void target(A Baz) {
4203       int Qux;
4204       Baz.Foo = Qux;
4205       auto &FooRef = Baz.Foo;
4206       auto &BarRef = Baz.Bar;
4207       auto &[BoundFooRef, BoundBarRef] = Baz;
4208       // [[p]]
4209     }
4210   )";
4211   runDataflow(
4212       Code,
4213       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4214          ASTContext &ASTCtx) {
4215         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4216         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4217 
4218         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4219         ASSERT_THAT(FooRefDecl, NotNull());
4220 
4221         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4222         ASSERT_THAT(BarRefDecl, NotNull());
4223 
4224         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4225         ASSERT_THAT(QuxDecl, NotNull());
4226 
4227         const ValueDecl *BoundFooRefDecl = findValueDecl(ASTCtx, "BoundFooRef");
4228         ASSERT_THAT(BoundFooRefDecl, NotNull());
4229 
4230         const ValueDecl *BoundBarRefDecl = findValueDecl(ASTCtx, "BoundBarRef");
4231         ASSERT_THAT(BoundBarRefDecl, NotNull());
4232 
4233         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4234         ASSERT_THAT(FooRefLoc, NotNull());
4235 
4236         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4237         ASSERT_THAT(BarRefLoc, NotNull());
4238 
4239         const Value *QuxVal = Env.getValue(*QuxDecl);
4240         ASSERT_THAT(QuxVal, NotNull());
4241 
4242         const StorageLocation *BoundFooRefLoc =
4243             Env.getStorageLocation(*BoundFooRefDecl);
4244         EXPECT_EQ(BoundFooRefLoc, FooRefLoc);
4245 
4246         const StorageLocation *BoundBarRefLoc =
4247             Env.getStorageLocation(*BoundBarRefDecl);
4248         EXPECT_EQ(BoundBarRefLoc, BarRefLoc);
4249 
4250         EXPECT_EQ(Env.getValue(*BoundFooRefDecl), QuxVal);
4251       });
4252 }
4253 
4254 TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToInts) {
4255   std::string Code = R"(
4256     struct A {
4257       int Foo;
4258       int Bar;
4259     };
4260 
4261     void target() {
4262       int Qux;
4263       A Baz;
4264       Baz.Foo = Qux;
4265       auto &FooRef = Baz.Foo;
4266       auto &BarRef = Baz.Bar;
4267       auto [BoundFoo, BoundBar] = Baz;
4268       // [[p]]
4269     }
4270   )";
4271   runDataflow(
4272       Code,
4273       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4274          ASTContext &ASTCtx) {
4275         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4276         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4277 
4278         const ValueDecl *FooRefDecl = findValueDecl(ASTCtx, "FooRef");
4279         ASSERT_THAT(FooRefDecl, NotNull());
4280 
4281         const ValueDecl *BarRefDecl = findValueDecl(ASTCtx, "BarRef");
4282         ASSERT_THAT(BarRefDecl, NotNull());
4283 
4284         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4285         ASSERT_THAT(BoundFooDecl, NotNull());
4286 
4287         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4288         ASSERT_THAT(BoundBarDecl, NotNull());
4289 
4290         const ValueDecl *QuxDecl = findValueDecl(ASTCtx, "Qux");
4291         ASSERT_THAT(QuxDecl, NotNull());
4292 
4293         const StorageLocation *FooRefLoc = Env.getStorageLocation(*FooRefDecl);
4294         ASSERT_THAT(FooRefLoc, NotNull());
4295 
4296         const StorageLocation *BarRefLoc = Env.getStorageLocation(*BarRefDecl);
4297         ASSERT_THAT(BarRefLoc, NotNull());
4298 
4299         const Value *QuxVal = Env.getValue(*QuxDecl);
4300         ASSERT_THAT(QuxVal, NotNull());
4301 
4302         const StorageLocation *BoundFooLoc =
4303             Env.getStorageLocation(*BoundFooDecl);
4304         EXPECT_NE(BoundFooLoc, FooRefLoc);
4305 
4306         const StorageLocation *BoundBarLoc =
4307             Env.getStorageLocation(*BoundBarDecl);
4308         EXPECT_NE(BoundBarLoc, BarRefLoc);
4309 
4310         EXPECT_EQ(Env.getValue(*BoundFooDecl), QuxVal);
4311       });
4312 }
4313 
4314 TEST(TransferTest, StructuredBindingAssignFromTupleLikeType) {
4315   std::string Code = R"(
4316     namespace std {
4317     using size_t = int;
4318     template <class> struct tuple_size;
4319     template <std::size_t, class> struct tuple_element;
4320     template <class...> class tuple;
4321 
4322     namespace {
4323     template <class T, T v>
4324     struct size_helper { static const T value = v; };
4325     } // namespace
4326 
4327     template <class... T>
4328     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4329 
4330     template <std::size_t I, class... T>
4331     struct tuple_element<I, tuple<T...>> {
4332       using type =  __type_pack_element<I, T...>;
4333     };
4334 
4335     template <class...> class tuple {};
4336 
4337     template <std::size_t I, class... T>
4338     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4339     } // namespace std
4340 
4341     std::tuple<bool, int> makeTuple();
4342 
4343     void target(bool B) {
4344       auto [BoundFoo, BoundBar] = makeTuple();
4345       bool Baz;
4346       // Include if-then-else to test interaction of `BindingDecl` with join.
4347       if (B) {
4348         Baz = BoundFoo;
4349         (void)BoundBar;
4350         // [[p1]]
4351       } else {
4352         Baz = BoundFoo;
4353       }
4354       (void)0;
4355       // [[p2]]
4356     }
4357   )";
4358   runDataflow(
4359       Code,
4360       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4361          ASTContext &ASTCtx) {
4362         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4363         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4364 
4365         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4366         ASSERT_THAT(BoundFooDecl, NotNull());
4367 
4368         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4369         ASSERT_THAT(BoundBarDecl, NotNull());
4370 
4371         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4372         ASSERT_THAT(BazDecl, NotNull());
4373 
4374         // BindingDecls always map to references -- either lvalue or rvalue, so
4375         // we still need to skip here.
4376         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4377         ASSERT_THAT(BoundFooValue, NotNull());
4378         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4379 
4380         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4381         ASSERT_THAT(BoundBarValue, NotNull());
4382         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4383 
4384         // Test that a `DeclRefExpr` to a `BindingDecl` works as expected.
4385         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4386 
4387         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4388 
4389         // Test that `BoundFooDecl` retains the value we expect, after the join.
4390         BoundFooValue = Env2.getValue(*BoundFooDecl);
4391         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4392       });
4393 }
4394 
4395 TEST(TransferTest, StructuredBindingAssignRefFromTupleLikeType) {
4396   std::string Code = R"(
4397     namespace std {
4398     using size_t = int;
4399     template <class> struct tuple_size;
4400     template <std::size_t, class> struct tuple_element;
4401     template <class...> class tuple;
4402 
4403     namespace {
4404     template <class T, T v>
4405     struct size_helper { static const T value = v; };
4406     } // namespace
4407 
4408     template <class... T>
4409     struct tuple_size<tuple<T...>> : size_helper<std::size_t, sizeof...(T)> {};
4410 
4411     template <std::size_t I, class... T>
4412     struct tuple_element<I, tuple<T...>> {
4413       using type =  __type_pack_element<I, T...>;
4414     };
4415 
4416     template <class...> class tuple {};
4417 
4418     template <std::size_t I, class... T>
4419     typename tuple_element<I, tuple<T...>>::type get(tuple<T...>);
4420     } // namespace std
4421 
4422     std::tuple<bool, int> &getTuple();
4423 
4424     void target(bool B) {
4425       auto &[BoundFoo, BoundBar] = getTuple();
4426       bool Baz;
4427       // Include if-then-else to test interaction of `BindingDecl` with join.
4428       if (B) {
4429         Baz = BoundFoo;
4430         (void)BoundBar;
4431         // [[p1]]
4432       } else {
4433         Baz = BoundFoo;
4434       }
4435       (void)0;
4436       // [[p2]]
4437     }
4438   )";
4439   runDataflow(
4440       Code,
4441       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4442          ASTContext &ASTCtx) {
4443         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p1", "p2"));
4444         const Environment &Env1 = getEnvironmentAtAnnotation(Results, "p1");
4445 
4446         const ValueDecl *BoundFooDecl = findValueDecl(ASTCtx, "BoundFoo");
4447         ASSERT_THAT(BoundFooDecl, NotNull());
4448 
4449         const ValueDecl *BoundBarDecl = findValueDecl(ASTCtx, "BoundBar");
4450         ASSERT_THAT(BoundBarDecl, NotNull());
4451 
4452         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4453         ASSERT_THAT(BazDecl, NotNull());
4454 
4455         const Value *BoundFooValue = Env1.getValue(*BoundFooDecl);
4456         ASSERT_THAT(BoundFooValue, NotNull());
4457         EXPECT_TRUE(isa<BoolValue>(BoundFooValue));
4458 
4459         const Value *BoundBarValue = Env1.getValue(*BoundBarDecl);
4460         ASSERT_THAT(BoundBarValue, NotNull());
4461         EXPECT_TRUE(isa<IntegerValue>(BoundBarValue));
4462 
4463         // Test that a `DeclRefExpr` to a `BindingDecl` (with reference type)
4464         // works as expected. We don't test aliasing properties of the
4465         // reference, because we don't model `std::get` and so have no way to
4466         // equate separate references into the tuple.
4467         EXPECT_EQ(Env1.getValue(*BazDecl), BoundFooValue);
4468 
4469         const Environment &Env2 = getEnvironmentAtAnnotation(Results, "p2");
4470 
4471         // Test that `BoundFooDecl` retains the value we expect, after the join.
4472         BoundFooValue = Env2.getValue(*BoundFooDecl);
4473         EXPECT_EQ(Env2.getValue(*BazDecl), BoundFooValue);
4474       });
4475 }
4476 
4477 TEST(TransferTest, BinaryOperatorComma) {
4478   std::string Code = R"(
4479     void target(int Foo, int Bar) {
4480       int &Baz = (Foo, Bar);
4481       // [[p]]
4482     }
4483   )";
4484   runDataflow(
4485       Code,
4486       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4487          ASTContext &ASTCtx) {
4488         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4489         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4490 
4491         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4492         ASSERT_THAT(BarDecl, NotNull());
4493 
4494         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
4495         ASSERT_THAT(BazDecl, NotNull());
4496 
4497         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
4498         ASSERT_THAT(BarLoc, NotNull());
4499 
4500         const StorageLocation *BazLoc = Env.getStorageLocation(*BazDecl);
4501         EXPECT_EQ(BazLoc, BarLoc);
4502       });
4503 }
4504 
4505 TEST(TransferTest, IfStmtBranchExtendsFlowCondition) {
4506   std::string Code = R"(
4507     void target(bool Foo) {
4508       if (Foo) {
4509         (void)0;
4510         // [[if_then]]
4511       } else {
4512         (void)0;
4513         // [[if_else]]
4514       }
4515     }
4516   )";
4517   runDataflow(
4518       Code,
4519       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4520          ASTContext &ASTCtx) {
4521         ASSERT_THAT(Results.keys(), UnorderedElementsAre("if_then", "if_else"));
4522         const Environment &ThenEnv =
4523             getEnvironmentAtAnnotation(Results, "if_then");
4524         const Environment &ElseEnv =
4525             getEnvironmentAtAnnotation(Results, "if_else");
4526 
4527         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4528         ASSERT_THAT(FooDecl, NotNull());
4529 
4530         auto &ThenFooVal= getFormula(*FooDecl, ThenEnv);
4531         EXPECT_TRUE(ThenEnv.proves(ThenFooVal));
4532 
4533         auto &ElseFooVal = getFormula(*FooDecl, ElseEnv);
4534         EXPECT_TRUE(ElseEnv.proves(ElseEnv.arena().makeNot(ElseFooVal)));
4535       });
4536 }
4537 
4538 TEST(TransferTest, WhileStmtBranchExtendsFlowCondition) {
4539   std::string Code = R"(
4540     void target(bool Foo) {
4541       while (Foo) {
4542         (void)0;
4543         // [[loop_body]]
4544       }
4545       (void)0;
4546       // [[after_loop]]
4547     }
4548   )";
4549   runDataflow(
4550       Code,
4551       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4552          ASTContext &ASTCtx) {
4553         ASSERT_THAT(Results.keys(),
4554                     UnorderedElementsAre("loop_body", "after_loop"));
4555         const Environment &LoopBodyEnv =
4556             getEnvironmentAtAnnotation(Results, "loop_body");
4557         const Environment &AfterLoopEnv =
4558             getEnvironmentAtAnnotation(Results, "after_loop");
4559 
4560         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4561         ASSERT_THAT(FooDecl, NotNull());
4562 
4563         auto &LoopBodyFooVal = getFormula(*FooDecl, LoopBodyEnv);
4564         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
4565 
4566         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4567         EXPECT_TRUE(
4568             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
4569       });
4570 }
4571 
4572 TEST(TransferTest, DoWhileStmtBranchExtendsFlowCondition) {
4573   std::string Code = R"(
4574     void target(bool Foo) {
4575       bool Bar = true;
4576       do {
4577         (void)0;
4578         // [[loop_body]]
4579         Bar = false;
4580       } while (Foo);
4581       (void)0;
4582       // [[after_loop]]
4583     }
4584   )";
4585   runDataflow(
4586       Code,
4587       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4588          ASTContext &ASTCtx) {
4589         ASSERT_THAT(Results.keys(),
4590                     UnorderedElementsAre("loop_body", "after_loop"));
4591         const Environment &LoopBodyEnv =
4592             getEnvironmentAtAnnotation(Results, "loop_body");
4593         const Environment &AfterLoopEnv =
4594             getEnvironmentAtAnnotation(Results, "after_loop");
4595         auto &A = AfterLoopEnv.arena();
4596 
4597         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4598         ASSERT_THAT(FooDecl, NotNull());
4599 
4600         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4601         ASSERT_THAT(BarDecl, NotNull());
4602 
4603         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4604         auto &LoopBodyBarVal = getFormula(*BarDecl, LoopBodyEnv);
4605         EXPECT_TRUE(
4606             LoopBodyEnv.proves(A.makeOr(LoopBodyBarVal, LoopBodyFooVal)));
4607 
4608         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4609         auto &AfterLoopBarVal = getFormula(*BarDecl, AfterLoopEnv);
4610         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopFooVal)));
4611         EXPECT_TRUE(AfterLoopEnv.proves(A.makeNot(AfterLoopBarVal)));
4612       });
4613 }
4614 
4615 TEST(TransferTest, ForStmtBranchExtendsFlowCondition) {
4616   std::string Code = R"(
4617     void target(bool Foo) {
4618       for (; Foo;) {
4619         (void)0;
4620         // [[loop_body]]
4621       }
4622       (void)0;
4623       // [[after_loop]]
4624     }
4625   )";
4626   runDataflow(
4627       Code,
4628       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4629          ASTContext &ASTCtx) {
4630         ASSERT_THAT(Results.keys(),
4631                     UnorderedElementsAre("loop_body", "after_loop"));
4632         const Environment &LoopBodyEnv =
4633             getEnvironmentAtAnnotation(Results, "loop_body");
4634         const Environment &AfterLoopEnv =
4635             getEnvironmentAtAnnotation(Results, "after_loop");
4636 
4637         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4638         ASSERT_THAT(FooDecl, NotNull());
4639 
4640         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4641         EXPECT_TRUE(LoopBodyEnv.proves(LoopBodyFooVal));
4642 
4643         auto &AfterLoopFooVal = getFormula(*FooDecl, AfterLoopEnv);
4644         EXPECT_TRUE(
4645             AfterLoopEnv.proves(AfterLoopEnv.arena().makeNot(AfterLoopFooVal)));
4646       });
4647 }
4648 
4649 TEST(TransferTest, ForStmtBranchWithoutConditionDoesNotExtendFlowCondition) {
4650   std::string Code = R"(
4651     void target(bool Foo) {
4652       for (;;) {
4653         (void)0;
4654         // [[loop_body]]
4655       }
4656     }
4657   )";
4658   runDataflow(
4659       Code,
4660       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4661          ASTContext &ASTCtx) {
4662         ASSERT_THAT(Results.keys(), UnorderedElementsAre("loop_body"));
4663         const Environment &LoopBodyEnv =
4664             getEnvironmentAtAnnotation(Results, "loop_body");
4665 
4666         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4667         ASSERT_THAT(FooDecl, NotNull());
4668 
4669         auto &LoopBodyFooVal= getFormula(*FooDecl, LoopBodyEnv);
4670         EXPECT_FALSE(LoopBodyEnv.proves(LoopBodyFooVal));
4671       });
4672 }
4673 
4674 TEST(TransferTest, ContextSensitiveOptionDisabled) {
4675   std::string Code = R"(
4676     bool GiveBool();
4677     void SetBool(bool &Var) { Var = true; }
4678 
4679     void target() {
4680       bool Foo = GiveBool();
4681       SetBool(Foo);
4682       // [[p]]
4683     }
4684   )";
4685   runDataflow(
4686       Code,
4687       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4688          ASTContext &ASTCtx) {
4689         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4690         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4691 
4692         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4693         ASSERT_THAT(FooDecl, NotNull());
4694 
4695         auto &FooVal = getFormula(*FooDecl, Env);
4696         EXPECT_FALSE(Env.proves(FooVal));
4697         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
4698       },
4699       {BuiltinOptions{/*.ContextSensitiveOpts=*/std::nullopt}});
4700 }
4701 
4702 TEST(TransferTest, ContextSensitiveReturnReference) {
4703   std::string Code = R"(
4704     class S {};
4705     S& target(bool b, S &s) {
4706       return s;
4707       // [[p]]
4708     }
4709   )";
4710   runDataflow(
4711       Code,
4712       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4713          ASTContext &ASTCtx) {
4714         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4715 
4716         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4717         ASSERT_THAT(SDecl, NotNull());
4718 
4719         auto *SLoc = Env.getStorageLocation(*SDecl);
4720         ASSERT_THAT(SLoc, NotNull());
4721 
4722         ASSERT_THAT(Env.getReturnStorageLocation(), Eq(SLoc));
4723       },
4724       {BuiltinOptions{ContextSensitiveOptions{}}});
4725 }
4726 
4727 // This test is a regression test, based on a real crash.
4728 TEST(TransferTest, ContextSensitiveReturnReferenceWithConditionalOperator) {
4729   std::string Code = R"(
4730     class S {};
4731     S& target(bool b, S &s) {
4732       return b ? s : s;
4733       // [[p]]
4734     }
4735   )";
4736   runDataflow(
4737       Code,
4738       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4739          ASTContext &ASTCtx) {
4740         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4741         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4742 
4743         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
4744         ASSERT_THAT(SDecl, NotNull());
4745 
4746         auto *SLoc = Env.getStorageLocation(*SDecl);
4747         ASSERT_THAT(SLoc, NotNull());
4748         EXPECT_THAT(Env.getValue(*SLoc), NotNull());
4749 
4750         auto *Loc = Env.getReturnStorageLocation();
4751         ASSERT_THAT(Loc, NotNull());
4752         EXPECT_THAT(Env.getValue(*Loc), NotNull());
4753 
4754         // TODO: We would really like to make this stronger assertion, but that
4755         // doesn't work because we don't propagate values correctly through
4756         // the conditional operator yet.
4757         // ASSERT_THAT(Loc, Eq(SLoc));
4758       },
4759       {BuiltinOptions{ContextSensitiveOptions{}}});
4760 }
4761 
4762 TEST(TransferTest, ContextSensitiveReturnOneOfTwoReferences) {
4763   std::string Code = R"(
4764     class S {};
4765     S &callee(bool b, S &s1_parm, S &s2_parm) {
4766       if (b)
4767         return s1_parm;
4768       else
4769         return s2_parm;
4770     }
4771     void target(bool b) {
4772       S s1;
4773       S s2;
4774       S &return_s1 = s1;
4775       S &return_s2 = s2;
4776       S &return_dont_know = callee(b, s1, s2);
4777       // [[p]]
4778     }
4779   )";
4780   runDataflow(
4781       Code,
4782       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4783          ASTContext &ASTCtx) {
4784         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4785 
4786         const ValueDecl *S1 = findValueDecl(ASTCtx, "s1");
4787         ASSERT_THAT(S1, NotNull());
4788         const ValueDecl *S2 = findValueDecl(ASTCtx, "s2");
4789         ASSERT_THAT(S2, NotNull());
4790         const ValueDecl *ReturnS1 = findValueDecl(ASTCtx, "return_s1");
4791         ASSERT_THAT(ReturnS1, NotNull());
4792         const ValueDecl *ReturnS2 = findValueDecl(ASTCtx, "return_s2");
4793         ASSERT_THAT(ReturnS2, NotNull());
4794         const ValueDecl *ReturnDontKnow =
4795             findValueDecl(ASTCtx, "return_dont_know");
4796         ASSERT_THAT(ReturnDontKnow, NotNull());
4797 
4798         StorageLocation *S1Loc = Env.getStorageLocation(*S1);
4799         StorageLocation *S2Loc = Env.getStorageLocation(*S2);
4800 
4801         EXPECT_THAT(Env.getStorageLocation(*ReturnS1), Eq(S1Loc));
4802         EXPECT_THAT(Env.getStorageLocation(*ReturnS2), Eq(S2Loc));
4803 
4804         // In the case where we don't have a consistent storage location for
4805         // the return value, the framework creates a new storage location, which
4806         // should be different from the storage locations of `s1` and `s2`.
4807         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S1Loc));
4808         EXPECT_THAT(Env.getStorageLocation(*ReturnDontKnow), Ne(S2Loc));
4809       },
4810       {BuiltinOptions{ContextSensitiveOptions{}}});
4811 }
4812 
4813 TEST(TransferTest, ContextSensitiveDepthZero) {
4814   std::string Code = R"(
4815     bool GiveBool();
4816     void SetBool(bool &Var) { Var = true; }
4817 
4818     void target() {
4819       bool Foo = GiveBool();
4820       SetBool(Foo);
4821       // [[p]]
4822     }
4823   )";
4824   runDataflow(
4825       Code,
4826       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4827          ASTContext &ASTCtx) {
4828         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4829         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4830 
4831         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4832         ASSERT_THAT(FooDecl, NotNull());
4833 
4834         auto &FooVal = getFormula(*FooDecl, Env);
4835         EXPECT_FALSE(Env.proves(FooVal));
4836         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
4837       },
4838       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/0}}});
4839 }
4840 
4841 TEST(TransferTest, ContextSensitiveSetTrue) {
4842   std::string Code = R"(
4843     bool GiveBool();
4844     void SetBool(bool &Var) { Var = true; }
4845 
4846     void target() {
4847       bool Foo = GiveBool();
4848       SetBool(Foo);
4849       // [[p]]
4850     }
4851   )";
4852   runDataflow(
4853       Code,
4854       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4855          ASTContext &ASTCtx) {
4856         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4857         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4858 
4859         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4860         ASSERT_THAT(FooDecl, NotNull());
4861 
4862         auto &FooVal = getFormula(*FooDecl, Env);
4863         EXPECT_TRUE(Env.proves(FooVal));
4864       },
4865       {BuiltinOptions{ContextSensitiveOptions{}}});
4866 }
4867 
4868 TEST(TransferTest, ContextSensitiveSetFalse) {
4869   std::string Code = R"(
4870     bool GiveBool();
4871     void SetBool(bool &Var) { Var = false; }
4872 
4873     void target() {
4874       bool Foo = GiveBool();
4875       SetBool(Foo);
4876       // [[p]]
4877     }
4878   )";
4879   runDataflow(
4880       Code,
4881       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4882          ASTContext &ASTCtx) {
4883         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4884         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4885 
4886         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4887         ASSERT_THAT(FooDecl, NotNull());
4888 
4889         auto &FooVal = getFormula(*FooDecl, Env);
4890         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
4891       },
4892       {BuiltinOptions{ContextSensitiveOptions{}}});
4893 }
4894 
4895 TEST(TransferTest, ContextSensitiveSetBothTrueAndFalse) {
4896   std::string Code = R"(
4897     bool GiveBool();
4898     void SetBool(bool &Var, bool Val) { Var = Val; }
4899 
4900     void target() {
4901       bool Foo = GiveBool();
4902       bool Bar = GiveBool();
4903       SetBool(Foo, true);
4904       SetBool(Bar, false);
4905       // [[p]]
4906     }
4907   )";
4908   runDataflow(
4909       Code,
4910       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4911          ASTContext &ASTCtx) {
4912         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4913         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4914         auto &A = Env.arena();
4915 
4916         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4917         ASSERT_THAT(FooDecl, NotNull());
4918 
4919         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
4920         ASSERT_THAT(BarDecl, NotNull());
4921 
4922         auto &FooVal = getFormula(*FooDecl, Env);
4923         EXPECT_TRUE(Env.proves(FooVal));
4924         EXPECT_FALSE(Env.proves(A.makeNot(FooVal)));
4925 
4926         auto &BarVal = getFormula(*BarDecl, Env);
4927         EXPECT_FALSE(Env.proves(BarVal));
4928         EXPECT_TRUE(Env.proves(A.makeNot(BarVal)));
4929       },
4930       {BuiltinOptions{ContextSensitiveOptions{}}});
4931 }
4932 
4933 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthOne) {
4934   std::string Code = R"(
4935     bool GiveBool();
4936     void SetBool1(bool &Var) { Var = true; }
4937     void SetBool2(bool &Var) { SetBool1(Var); }
4938 
4939     void target() {
4940       bool Foo = GiveBool();
4941       SetBool2(Foo);
4942       // [[p]]
4943     }
4944   )";
4945   runDataflow(
4946       Code,
4947       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4948          ASTContext &ASTCtx) {
4949         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4950         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4951 
4952         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4953         ASSERT_THAT(FooDecl, NotNull());
4954 
4955         auto &FooVal = getFormula(*FooDecl, Env);
4956         EXPECT_FALSE(Env.proves(FooVal));
4957         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
4958       },
4959       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/1}}});
4960 }
4961 
4962 TEST(TransferTest, ContextSensitiveSetTwoLayersDepthTwo) {
4963   std::string Code = R"(
4964     bool GiveBool();
4965     void SetBool1(bool &Var) { Var = true; }
4966     void SetBool2(bool &Var) { SetBool1(Var); }
4967 
4968     void target() {
4969       bool Foo = GiveBool();
4970       SetBool2(Foo);
4971       // [[p]]
4972     }
4973   )";
4974   runDataflow(
4975       Code,
4976       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
4977          ASTContext &ASTCtx) {
4978         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
4979         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
4980 
4981         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
4982         ASSERT_THAT(FooDecl, NotNull());
4983 
4984         auto &FooVal = getFormula(*FooDecl, Env);
4985         EXPECT_TRUE(Env.proves(FooVal));
4986       },
4987       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
4988 }
4989 
4990 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthTwo) {
4991   std::string Code = R"(
4992     bool GiveBool();
4993     void SetBool1(bool &Var) { Var = true; }
4994     void SetBool2(bool &Var) { SetBool1(Var); }
4995     void SetBool3(bool &Var) { SetBool2(Var); }
4996 
4997     void target() {
4998       bool Foo = GiveBool();
4999       SetBool3(Foo);
5000       // [[p]]
5001     }
5002   )";
5003   runDataflow(
5004       Code,
5005       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5006          ASTContext &ASTCtx) {
5007         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5008         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5009 
5010         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5011         ASSERT_THAT(FooDecl, NotNull());
5012 
5013         auto &FooVal = getFormula(*FooDecl, Env);
5014         EXPECT_FALSE(Env.proves(FooVal));
5015         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5016       },
5017       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/2}}});
5018 }
5019 
5020 TEST(TransferTest, ContextSensitiveSetThreeLayersDepthThree) {
5021   std::string Code = R"(
5022     bool GiveBool();
5023     void SetBool1(bool &Var) { Var = true; }
5024     void SetBool2(bool &Var) { SetBool1(Var); }
5025     void SetBool3(bool &Var) { SetBool2(Var); }
5026 
5027     void target() {
5028       bool Foo = GiveBool();
5029       SetBool3(Foo);
5030       // [[p]]
5031     }
5032   )";
5033   runDataflow(
5034       Code,
5035       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5036          ASTContext &ASTCtx) {
5037         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5038         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5039 
5040         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5041         ASSERT_THAT(FooDecl, NotNull());
5042 
5043         auto &FooVal = getFormula(*FooDecl, Env);
5044         EXPECT_TRUE(Env.proves(FooVal));
5045       },
5046       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/3}}});
5047 }
5048 
5049 TEST(TransferTest, ContextSensitiveMutualRecursion) {
5050   std::string Code = R"(
5051     bool Pong(bool X, bool Y);
5052 
5053     bool Ping(bool X, bool Y) {
5054       if (X) {
5055         return Y;
5056       } else {
5057         return Pong(!X, Y);
5058       }
5059     }
5060 
5061     bool Pong(bool X, bool Y) {
5062       if (Y) {
5063         return X;
5064       } else {
5065         return Ping(X, !Y);
5066       }
5067     }
5068 
5069     void target() {
5070       bool Foo = Ping(false, false);
5071       // [[p]]
5072     }
5073   )";
5074   runDataflow(
5075       Code,
5076       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5077          ASTContext &ASTCtx) {
5078         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5079         // The analysis doesn't crash...
5080         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5081 
5082         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5083         ASSERT_THAT(FooDecl, NotNull());
5084 
5085         auto &FooVal = getFormula(*FooDecl, Env);
5086         // ... but it also can't prove anything here.
5087         EXPECT_FALSE(Env.proves(FooVal));
5088         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5089       },
5090       {BuiltinOptions{ContextSensitiveOptions{/*.Depth=*/4}}});
5091 }
5092 
5093 TEST(TransferTest, ContextSensitiveSetMultipleLines) {
5094   std::string Code = R"(
5095     void SetBools(bool &Var1, bool &Var2) {
5096       Var1 = true;
5097       Var2 = false;
5098     }
5099 
5100     void target() {
5101       bool Foo = false;
5102       bool Bar = true;
5103       SetBools(Foo, Bar);
5104       // [[p]]
5105     }
5106   )";
5107   runDataflow(
5108       Code,
5109       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5110          ASTContext &ASTCtx) {
5111         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5112         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5113 
5114         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5115         ASSERT_THAT(FooDecl, NotNull());
5116 
5117         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5118         ASSERT_THAT(BarDecl, NotNull());
5119 
5120         auto &FooVal = getFormula(*FooDecl, Env);
5121         EXPECT_TRUE(Env.proves(FooVal));
5122         EXPECT_FALSE(Env.proves(Env.arena().makeNot(FooVal)));
5123 
5124         auto &BarVal = getFormula(*BarDecl, Env);
5125         EXPECT_FALSE(Env.proves(BarVal));
5126         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5127       },
5128       {BuiltinOptions{ContextSensitiveOptions{}}});
5129 }
5130 
5131 TEST(TransferTest, ContextSensitiveSetMultipleBlocks) {
5132   std::string Code = R"(
5133     void IfCond(bool Cond, bool &Then, bool &Else) {
5134       if (Cond) {
5135         Then = true;
5136       } else {
5137         Else = true;
5138       }
5139     }
5140 
5141     void target() {
5142       bool Foo = false;
5143       bool Bar = false;
5144       bool Baz = false;
5145       IfCond(Foo, Bar, Baz);
5146       // [[p]]
5147     }
5148   )";
5149   runDataflow(
5150       Code,
5151       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5152          ASTContext &ASTCtx) {
5153         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5154         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5155 
5156         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
5157         ASSERT_THAT(BarDecl, NotNull());
5158 
5159         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5160         ASSERT_THAT(BazDecl, NotNull());
5161 
5162         auto &BarVal = getFormula(*BarDecl, Env);
5163         EXPECT_FALSE(Env.proves(BarVal));
5164         EXPECT_TRUE(Env.proves(Env.arena().makeNot(BarVal)));
5165 
5166         auto &BazVal = getFormula(*BazDecl, Env);
5167         EXPECT_TRUE(Env.proves(BazVal));
5168         EXPECT_FALSE(Env.proves(Env.arena().makeNot(BazVal)));
5169       },
5170       {BuiltinOptions{ContextSensitiveOptions{}}});
5171 }
5172 
5173 TEST(TransferTest, ContextSensitiveReturnVoid) {
5174   std::string Code = R"(
5175     void Noop() { return; }
5176 
5177     void target() {
5178       Noop();
5179       // [[p]]
5180     }
5181   )";
5182   runDataflow(
5183       Code,
5184       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5185          ASTContext &ASTCtx) {
5186         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5187         // This just tests that the analysis doesn't crash.
5188       },
5189       {BuiltinOptions{ContextSensitiveOptions{}}});
5190 }
5191 
5192 TEST(TransferTest, ContextSensitiveReturnTrue) {
5193   std::string Code = R"(
5194     bool GiveBool() { return true; }
5195 
5196     void target() {
5197       bool Foo = GiveBool();
5198       // [[p]]
5199     }
5200   )";
5201   runDataflow(
5202       Code,
5203       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5204          ASTContext &ASTCtx) {
5205         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5206         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5207 
5208         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5209         ASSERT_THAT(FooDecl, NotNull());
5210 
5211         auto &FooVal = getFormula(*FooDecl, Env);
5212         EXPECT_TRUE(Env.proves(FooVal));
5213       },
5214       {BuiltinOptions{ContextSensitiveOptions{}}});
5215 }
5216 
5217 TEST(TransferTest, ContextSensitiveReturnFalse) {
5218   std::string Code = R"(
5219     bool GiveBool() { return false; }
5220 
5221     void target() {
5222       bool Foo = GiveBool();
5223       // [[p]]
5224     }
5225   )";
5226   runDataflow(
5227       Code,
5228       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5229          ASTContext &ASTCtx) {
5230         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5231         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5232 
5233         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5234         ASSERT_THAT(FooDecl, NotNull());
5235 
5236         auto &FooVal = getFormula(*FooDecl, Env);
5237         EXPECT_TRUE(Env.proves(Env.arena().makeNot(FooVal)));
5238       },
5239       {BuiltinOptions{ContextSensitiveOptions{}}});
5240 }
5241 
5242 TEST(TransferTest, ContextSensitiveReturnArg) {
5243   std::string Code = R"(
5244     bool GiveBool();
5245     bool GiveBack(bool Arg) { return Arg; }
5246 
5247     void target() {
5248       bool Foo = GiveBool();
5249       bool Bar = GiveBack(Foo);
5250       bool Baz = Foo == Bar;
5251       // [[p]]
5252     }
5253   )";
5254   runDataflow(
5255       Code,
5256       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5257          ASTContext &ASTCtx) {
5258         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5259         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5260 
5261         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
5262         ASSERT_THAT(BazDecl, NotNull());
5263 
5264         auto &BazVal = getFormula(*BazDecl, Env);
5265         EXPECT_TRUE(Env.proves(BazVal));
5266       },
5267       {BuiltinOptions{ContextSensitiveOptions{}}});
5268 }
5269 
5270 TEST(TransferTest, ContextSensitiveReturnInt) {
5271   std::string Code = R"(
5272     int identity(int x) { return x; }
5273 
5274     void target() {
5275       int y = identity(42);
5276       // [[p]]
5277     }
5278   )";
5279   runDataflow(
5280       Code,
5281       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5282          ASTContext &ASTCtx) {
5283         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5284         // This just tests that the analysis doesn't crash.
5285       },
5286       {BuiltinOptions{ContextSensitiveOptions{}}});
5287 }
5288 
5289 TEST(TransferTest, ContextSensitiveMethodLiteral) {
5290   std::string Code = R"(
5291     class MyClass {
5292     public:
5293       bool giveBool() { return true; }
5294     };
5295 
5296     void target() {
5297       MyClass MyObj;
5298       bool Foo = MyObj.giveBool();
5299       // [[p]]
5300     }
5301   )";
5302   runDataflow(
5303       Code,
5304       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5305          ASTContext &ASTCtx) {
5306         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5307         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5308 
5309         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5310         ASSERT_THAT(FooDecl, NotNull());
5311 
5312         auto &FooVal = getFormula(*FooDecl, Env);
5313         EXPECT_TRUE(Env.proves(FooVal));
5314       },
5315       {BuiltinOptions{ContextSensitiveOptions{}}});
5316 }
5317 
5318 TEST(TransferTest, ContextSensitiveMethodGetter) {
5319   std::string Code = R"(
5320     class MyClass {
5321     public:
5322       bool getField() { return Field; }
5323 
5324       bool Field;
5325     };
5326 
5327     void target() {
5328       MyClass MyObj;
5329       MyObj.Field = true;
5330       bool Foo = MyObj.getField();
5331       // [[p]]
5332     }
5333   )";
5334   runDataflow(
5335       Code,
5336       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5337          ASTContext &ASTCtx) {
5338         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5339         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5340 
5341         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5342         ASSERT_THAT(FooDecl, NotNull());
5343 
5344         auto &FooVal = getFormula(*FooDecl, Env);
5345         EXPECT_TRUE(Env.proves(FooVal));
5346       },
5347       {BuiltinOptions{ContextSensitiveOptions{}}});
5348 }
5349 
5350 TEST(TransferTest, ContextSensitiveMethodSetter) {
5351   std::string Code = R"(
5352     class MyClass {
5353     public:
5354       void setField(bool Val) { Field = Val; }
5355 
5356       bool Field;
5357     };
5358 
5359     void target() {
5360       MyClass MyObj;
5361       MyObj.setField(true);
5362       bool Foo = MyObj.Field;
5363       // [[p]]
5364     }
5365   )";
5366   runDataflow(
5367       Code,
5368       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5369          ASTContext &ASTCtx) {
5370         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5371         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5372 
5373         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5374         ASSERT_THAT(FooDecl, NotNull());
5375 
5376         auto &FooVal = getFormula(*FooDecl, Env);
5377         EXPECT_TRUE(Env.proves(FooVal));
5378       },
5379       {BuiltinOptions{ContextSensitiveOptions{}}});
5380 }
5381 
5382 TEST(TransferTest, ContextSensitiveMethodGetterAndSetter) {
5383   std::string Code = R"(
5384     class MyClass {
5385     public:
5386       bool getField() { return Field; }
5387       void setField(bool Val) { Field = Val; }
5388 
5389     private:
5390       bool Field;
5391     };
5392 
5393     void target() {
5394       MyClass MyObj;
5395       MyObj.setField(true);
5396       bool Foo = MyObj.getField();
5397       // [[p]]
5398     }
5399   )";
5400   runDataflow(
5401       Code,
5402       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5403          ASTContext &ASTCtx) {
5404         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5405         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5406 
5407         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5408         ASSERT_THAT(FooDecl, NotNull());
5409 
5410         auto &FooVal = getFormula(*FooDecl, Env);
5411         EXPECT_TRUE(Env.proves(FooVal));
5412       },
5413       {BuiltinOptions{ContextSensitiveOptions{}}});
5414 }
5415 
5416 
5417 TEST(TransferTest, ContextSensitiveMethodTwoLayersVoid) {
5418   std::string Code = R"(
5419     class MyClass {
5420     public:
5421       void Inner() { MyField = true; }
5422       void Outer() { Inner(); }
5423 
5424       bool MyField;
5425     };
5426 
5427     void target() {
5428       MyClass MyObj;
5429       MyObj.Outer();
5430       bool Foo = MyObj.MyField;
5431       // [[p]]
5432     }
5433   )";
5434   runDataflow(
5435       Code,
5436       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5437          ASTContext &ASTCtx) {
5438         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5439         ;
5440         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5441 
5442         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5443         ASSERT_THAT(FooDecl, NotNull());
5444 
5445         auto &FooVal = getFormula(*FooDecl, Env);
5446         EXPECT_TRUE(Env.proves(FooVal));
5447       },
5448       {BuiltinOptions{ContextSensitiveOptions{}}});
5449 }
5450 
5451 TEST(TransferTest, ContextSensitiveMethodTwoLayersReturn) {
5452   std::string Code = R"(
5453     class MyClass {
5454     public:
5455       bool Inner() { return MyField; }
5456       bool Outer() { return Inner(); }
5457 
5458       bool MyField;
5459     };
5460 
5461     void target() {
5462       MyClass MyObj;
5463       MyObj.MyField = true;
5464       bool Foo = MyObj.Outer();
5465       // [[p]]
5466     }
5467   )";
5468   runDataflow(
5469       Code,
5470       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5471          ASTContext &ASTCtx) {
5472         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5473         ;
5474         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5475 
5476         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5477         ASSERT_THAT(FooDecl, NotNull());
5478 
5479         auto &FooVal = getFormula(*FooDecl, Env);
5480         EXPECT_TRUE(Env.proves(FooVal));
5481       },
5482       {BuiltinOptions{ContextSensitiveOptions{}}});
5483 }
5484 
5485 TEST(TransferTest, ContextSensitiveConstructorBody) {
5486   std::string Code = R"(
5487     class MyClass {
5488     public:
5489       MyClass() { MyField = true; }
5490 
5491       bool MyField;
5492     };
5493 
5494     void target() {
5495       MyClass MyObj;
5496       bool Foo = MyObj.MyField;
5497       // [[p]]
5498     }
5499   )";
5500   runDataflow(
5501       Code,
5502       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5503          ASTContext &ASTCtx) {
5504         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5505         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5506 
5507         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5508         ASSERT_THAT(FooDecl, NotNull());
5509 
5510         auto &FooVal = getFormula(*FooDecl, Env);
5511         EXPECT_TRUE(Env.proves(FooVal));
5512       },
5513       {BuiltinOptions{ContextSensitiveOptions{}}});
5514 }
5515 
5516 TEST(TransferTest, ContextSensitiveConstructorInitializer) {
5517   std::string Code = R"(
5518     class MyClass {
5519     public:
5520       MyClass() : MyField(true) {}
5521 
5522       bool MyField;
5523     };
5524 
5525     void target() {
5526       MyClass MyObj;
5527       bool Foo = MyObj.MyField;
5528       // [[p]]
5529     }
5530   )";
5531   runDataflow(
5532       Code,
5533       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5534          ASTContext &ASTCtx) {
5535         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5536         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5537 
5538         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5539         ASSERT_THAT(FooDecl, NotNull());
5540 
5541         auto &FooVal = getFormula(*FooDecl, Env);
5542         EXPECT_TRUE(Env.proves(FooVal));
5543       },
5544       {BuiltinOptions{ContextSensitiveOptions{}}});
5545 }
5546 
5547 TEST(TransferTest, ContextSensitiveConstructorDefault) {
5548   std::string Code = R"(
5549     class MyClass {
5550     public:
5551       MyClass() = default;
5552 
5553       bool MyField = true;
5554     };
5555 
5556     void target() {
5557       MyClass MyObj;
5558       bool Foo = MyObj.MyField;
5559       // [[p]]
5560     }
5561   )";
5562   runDataflow(
5563       Code,
5564       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5565          ASTContext &ASTCtx) {
5566         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5567         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5568 
5569         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
5570         ASSERT_THAT(FooDecl, NotNull());
5571 
5572         auto &FooVal = getFormula(*FooDecl, Env);
5573         EXPECT_TRUE(Env.proves(FooVal));
5574       },
5575       {BuiltinOptions{ContextSensitiveOptions{}}});
5576 }
5577 
5578 TEST(TransferTest, ContextSensitiveSelfReferentialClass) {
5579   // Test that the `this` pointer seen in the constructor has the same value
5580   // as the address of the variable the object is constructed into.
5581   std::string Code = R"(
5582     class MyClass {
5583     public:
5584       MyClass() : Self(this) {}
5585       MyClass *Self;
5586     };
5587 
5588     void target() {
5589       MyClass MyObj;
5590       MyClass *SelfPtr = MyObj.Self;
5591       // [[p]]
5592     }
5593   )";
5594   runDataflow(
5595       Code,
5596       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5597          ASTContext &ASTCtx) {
5598         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5599 
5600         const ValueDecl *MyObjDecl = findValueDecl(ASTCtx, "MyObj");
5601         ASSERT_THAT(MyObjDecl, NotNull());
5602 
5603         const ValueDecl *SelfDecl = findValueDecl(ASTCtx, "SelfPtr");
5604         ASSERT_THAT(SelfDecl, NotNull());
5605 
5606         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5607         auto &SelfVal = *cast<PointerValue>(Env.getValue(*SelfDecl));
5608         EXPECT_EQ(Env.getStorageLocation(*MyObjDecl), &SelfVal.getPointeeLoc());
5609       },
5610       {BuiltinOptions{ContextSensitiveOptions{}}});
5611 }
5612 
5613 TEST(TransferTest, UnnamedBitfieldInitializer) {
5614   std::string Code = R"(
5615     struct B {};
5616     struct A {
5617       unsigned a;
5618       unsigned : 4;
5619       unsigned c;
5620       B b;
5621     };
5622     void target() {
5623       A a = {};
5624       A test = a;
5625       (void)test.c;
5626     }
5627   )";
5628   runDataflow(
5629       Code,
5630       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5631          ASTContext &ASTCtx) {
5632         // This doesn't need a body because this test was crashing the framework
5633         // before handling correctly Unnamed bitfields in `InitListExpr`.
5634       });
5635 }
5636 
5637 // Repro for a crash that used to occur with chained short-circuiting logical
5638 // operators.
5639 TEST(TransferTest, ChainedLogicalOps) {
5640   std::string Code = R"(
5641     bool target() {
5642       bool b = true || false || false || false;
5643       // [[p]]
5644       return b;
5645     }
5646   )";
5647   runDataflow(
5648       Code,
5649       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5650          ASTContext &ASTCtx) {
5651         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5652         auto &B = getValueForDecl<BoolValue>(ASTCtx, Env, "b").formula();
5653         EXPECT_TRUE(Env.proves(B));
5654       });
5655 }
5656 
5657 // Repro for a crash that used to occur when we call a `noreturn` function
5658 // within one of the operands of a `&&` or `||` operator.
5659 TEST(TransferTest, NoReturnFunctionInsideShortCircuitedBooleanOp) {
5660   std::string Code = R"(
5661     __attribute__((noreturn)) int doesnt_return();
5662     bool some_condition();
5663     void target(bool b1, bool b2) {
5664       // Neither of these should crash. In addition, if we don't terminate the
5665       // program, we know that the operators need to trigger the short-circuit
5666       // logic, so `NoreturnOnRhsOfAnd` will be false and `NoreturnOnRhsOfOr`
5667       // will be true.
5668       bool NoreturnOnRhsOfAnd = b1 && doesnt_return() > 0;
5669       bool NoreturnOnRhsOfOr = b2 || doesnt_return() > 0;
5670 
5671       // Calling a `noreturn` function on the LHS of an `&&` or `||` makes the
5672       // entire expression unreachable. So we know that in both of the following
5673       // cases, if `target()` terminates, the `else` branch was taken.
5674       bool NoreturnOnLhsMakesAndUnreachable = false;
5675       if (some_condition())
5676          doesnt_return() > 0 && some_condition();
5677       else
5678          NoreturnOnLhsMakesAndUnreachable = true;
5679 
5680       bool NoreturnOnLhsMakesOrUnreachable = false;
5681       if (some_condition())
5682          doesnt_return() > 0 || some_condition();
5683       else
5684          NoreturnOnLhsMakesOrUnreachable = true;
5685 
5686       // [[p]]
5687     }
5688   )";
5689   runDataflow(
5690       Code,
5691       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5692          ASTContext &ASTCtx) {
5693         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
5694         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5695         auto &A = Env.arena();
5696 
5697         // Check that [[p]] is reachable with a non-false flow condition.
5698         EXPECT_FALSE(Env.proves(A.makeLiteral(false)));
5699 
5700         auto &B1 = getValueForDecl<BoolValue>(ASTCtx, Env, "b1").formula();
5701         EXPECT_TRUE(Env.proves(A.makeNot(B1)));
5702 
5703         auto &NoreturnOnRhsOfAnd =
5704             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfAnd").formula();
5705         EXPECT_TRUE(Env.proves(A.makeNot(NoreturnOnRhsOfAnd)));
5706 
5707         auto &B2 = getValueForDecl<BoolValue>(ASTCtx, Env, "b2").formula();
5708         EXPECT_TRUE(Env.proves(B2));
5709 
5710         auto &NoreturnOnRhsOfOr =
5711             getValueForDecl<BoolValue>(ASTCtx, Env, "NoreturnOnRhsOfOr")
5712                 .formula();
5713         EXPECT_TRUE(Env.proves(NoreturnOnRhsOfOr));
5714 
5715         auto &NoreturnOnLhsMakesAndUnreachable = getValueForDecl<BoolValue>(
5716             ASTCtx, Env, "NoreturnOnLhsMakesAndUnreachable").formula();
5717         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesAndUnreachable));
5718 
5719         auto &NoreturnOnLhsMakesOrUnreachable = getValueForDecl<BoolValue>(
5720             ASTCtx, Env, "NoreturnOnLhsMakesOrUnreachable").formula();
5721         EXPECT_TRUE(Env.proves(NoreturnOnLhsMakesOrUnreachable));
5722       });
5723 }
5724 
5725 TEST(TransferTest, NewExpressions) {
5726   std::string Code = R"(
5727     void target() {
5728       int *p = new int(42);
5729       // [[after_new]]
5730     }
5731   )";
5732   runDataflow(
5733       Code,
5734       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5735          ASTContext &ASTCtx) {
5736         const Environment &Env =
5737             getEnvironmentAtAnnotation(Results, "after_new");
5738 
5739         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5740 
5741         EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
5742       });
5743 }
5744 
5745 TEST(TransferTest, NewExpressions_Structs) {
5746   std::string Code = R"(
5747     struct Inner {
5748       int InnerField;
5749     };
5750 
5751     struct Outer {
5752       Inner OuterField;
5753     };
5754 
5755     void target() {
5756       Outer *p = new Outer;
5757       // Access the fields to make sure the analysis actually generates children
5758       // for them in the `RecordStorageLocation` and `RecordValue`.
5759       p->OuterField.InnerField;
5760       // [[after_new]]
5761     }
5762   )";
5763   runDataflow(
5764       Code,
5765       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5766          ASTContext &ASTCtx) {
5767         const Environment &Env =
5768             getEnvironmentAtAnnotation(Results, "after_new");
5769 
5770         const ValueDecl *OuterField = findValueDecl(ASTCtx, "OuterField");
5771         const ValueDecl *InnerField = findValueDecl(ASTCtx, "InnerField");
5772 
5773         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
5774 
5775         auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
5776         auto &OuterFieldLoc =
5777             *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
5778         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
5779 
5780         // Values for the struct and all fields exist after the new.
5781         EXPECT_THAT(Env.getValue(OuterLoc), NotNull());
5782         EXPECT_THAT(Env.getValue(OuterFieldLoc), NotNull());
5783         EXPECT_THAT(Env.getValue(InnerFieldLoc), NotNull());
5784       });
5785 }
5786 
5787 TEST(TransferTest, FunctionToPointerDecayHasValue) {
5788   std::string Code = R"(
5789     struct A { static void static_member_func(); };
5790     void target() {
5791       // To check that we're treating function-to-pointer decay correctly,
5792       // create two pointers, then verify they refer to the same storage
5793       // location.
5794       // We need to do the test this way because even if an initializer (in this
5795       // case, the function-to-pointer decay) does not create a value, we still
5796       // create a value for the variable.
5797       void (*non_member_p1)() = target;
5798       void (*non_member_p2)() = target;
5799 
5800       // Do the same thing but for a static member function.
5801       void (*member_p1)() = A::static_member_func;
5802       void (*member_p2)() = A::static_member_func;
5803       // [[p]]
5804     }
5805   )";
5806   runDataflow(
5807       Code,
5808       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5809          ASTContext &ASTCtx) {
5810         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5811 
5812         auto &NonMemberP1 =
5813             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
5814         auto &NonMemberP2 =
5815             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
5816         EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
5817 
5818         auto &MemberP1 =
5819             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
5820         auto &MemberP2 =
5821             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
5822         EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
5823       });
5824 }
5825 
5826 // Check that a builtin function is not associated with a value. (It's only
5827 // possible to call builtin functions directly, not take their address.)
5828 TEST(TransferTest, BuiltinFunctionModeled) {
5829   std::string Code = R"(
5830     void target() {
5831       __builtin_expect(0, 0);
5832       // [[p]]
5833     }
5834   )";
5835   runDataflow(
5836       Code,
5837       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5838          ASTContext &ASTCtx) {
5839         using ast_matchers::selectFirst;
5840         using ast_matchers::match;
5841         using ast_matchers::traverse;
5842         using ast_matchers::implicitCastExpr;
5843         using ast_matchers::hasCastKind;
5844 
5845         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5846 
5847         auto *ImplicitCast = selectFirst<ImplicitCastExpr>(
5848             "implicit_cast",
5849             match(traverse(TK_AsIs,
5850                            implicitCastExpr(hasCastKind(CK_BuiltinFnToFnPtr))
5851                                .bind("implicit_cast")),
5852                   ASTCtx));
5853 
5854         ASSERT_THAT(ImplicitCast, NotNull());
5855         EXPECT_THAT(Env.getValue(*ImplicitCast), IsNull());
5856       });
5857 }
5858 
5859 // Check that a callee of a member operator call is modeled as a `PointerValue`.
5860 // Member operator calls are unusual in that their callee is a pointer that
5861 // stems from a `FunctionToPointerDecay`. In calls to non-operator non-static
5862 // member functions, the callee is a `MemberExpr` (which does not have pointer
5863 // type).
5864 // We want to make sure that we produce a pointer value for the callee in this
5865 // specific scenario and that its storage location is durable (for convergence).
5866 TEST(TransferTest, MemberOperatorCallModelsPointerForCallee) {
5867   std::string Code = R"(
5868     struct S {
5869       bool operator!=(S s);
5870     };
5871     void target() {
5872       S s;
5873       (void)(s != s);
5874       (void)(s != s);
5875       // [[p]]
5876     }
5877   )";
5878   runDataflow(
5879       Code,
5880       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5881          ASTContext &ASTCtx) {
5882         using ast_matchers::selectFirst;
5883         using ast_matchers::match;
5884         using ast_matchers::traverse;
5885         using ast_matchers::cxxOperatorCallExpr;
5886 
5887         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5888 
5889         auto Matches = match(
5890             traverse(TK_AsIs, cxxOperatorCallExpr().bind("call")), ASTCtx);
5891 
5892         ASSERT_EQ(Matches.size(), 2UL);
5893 
5894         auto *Call1 = Matches[0].getNodeAs<CXXOperatorCallExpr>("call");
5895         auto *Call2 = Matches[1].getNodeAs<CXXOperatorCallExpr>("call");
5896 
5897         ASSERT_THAT(Call1, NotNull());
5898         ASSERT_THAT(Call2, NotNull());
5899 
5900         EXPECT_EQ(cast<ImplicitCastExpr>(Call1->getCallee())->getCastKind(),
5901                   CK_FunctionToPointerDecay);
5902         EXPECT_EQ(cast<ImplicitCastExpr>(Call2->getCallee())->getCastKind(),
5903                   CK_FunctionToPointerDecay);
5904 
5905         auto *Ptr1 = cast<PointerValue>(Env.getValue(*Call1->getCallee()));
5906         auto *Ptr2 = cast<PointerValue>(Env.getValue(*Call2->getCallee()));
5907 
5908         ASSERT_EQ(&Ptr1->getPointeeLoc(), &Ptr2->getPointeeLoc());
5909       });
5910 }
5911 
5912 // Check that fields of anonymous records are modeled.
5913 TEST(TransferTest, AnonymousStruct) {
5914   std::string Code = R"(
5915     struct S {
5916       struct {
5917         bool b;
5918       };
5919     };
5920     void target() {
5921       S s;
5922       s.b = true;
5923       // [[p]]
5924     }
5925   )";
5926   runDataflow(
5927       Code,
5928       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5929          ASTContext &ASTCtx) {
5930         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5931         const ValueDecl *SDecl = findValueDecl(ASTCtx, "s");
5932         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
5933         const IndirectFieldDecl *IndirectField =
5934             findIndirectFieldDecl(ASTCtx, "b");
5935 
5936         auto *S = cast<RecordStorageLocation>(Env.getStorageLocation(*SDecl));
5937         auto &AnonStruct = *cast<RecordStorageLocation>(
5938             S->getChild(*cast<ValueDecl>(IndirectField->chain().front())));
5939 
5940         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
5941         ASSERT_TRUE(Env.proves(B->formula()));
5942       });
5943 }
5944 
5945 TEST(TransferTest, AnonymousStructWithInitializer) {
5946   std::string Code = R"(
5947     struct target {
5948       target() {
5949         (void)0;
5950         // [[p]]
5951       }
5952       struct {
5953         bool b = true;
5954       };
5955     };
5956   )";
5957   runDataflow(
5958       Code,
5959       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5960          ASTContext &ASTCtx) {
5961         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5962         const ValueDecl *BDecl = findValueDecl(ASTCtx, "b");
5963         const IndirectFieldDecl *IndirectField =
5964             findIndirectFieldDecl(ASTCtx, "b");
5965 
5966         auto *ThisLoc =
5967             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
5968         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
5969             *cast<ValueDecl>(IndirectField->chain().front())));
5970 
5971         auto *B = cast<BoolValue>(getFieldValue(&AnonStruct, *BDecl, Env));
5972         ASSERT_TRUE(Env.proves(B->formula()));
5973       });
5974 }
5975 
5976 TEST(TransferTest, AnonymousStructWithReferenceField) {
5977   std::string Code = R"(
5978     int global_i = 0;
5979     struct target {
5980       target() {
5981         (void)0;
5982         // [[p]]
5983       }
5984       struct {
5985         int &i = global_i;
5986       };
5987     };
5988   )";
5989   runDataflow(
5990       Code,
5991       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
5992          ASTContext &ASTCtx) {
5993         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
5994         const ValueDecl *GlobalIDecl = findValueDecl(ASTCtx, "global_i");
5995         const ValueDecl *IDecl = findValueDecl(ASTCtx, "i");
5996         const IndirectFieldDecl *IndirectField =
5997             findIndirectFieldDecl(ASTCtx, "i");
5998 
5999         auto *ThisLoc =
6000             cast<RecordStorageLocation>(Env.getThisPointeeStorageLocation());
6001         auto &AnonStruct = *cast<RecordStorageLocation>(ThisLoc->getChild(
6002             *cast<ValueDecl>(IndirectField->chain().front())));
6003 
6004         ASSERT_EQ(AnonStruct.getChild(*IDecl),
6005                   Env.getStorageLocation(*GlobalIDecl));
6006       });
6007 }
6008 
6009 TEST(TransferTest, EvaluateBlockWithUnreachablePreds) {
6010   // This is a crash repro.
6011   // `false` block may not have been processed when we try to evaluate the `||`
6012   // after visiting `true`, because it is not necessary (and therefore the edge
6013   // is marked unreachable). Trying to get the analysis state via
6014   // `getEnvironment` for the subexpression still should not crash.
6015   std::string Code = R"(
6016     int target(int i) {
6017       if ((i < 0 && true) || false) {
6018         return 0;
6019       }
6020       return 0;
6021     }
6022   )";
6023   runDataflow(
6024       Code,
6025       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6026          ASTContext &ASTCtx) {});
6027 }
6028 
6029 TEST(TransferTest, LambdaCaptureByCopy) {
6030   std::string Code = R"(
6031     void target(int Foo, int Bar) {
6032       [Foo]() {
6033         (void)0;
6034         // [[p]]
6035       }();
6036     }
6037   )";
6038   runDataflowOnLambda(
6039       Code,
6040       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6041          ASTContext &ASTCtx) {
6042         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6043         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6044 
6045         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6046         ASSERT_THAT(FooDecl, NotNull());
6047 
6048         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6049         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6050 
6051         const Value *FooVal = Env.getValue(*FooLoc);
6052         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6053 
6054         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6055         ASSERT_THAT(BarDecl, NotNull());
6056 
6057         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6058         EXPECT_THAT(BarLoc, IsNull());
6059       });
6060 }
6061 
6062 TEST(TransferTest, LambdaCaptureByReference) {
6063   std::string Code = R"(
6064     void target(int Foo, int Bar) {
6065       [&Foo]() {
6066         (void)0;
6067         // [[p]]
6068       }();
6069     }
6070   )";
6071   runDataflowOnLambda(
6072       Code,
6073       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6074          ASTContext &ASTCtx) {
6075         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6076         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6077 
6078         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6079         ASSERT_THAT(FooDecl, NotNull());
6080 
6081         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6082         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6083 
6084         const Value *FooVal = Env.getValue(*FooLoc);
6085         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6086 
6087         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6088         ASSERT_THAT(BarDecl, NotNull());
6089 
6090         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6091         EXPECT_THAT(BarLoc, IsNull());
6092       });
6093 }
6094 
6095 TEST(TransferTest, LambdaCaptureWithInitializer) {
6096   std::string Code = R"(
6097     void target(int Bar) {
6098       [Foo=Bar]() {
6099         (void)0;
6100         // [[p]]
6101       }();
6102     }
6103   )";
6104   runDataflowOnLambda(
6105       Code,
6106       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6107          ASTContext &ASTCtx) {
6108         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6109         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6110 
6111         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6112         ASSERT_THAT(FooDecl, NotNull());
6113 
6114         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6115         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6116 
6117         const Value *FooVal = Env.getValue(*FooLoc);
6118         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6119 
6120         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6121         ASSERT_THAT(BarDecl, NotNull());
6122 
6123         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6124         EXPECT_THAT(BarLoc, IsNull());
6125       });
6126 }
6127 
6128 TEST(TransferTest, LambdaCaptureByCopyImplicit) {
6129   std::string Code = R"(
6130     void target(int Foo, int Bar) {
6131       [=]() {
6132         Foo;
6133         // [[p]]
6134       }();
6135     }
6136   )";
6137   runDataflowOnLambda(
6138       Code,
6139       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6140          ASTContext &ASTCtx) {
6141         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6142         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6143 
6144         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6145         ASSERT_THAT(FooDecl, NotNull());
6146 
6147         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6148         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6149 
6150         const Value *FooVal = Env.getValue(*FooLoc);
6151         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6152 
6153         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6154         ASSERT_THAT(BarDecl, NotNull());
6155 
6156         // There is no storage location for `Bar` because it isn't used in the
6157         // body of the lambda.
6158         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6159         EXPECT_THAT(BarLoc, IsNull());
6160       });
6161 }
6162 
6163 TEST(TransferTest, LambdaCaptureByReferenceImplicit) {
6164   std::string Code = R"(
6165     void target(int Foo, int Bar) {
6166       [&]() {
6167         Foo;
6168         // [[p]]
6169       }();
6170     }
6171   )";
6172   runDataflowOnLambda(
6173       Code,
6174       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6175          ASTContext &ASTCtx) {
6176         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6177         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6178 
6179         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6180         ASSERT_THAT(FooDecl, NotNull());
6181 
6182         const StorageLocation *FooLoc = Env.getStorageLocation(*FooDecl);
6183         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6184 
6185         const Value *FooVal = Env.getValue(*FooLoc);
6186         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6187 
6188         const ValueDecl *BarDecl = findValueDecl(ASTCtx, "Bar");
6189         ASSERT_THAT(BarDecl, NotNull());
6190 
6191         // There is no storage location for `Bar` because it isn't used in the
6192         // body of the lambda.
6193         const StorageLocation *BarLoc = Env.getStorageLocation(*BarDecl);
6194         EXPECT_THAT(BarLoc, IsNull());
6195       });
6196 }
6197 
6198 TEST(TransferTest, LambdaCaptureThis) {
6199   std::string Code = R"(
6200     struct Bar {
6201       int Foo;
6202 
6203       void target() {
6204         [this]() {
6205           Foo;
6206           // [[p]]
6207         }();
6208       }
6209     };
6210   )";
6211   runDataflowOnLambda(
6212       Code,
6213       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6214          ASTContext &ASTCtx) {
6215         ASSERT_THAT(Results.keys(), UnorderedElementsAre("p"));
6216         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6217 
6218         const RecordStorageLocation *ThisPointeeLoc =
6219             Env.getThisPointeeStorageLocation();
6220         ASSERT_THAT(ThisPointeeLoc, NotNull());
6221 
6222         const ValueDecl *FooDecl = findValueDecl(ASTCtx, "Foo");
6223         ASSERT_THAT(FooDecl, NotNull());
6224 
6225         const StorageLocation *FooLoc = ThisPointeeLoc->getChild(*FooDecl);
6226         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
6227 
6228         const Value *FooVal = Env.getValue(*FooLoc);
6229         EXPECT_TRUE(isa_and_nonnull<IntegerValue>(FooVal));
6230       });
6231 }
6232 
6233 TEST(TransferTest, DifferentReferenceLocInJoin) {
6234   // This test triggers a case where the storage location for a reference-type
6235   // variable is different for two states being joined. We used to believe this
6236   // could not happen and therefore had an assertion disallowing this; this test
6237   // exists to demonstrate that we can handle this condition without a failing
6238   // assertion. See also the discussion here:
6239   // https://discourse.llvm.org/t/70086/6
6240   std::string Code = R"(
6241     namespace std {
6242       template <class T> struct initializer_list {
6243         const T* begin();
6244         const T* end();
6245       };
6246     }
6247 
6248     void target(char* p, char* end) {
6249       while (p != end) {
6250         if (*p == ' ') {
6251           p++;
6252           continue;
6253         }
6254 
6255         auto && range = {1, 2};
6256         for (auto b = range.begin(), e = range.end(); b != e; ++b) {
6257         }
6258         (void)0;
6259         // [[p]]
6260       }
6261     }
6262   )";
6263   runDataflow(
6264       Code,
6265       [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
6266          ASTContext &ASTCtx) {
6267         const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
6268 
6269         // Joining environments with different storage locations for the same
6270         // declaration results in the declaration being removed from the joined
6271         // environment.
6272         const ValueDecl *VD = findValueDecl(ASTCtx, "range");
6273         ASSERT_EQ(Env.getStorageLocation(*VD), nullptr);
6274       });
6275 }
6276 
6277 } // namespace
6278